Documentação

Fluxo de autorização

Cada redirect e requisição do fluxo de código de autorização, em ordem, com os parâmetros que seu projeto realmente aceita.

Um fluxo só, porque o OAuth 2.1 removeu os outros: código de autorização com PKCE. Clientes públicos e confidenciais rodam a mesma sequência; a única diferença é se um client_secret acompanha a requisição de token.

App clienteSeu projetoSua tela de consentimentoGET /oauth/authorizevalida cliente e redirect_uri302 para o seu caminho de consentimentoGET /oauth/authorizations/:idclient, scope, autoApprovedPOST …/consent { action }redirect.uri302 com code e statePOST /oauth/token { code, code_verifier }access_token, refresh_token, id_token

1. A requisição de autorização

GET /oauth/authorize
  ?client_id=…
  &redirect_uri=https://acme.example.com/callback
  &response_type=code
  &scope=openid%20email
  &state=…
  &code_challenge=…
  &code_challenge_method=S256
  &nonce=…
  &resource=…
client_idobrigatórioOptional

A aplicação registrada.

redirect_uriobrigatórioOptional

Precisa casar exatamente com um registrado para o cliente.

response_typeobrigatórioOptional

code. Não existe outro no OAuth 2.1.

scopeopcionalOptional

Separado por espaço. Omitido, cai em email.

staterecomendadoOptional

Devolvido intacto no redirect de volta. Sua defesa contra CSRF.

code_challengeobrigatórioOptional

Base64url do SHA-256 do seu verifier.

code_challenge_methodobrigatórioOptional

S256.

nonceopcionalOptional

Ecoado no ID token. Amarra o token a esta requisição.

resourceopcionalOptional

A API para a qual o token se destina, quando seu projeto protege mais de uma.

Se o Servidor OAuth estiver desligado no ambiente, este endpoint responde 403 antes de qualquer outra coisa.

2. Para onde vão os erros

É a parte que as integrações erram, e a regra vem direto da spec: onde um erro aparece depende de o redirect URI já ter sido validado ou não.

Antes da validaçãoJSON, 400Optional

client_id desconhecido, client_id ausente, redirect_uri que não casa. Não dá para redirecionar — mandar erro para um URI não verificado entregaria a um atacante um redirecionador funcional. Voltam como JSON.

Depois da validação302 para o redirect_uriOptional

Escopo não suportado, response_type inválido, consentimento negado. Esses redirecionam de volta com ?error=…&error_description=…&state=…, porque já se sabe que o cliente é dono daquele URI.

Então um cliente que só trata ?error= no callback vai perder silenciosamente a primeira classe de falhas. Trate as duas.

3. A passagem para a sua tela de consentimento

Validada a requisição, seu projeto cria uma autorização — um registro efêmero do que foi pedido — e redireciona o navegador para:

{siteUrl}{authorizationPath}?authorization_id=…

As duas metades vêm das configurações do seu projeto. O usuário agora está na sua aplicação, e a nulvless sai de cena até a sua página chamar de volta.

4. Lendo e respondendo

Sua tela de consentimento busca o que foi pedido:

GET /oauth/authorizations/:authorization_id
{
  "client": { "id": "…", "name": "Acme Analytics", "logoUri": "…", "uri": "…" },
  "scope": ["openid", "email"],
  "autoApproved": false,
  "redirect": { "uri": "…" }
}

autoApproved é true quando este usuário já concedeu exatamente esses escopos a este cliente. Não renderize nada e complete o fluxo — pedir de novo uma permissão que alguém já deu ensina as pessoas a clicarem em telas de consentimento sem ler.

Depois registre a decisão:

POST /oauth/authorizations/:authorization_id/consent
{ "action": "approve" }   // ou "deny"

De um jeito ou de outro a resposta carrega o URI para onde mandar o navegador. Em approve ele leva o código; em deny leva error=access_denied. Sua página não monta essa URL — ela redireciona para a que recebeu.

Esta requisição é autenticada

Ler e responder uma autorização exigem a sessão do usuário logado. É isso que amarra o consentimento a uma pessoa. Se sua página de consentimento é alcançável deslogado, mande o usuário para o login primeiro e traga-o de volta com o authorization_id intacto.

5. A requisição de token

POST /oauth/token
{
  "grant_type": "authorization_code",
  "code": "…",
  "redirect_uri": "https://acme.example.com/callback",
  "code_verifier": "…",
  "client_id": "…",
  "client_secret": "…"
}

O código é de uso único e vida curta. O code_verifier precisa gerar o code_challenge do passo 1 — isso é PKCE, e é o que torna um código interceptado inútil para qualquer outro.

{
  "access_token": "…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "…",
  "id_token": "…"
}

id_token aparece só quando openid estava entre os escopos.

6. Renovando

POST /oauth/token
{ "grant_type": "refresh_token", "refresh_token": "…", "client_id": "…" }

Mesmo endpoint, outro grant. O usuário não participa — que é exatamente por que refresh tokens merecem o cuidado de armazenamento que você daria a uma senha.

O que o usuário vê

Escrito assim, tudo são quatro carregamentos de página: o cliente, sua tela de consentimento, de volta ao cliente, pronto. Se sua tela for rápida e parecer com o resto do seu produto, a maioria das pessoas nem vai registrar que saiu dele.

Nesta página