Webhooks

Webhooks

Receba notificações HTTP em tempo real quando eventos de autenticação ocorrerem no seu projeto. Sincronize usuários com seu banco de dados, envie e-mails de boas-vindas ou acione fluxos de trabalho sempre que usuários se cadastrarem, entrarem ou forem banidos.

O que são Webhooks?

Um webhook é um callback HTTP que seu servidor registra para receber notificações de eventos em tempo real. Em vez de consultar o Authon para verificar se um usuário foi excluído ou banido, o Authon envia proativamente uma requisição POST para sua URL no momento em que o evento ocorre.

text
Usuário excluído no dashboard do Authon
  → Authon envia POST /webhooks/authon
  → Seu servidor recebe o evento e remove o usuário do seu DB

Como os Webhooks Funcionam

Quando um evento ocorre no seu projeto Authon, a API envia uma requisição POST para o seu endpoint registrado com um payload JSON. Cada requisição inclui um cabeçalho X-Authon-Signature com um prefixo v1= — uma assinatura HMAC-SHA256 calculada sobre timestamp.body usando o seu segredo de assinatura de webhook. Sempre verifique esta assinatura antes de processar o evento.

1
Um evento ocorre no Authon (ex.: um usuário se cadastra)
2
O Authon assina o payload com HMAC-SHA256 usando seu segredo de webhook
3
O Authon envia uma requisição POST para a URL do seu endpoint
4
Seu servidor verifica a assinatura e processa o evento
5
Seu servidor responde com 2xx para confirmar o recebimento

Configurando um Webhook

  1. 1
    Acesse Dashboard → Webhooks → Adicionar Webhook
  2. 2
    Informe a URL do seu endpoint — deve ser acessível publicamente via HTTPS
  3. 3
    Selecione os eventos que deseja receber
  4. 4
    Copie o segredo de assinatura — exibido apenas uma vez, armazene-o com segurança
  5. 5
    Defina AUTHON_WEBHOOK_SECRET no ambiente do seu servidor

Tipos de Eventos

EventoGatilho
user.createdUm novo usuário conclui o cadastro
user.updatedO perfil de um usuário é atualizado
user.deletedUma conta de usuário é excluída permanentemente
user.signinUm usuário entra (e-mail ou OAuth)
user.signoutUm usuário sai
user.bannedUm usuário é banido por um administrador
user.unbannedUm usuário banido é restaurado
session.createdUma nova sessão é criada (login, atualização de token)
session.revokedUma sessão é revogada (logout, revogação pelo administrador)

Formato do Payload

Todo payload de webhook é um objeto JSON com uma estrutura consistente no nível superior. O campo data contém detalhes específicos do evento.

json
{
  "event": "user.created",
  "data": {
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "displayName": "Jane Doe",
      "emailVerified": false,
      "isBanned": false,
      "publicMetadata": null,
      "createdAt": "2026-01-15T10:30:00.000Z",
      "updatedAt": "2026-01-15T10:30:00.000Z"
    }
  },
  "timestamp": "2026-01-15T10:30:00.000Z"
}

Para eventossession.*, o campo datatambém inclui um objeto sessioncom id, ipAddress e userAgent.

Verificação de Assinatura

Cada requisição de webhook contém um cabeçalho X-Authon-Signature com o formato v1=<hex_digest>. A assinatura é calculada como HMAC-SHA256 sobre timestamp.rawBody usando seu segredo de webhook. Compare o resultado com igualdade de tempo constante.

CabeçalhoFormatoDescrição
X-Authon-Signaturev1={hmac_sha256}Assinatura HMAC-SHA256 para verificar a origem da requisição
X-Authon-TimestampISO 8601Timestamp ISO 8601 de quando o evento foi enviado
X-Authon-Eventuser.createdO tipo de evento (ex.: user.created, session.revoked)
Sempre use o buffer de corpo bruto para verificação, não uma string JSON analisada. O middleware json() do Express re-serializa o corpo, o que pode alterar espaços em branco e quebrar a assinatura.

Exemplo Node.js

routes/webhooks.ts
import { createHmac, timingSafeEqual } from "crypto";
import express from "express";

