Skip to main content
RFC na prática — remoto, loopback, PKCE e refresh rotativo. Caminho rápido: Quick Start.
Este guia é para quem implementa o fluxo do zero ou com biblioteca OAuth. Visão geral: Construir um cliente. A Notifique implementa OAuth 2.1 com PKCE obrigatório em todo authorization code exchange, mais Dynamic Client Registration (DCR) em POST /oauth/register. Issuer: https://api.notifique.dev. A tela de login e consentimento fica no painel Notifique. Seu app só abre a URL de autorização no browser e trata o callback — você não constrói UI de consentimento.

Tipos de cliente

PKCE é sempre obrigatório — mesmo em clientes confidenciais.

Caminhos recomendados

Antes de codar, decida:
  1. Registro fixo vs DCR
    • Pré-registrado (painel ou POST /oauth/register uma vez) — apps web e integrações conhecidas.
    • DCR em runtime — MCP hosts e CLIs que não sabem redirect/porta antes de rodar.
  2. Remoto vs local
    • Remoto — redirect https://seuapp.com/oauth/callback, backend guarda state e code_verifier na sessão.
    • Local — loopback http://127.0.0.1:<porta>/callback, servidor temporário na máquina do usuário.

Escopos

Peça o mínimo no registro e no authorize. Escopos omitidos no DCR podem ser interpretados de forma ampla — declare explicitamente. Exemplos Notifique:
  • Só e-mail: email:send
  • WhatsApp: whatsapp:send
  • Vários: email:send contacts:read (separados por espaço, URL-encoded na query)
Lista completa: Escopos.

Encoding e endpoints

Cliente confidencial autentica token/revoke com HTTP Basic (client_id:client_secret), não repita client_id no body se usar -u. Metadados: GET /.well-known/oauth-authorization-server (RFC 8414).

Gerar PKCE e state

Antes do authorize, gere três valores:
  • code_verifier — string aleatória de alta entropia; fica só no cliente até o token.
  • code_challengeBASE64URL(SHA256(code_verifier)).
  • state — aleatório; deve voltar igual no callback (proteção CSRF).
Remoto: persista state e codeVerifier na sessão do usuário antes do redirect. Local: mantenha em memória enquanto o servidor loopback estiver ativo.

Cliente remoto pré-registrado

Redirect HTTPS fixo, ex.: https://example.com/oauth/callback. Registre como confidencial (client_secret_basic). O client_secret aparece uma vez — guarde em cofre de secrets, nunca no frontend.

Checklist do callback

Trate como falha se:
  • Faltar code
  • state não bater com o salvo
  • Vier error na query (access_denied, etc.)

URL de autorização (exemplo)

Trocar o code

Resposta:

Cliente local (loopback)

Redirect em 127.0.0.1 com porta efêmera, ex.: http://127.0.0.1:49152/oauth/callback. Registre como público (token_endpoint_auth_method: none). Faça bind em 127.0.0.1 ou [::1]não use 0.0.0.0.
Não faça prefetch de /oauth/authorize no backend e siga redirects server-side. O usuário precisa ver a tela de consentimento no browser.

DCR para CLI

Na autorização, use a porta real (http://127.0.0.1:49152/oauth/callback) se o path base foi registrado com flexibilidade de porta — host e path devem bater com o cadastro.

Abrir authorize (Node)

Callback esperado:

Token (público)

Feche o servidor loopback após sucesso ou timeout.

Refresh token rotativo

Cada refresh bem-sucedido devolve um novo refresh_token. O anterior invalida.
Serialize refresh por grant (um worker por vez). Salve o novo refresh atomicamente com o resto da resposta. Se dois workers refresharem com o mesmo token antigo, o grant inteiro pode ser revogado.
Cliente público: inclua client_id no body em vez de Basic auth.

Chamar /v1 com access token

Access token é JWT (~15 min, EdDSA). Envie como Bearer:
Validação offline opcional: chaves em GET /.well-known/jwks.json.

Revogar acesso

Revogue o refresh token — access tokens JWT não são revogados individualmente; revogar o refresh invalida o grant.
No workspace: Configurações → Equipe → Apps conectados.

Erros comuns (implementação)

Próximos passos