Fluxos
As personas e os tokens só ganham vida dentro de um fluxo, o que a spec chama de grant type: a coreografia que leva do “quero acesso” ao token na mão. O OAuth 2.1 mantém uma lista curta de grants, cada um para uma situação. O que você vai encontrar na esmagadora maioria das vezes é o Authorization Code com PKCE; os outros cobrem serviço-a-serviço, aparelhos sem entrada de texto e a renovação de um token expirado.
Authorization Code com PKCE
Section titled “Authorization Code com PKCE”Este é o fluxo canônico, para qualquer cliente que age em nome de um usuário, seja ele um app web, uma SPA, um app de celular ou uma CLI. O PKCE (lê-se “pixy”, de Proof Key for Code Exchange) é a prova por requisição que substitui o segredo que falta ao cliente público, e na 2.1 ele é obrigatório para todos.
sequenceDiagram
participant RO as Resource Owner
participant C as Client
participant AS as Authorization Server
participant RS as Resource Server
C->>C: gera code_verifier e deriva code_challenge
C->>AS: GET /authorize com code_challenge e state
AS->>RO: pede login e consentimento
RO->>AS: aprova os escopos
AS->>C: redirect com authorization code e state
C->>AS: POST /token com code e code_verifier
AS->>AS: confere o code_verifier contra o code_challenge
AS->>C: access_token mais refresh_token
C->>RS: chamada com Authorization Bearer
RS->>C: recurso protegido
Passo a passo, o que cada seta carrega.
Antes de tudo, o cliente gera um segredo só seu para aquela requisição. Ele sorteia um code_verifier, uma string aleatória de 43 a 128 caracteres, e dela deriva um code_challenge. No método S256, o único que se deve usar, o desafio é o hash do verificador: code_challenge = BASE64URL(SHA256(code_verifier)).
Com isso em mãos, o cliente redireciona o navegador do usuário ao endpoint /authorize do AS, passando o desafio (não o verificador):
https://authorization-server.com/authorize?response_type=code &client_id=s6BhdRkqt3 &redirect_uri=https://app.exemplo.com/callback &scope=photos &state=xyz123 &code_challenge=E9Melhoa2CwvinuxlnA4hg... &code_challenge_method=S256O state é um valor aleatório contra CSRF, que o cliente vai conferir na volta; o code_challenge viaja agora, o code_verifier fica guardado. O AS então autentica o usuário e mostra a tela de consentimento com os escopos pedidos. Aprovado, ele redireciona de volta à redirect_uri com o code e o mesmo state. O cliente confere que o state bate (senão, descarta) e parte para a troca.
A troca acontece pelo back channel, um POST direto ao endpoint /token, sem passar pelo navegador:
POST /token HTTP/1.1Host: authorization-server.comContent-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https://app.exemplo.com/callback&client_id=s6BhdRkqt3&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r...Aqui está o pulo do gato do PKCE: o cliente envia agora o code_verifier original. O AS refaz o hash desse verificador e compara com o code_challenge que guardou na etapa do /authorize. Só se baterem ele emite os tokens (um cliente confidencial ainda apresenta o client_secret por cima). A resposta é um JSON:
{ "access_token": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk", "scope": "photos"}De posse do access token, o cliente chama a API do resource server pondo o token no cabeçalho Authorization: Bearer ..., e recebe o recurso.
O que o PKCE defende é a interceptação do authorization code. Num cliente público, um app malicioso registrado no mesmo esquema de redirect pode capturar o code na volta. Sem PKCE, o code roubado bastaria para obter tokens. Com PKCE, o atacante também precisaria do code_verifier, que nunca saiu do cliente legítimo e nunca trafegou pelo navegador, então o code interceptado não vale nada.
Client Credentials
Section titled “Client Credentials”Quando não há usuário nenhum na história, e um serviço fala com outro em seu próprio nome, o fluxo é o Client Credentials. Um backend que consome a API de outro sistema como ele mesmo, um job que roda de madrugada. Só clientes confidenciais o usam, porque ele se apoia num segredo. O cliente faz um POST ao /token com grant_type=client_credentials e se autentica com client_id e client_secret:
POST /token HTTP/1.1Host: authorization-server.comContent-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw&scope=reports.readNão há tela de consentimento (não há usuário para consentir) e, por convenção, não se emite refresh token: quando o access token expira, o cliente simplesmente roda o grant de novo, já que sempre pode se autenticar.
Device Authorization
Section titled “Device Authorization”Para aparelhos com internet mas sem teclado ou navegador decentes, uma smart TV, um console, uma CLI, o Device Authorization move o consentimento para um segundo aparelho. O aparelho pede um par de códigos ao AS e recebe algo como:
{ "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNh", "user_code": "WDJB-MJHT", "verification_uri": "https://exemplo.com/device", "expires_in": 1800, "interval": 5}A TV exibe “acesse exemplo.com/device e digite WDJB-MJHT” (o user_code), enquanto usa o device_code para consultar o endpoint de token de tempos em tempos, respeitando o interval. Enquanto o usuário não termina no celular, o AS responde authorization_pending; se o aparelho consultar rápido demais, slow_down. Assim que o usuário aprova, a próxima consulta recebe um token normal.
Refresh Token
Section titled “Refresh Token”Quando o access token expira, o Refresh Token o renova sem incomodar o usuário. O cliente faz um POST ao /token com grant_type=refresh_token e o refresh token que guardou; pode pedir um escopo igual ou menor, nunca maior. Sob rotação, a resposta traz também um refresh token novo, que invalida o anterior. Na 2.1 essa rotação (ou o sender-constraining) é obrigatória para clientes públicos, pela razão que a página de mudanças explica.
Qual fluxo usar
Section titled “Qual fluxo usar”A escolha cai naturalmente da situação, e é quase sempre óbvia.
| Situação | Fluxo |
|---|---|
| App (web, SPA, celular, desktop, CLI) agindo por um usuário | Authorization Code + PKCE |
| Serviço falando com serviço, sem usuário | Client Credentials |
| Aparelho sem teclado ou navegador | Device Authorization |
| Renovar um access token expirado | Refresh Token |
Faltam dois grants que existiam na 2.0 e você não vai achar aqui: o implícito e o de senha. A ausência é deliberada, e a página seguinte conta por que ambos foram removidos.
Palavras-chave
Section titled “Palavras-chave”Fluxos: authorization code, PKCE, client credentials, device authorization, refresh token
Parâmetros: response_type=code, code_challenge, code_challenge_method=S256, code_verifier, grant_type, state, scope
Endpoints: /authorize, /token
Conceitos: front channel, back channel, interceptação de code, rotação de token