const router = express.Router();

function verifySignature(
  rawBody: Buffer,
  signature: string,
  secret: string,
  timestamp: string,
): boolean {
  const payload = `${timestamp}.${rawBody.toString()}`;
  const expected = createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  const actual = signature.replace("v1=", "");

  const expectedBuf = Buffer.from(expected, "hex");
  const actualBuf = Buffer.from(actual, "hex");

  return (
    expectedBuf.length === actualBuf.length &&
    timingSafeEqual(expectedBuf, actualBuf)
  );
}

router.post(
  "/webhooks/authon",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.headers["x-authon-signature"] as string;
    const timestamp = req.headers["x-authon-timestamp"] as string; // ISO 8601
    const eventType = req.headers["x-authon-event"] as string;
    const webhookSecret = process.env.AUTHON_WEBHOOK_SECRET!;

    if (!verifySignature(req.body, signature, webhookSecret, timestamp)) {
      return res.status(401).json({ error: "Invalid signature" });
    }

    const { event, data } = JSON.parse(req.body.toString());

    switch (eventType) {
      case "user.created":
        // Sync new user to your database
        break;
      case "user.deleted":
        // Remove user from your database
        break;
      case "user.updated":
        // Update user data
        break;
      case "user.banned":
        // Revoke app-level access
        break;
    }

    res.status(200).json({ received: true });
  }
);

export default router;

Usando o SDK

O SDK@authon/node fornece um auxiliar de verificação embutido que lida com a comparação de tempo constante para você:

ts
import { AuthonBackend } from "@authon/node";

const authon = new AuthonBackend(process.env.AUTHON_SECRET_KEY!);

router.post(
  "/webhooks/authon",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.headers["x-authon-signature"] as string;
    const timestamp = req.headers["x-authon-timestamp"] as string;

    let event: Record<string, unknown>;
    try {
      event = authon.webhooks.verify(
        req.body,
        signature,
        timestamp,
        process.env.AUTHON_WEBHOOK_SECRET!,
      );
    } catch {
      return res.status(401).json({ error: "Invalid signature" });
    }

    console.log("Verified event:", event.event);
    res.json({ received: true });
  }
);

Política de Retry

Se seu endpoint retornar um código de status não 2xx ou não responder dentro de 10 segundos, o Authon tentará reenviar a entrega com backoff exponencial. Máximo de 3 tentativas no total.

TentativaAtrasoTempo Acumulado
Inicial0s
1ª tentativa1 second~1s
2ª tentativa2 seconds~3s

Casos de Uso

Sincronize usuários com seu banco de dados
Mantenha a tabela de usuários do seu app sincronizada com o Authon. Ouça os eventos user.created, user.updated e user.deleted para espelhar alterações automaticamente.
Envie e-mails de boas-vindas
Acione um e-mail de boas-vindas ou sequência de onboarding quando user.created for disparado. Use o e-mail e o nome de exibição do usuário no payload do evento.
Aplique banimentos em tempo real
Quando user.banned for disparado, revogue imediatamente os tokens de acesso no nível do app ou entradas de cache para que o usuário não possa continuar usando seu serviço.

Melhores Práticas

Sempre verifique a assinatura
Nunca pule a verificação de assinatura. Qualquer pessoa pode enviar um POST para o seu endpoint — a verificação prova que a requisição veio do Authon.
Use análise de corpo bruto
A verificação de assinatura requer os bytes brutos exatos do corpo da requisição. Evite middleware JSON em rotas de webhook.
Responda rapidamente, processe de forma assíncrona
Retorne 200 imediatamente e processe o evento de forma assíncrona. O Authon fará retry se seu endpoint demorar mais de 10s.
Torne os handlers idempotentes
Você pode receber o mesmo evento mais de uma vez devido a retries. Use o timestamp do evento para deduplicar — armazene os eventos processados no seu DB.
Rotacione segredos periodicamente
Gere um novo segredo de assinatura no Dashboard a cada 90 dias. Atualize AUTHON_WEBHOOK_SECRET em seu deployment sem interrupção.
Authon — Plataforma universal de autenticação