NetCatTest

DevSecOps & Supply Chain

OAuth em 2026: PKCE, BFF e os testes que evitam roubo de tokens

Entenda a RFC 10017, compare BFF e tokens no navegador e organize testes de PKCE, audiência e renovação com evidências de laboratório.

Por Daniel Felipe 9 min leitura

Segurança OAuth começa no caminho percorrido pelo token. Um login pode funcionar perfeitamente e ainda entregar credenciais a um destino incorreto, aceitar um código fora da sessão original ou expor um refresh token ao JavaScript. Para avaliar uma implementação, o teste precisa acompanhar emissão, armazenamento, uso e revogação.

Em agosto de 2026, a IETF publicou a RFC 10017 sobre aplicações OAuth no navegador. Ela oferece um ponto de partida atual para discutir arquitetura. Este guia combina essa referência com os padrões de PKCE, OpenID Connect e proteção de tokens, e propõe uma matriz de testes para um laboratório autorizado.

PKCE em bytes: por que o código roubado não basta

A comparação de PKCE deve ser entendida no nível dos bytes. O cliente cria um code_verifier aleatório para uma única transação; o desafio S256 é o SHA-256 desse texto, codificado em base64url sem padding. O servidor guarda o desafio junto do código de autorização. Na troca, recalcula o desafio do verificador recebido e compara os valores. Quem possui apenas o código não conhece automaticamente o verificador.

O exemplo local a seguir é uma implementação didática da transformação, não o código de um provedor. Os nomes correspondem aos parâmetros de RFC 7636. O par gerado é efêmero: não deve ser reutilizado entre usuários, abas ou tentativas. Um código interceptado junto do verificador continua perigoso; PKCE não corrige armazenamento que expõe ambos.

import base64
import hashlib
import secrets

verificador = secrets.token_urlsafe(32)
desafio = base64.urlsafe_b64encode(
    hashlib.sha256(verificador.encode('ascii')).digest()
).rstrip(b'=').decode('ascii')

assert 43 <= len(verificador) <= 128
assert len(desafio) == 43
print('S256', len(verificador), len(desafio))

Linha a linha, a aleatoriedade produz o segredo da transação, o hash evita enviá-lo no pedido de autorização e a codificação converte o digest em um valor apropriado para o protocolo. A expressão rstrip remove somente padding. Usar base64 comum, incluir padding ou aplicar hash sobre bytes diferentes do verificador original pode quebrar a interoperabilidade.

Há outras associações indispensáveis: código ao cliente, redirect URI, sessão que iniciou a operação e uso único. Uma boa matriz local troca apenas um desses vínculos por vez. O caso válido deve funcionar; verificador incorreto, código reutilizado e callback de outra transação devem falhar sem emissão de token. state e nonce têm finalidades próprias e não são substituídos pela aritmética de PKCE.

No BFF, a fronteira muda: o navegador recebe uma sessão, enquanto o backend manipula tokens. Teste também CSRF, isolamento da sessão e autorização das chamadas encaminhadas. Um BFF que aceita qualquer destino ou devolve tokens no corpo reintroduz a superfície que pretendia reduzir. A investigação precisa seguir onde o segredo existe, quem o lê e qual identidade a API realmente autoriza.

OAuth, OpenID Connect e JWT têm papéis diferentes

OAuth trata da autorização para acessar recursos. OpenID Connect acrescenta uma camada de identidade, com o ID token e regras de validação próprias. JWT é um formato que pode transportar declarações. Encontrar três partes separadas por pontos não demonstra que o token é confiável ou que ele pertence à aplicação que o recebeu.

Na revisão de um login OpenID Connect, confirme a assinatura com as chaves do emissor confiável, o emissor esperado, a audiência e a validade temporal. Quando a requisição utiliza nonce, o valor recebido precisa corresponder à transação iniciada. As condições exatas dependem do fluxo. A especificação OpenID Connect Core detalha essas verificações. Um ID token não deve ser tratado automaticamente como um access token para qualquer API.

O que PKCE protege e o que continua exposto

PKCE vincula a troca do código de autorização a um segredo temporário criado pelo cliente. No método S256, o cliente envia um desafio derivado desse segredo e apresenta o valor original ao trocar o código. O servidor compara os valores antes de liberar tokens. Esse vínculo dificulta o aproveitamento de um código interceptado por quem não possui o verificador. O mecanismo é definido na RFC 7636.

Cliente cria o verificador
        ↓
Autorização recebe o desafio S256
        ↓
Callback recebe um código temporário
        ↓
Troca exige o verificador correspondente
        ↓
Servidor valida o vínculo e emite tokens

Em um ambiente de teste, tente trocar um código com o verificador de outra sessão e registre a rejeição. Verifique também o tratamento de código já utilizado. Esses casos examinam o vínculo da transação; não comprovam, sozinhos, que armazenamento, redirecionamento e autorização da API estejam seguros.

PKCE não elimina XSS e não impede que código malicioso execute ações dentro de uma sessão comprometida. Portanto, a pergunta seguinte deve ser: qual componente recebe o token e quais operações ele consegue realizar?

Ilustração conceitual de navegador, servidor BFF com cofre de tokens e servidor de API

Ilustração conceitual gerada: navegador com sessão, BFF responsável pelos tokens e API. Os objetos ajudam a separar responsabilidades; não representam uma sequência normativa de mensagens OAuth.

BFF ou tokens no navegador: uma decisão de arquitetura

No padrão Backend for Frontend, ou BFF, um componente do servidor assume o papel de cliente OAuth, mantém tokens e encaminha as chamadas da interface à API. O navegador trabalha com uma sessão baseada em cookie. A RFC 10017 compara esse modelo com um backend que entrega access tokens ao navegador e com o cliente inteiramente executado no navegador.

Manter os tokens no servidor reduz sua exposição ao JavaScript, mas um script malicioso ainda pode tentar realizar ações pela sessão do usuário. O BFF também exige controles de sessão, proteção contra CSRF e limites nas rotas encaminhadas. A escolha deve considerar os recursos da equipe, a sensibilidade das operações e a capacidade de manter esse componente.

Cookie seguro e autorização da API precisam de retestes separados

No BFF, o navegador recebe uma sessão e o servidor guarda os tokens. Essa escolha reduz a exposição dos tokens ao JavaScript, mas cada proteção do cookie responde a uma pergunta específica. Secure restringe o envio ao transporte seguro; HttpOnly limita o acesso por script; SameSite influencia o envio em contextos entre sites. Nenhuma dessas opções, sozinha, confirma que a operação pertence ao usuário autenticado. A referência de gerenciamento de sessões da OWASP ajuda a separar essas responsabilidades.

No laboratório, mantenha duas identidades fictícias e registre qual sessão o BFF associou a cada chamada da API. Verifique renovação, logout, isolamento entre contas e operações que alteram estado. Um cookie inacessível ao script não impede que um XSS use a sessão pelo próprio navegador; o relatório precisa distinguir extração de token de execução de uma ação autenticada.

Para CSRF, documente o comportamento esperado conforme o desenho da aplicação e seus fluxos entre sites. Preserve o resultado da validação de origem ou do mecanismo adotado, sem exportar cookies e tokens. O encerramento exige evidência de que o cliente perdeu a sessão quando previsto e de que o BFF continua aplicando autorização a cada recurso.

Refresh tokens, audiência e prova de posse

A RFC 9700, a prática de segurança atual para OAuth 2.0, orienta restringir privilégios e reduzir o uso indevido de tokens roubados. Para clientes públicos, refresh tokens precisam usar rotação ou vínculo ao remetente. Também é necessário analisar audiência, escopo e o comportamento quando um token antigo reaparece.

Uma política operacional precisa responder a quatro perguntas: qual recurso aceita o token, quanto tempo ele permanece útil, como a renovação é protegida e quais credenciais são revogadas quando ocorre um incidente. Expiração curta não substitui a rejeição de audiência incorreta.

DPoP acrescenta uma prova assinada associada à chave do cliente e à requisição. A RFC 9449 descreve o mecanismo para restringir tokens ao remetente. Ele aumenta os requisitos de validação e de tratamento de replay. Não significa que uma aplicação com JavaScript comprometido possa continuar sendo considerada confiável.

Uma matriz de testes para o laboratório Aurora

O cenário abaixo é fictício e constitui um roteiro proposto, não um relato de exploração. Considere duas sessões de teste, uma API de perfil e dados sem valor real. Para cada caso, guarde o resultado esperado e a resposta observada.

Caso controladoResultado esperadoEvidência útil
Verificador PKCE de outra sessãoTroca recusadaStatus e erro do endpoint de token
Callback que não está cadastradoAutorização recusadaDestino solicitado e política efetiva
Token destinado a outra APIAcesso recusadoAudiência esperada e resposta
Renovação com token anteriorAplicação da política de replayEventos da família de tokens
Logout seguido de chamada autenticadaComportamento coerente com a política publicadaJanela de validade e estado da sessão

O relatório deve ocultar códigos e tokens completos. Prefira hashes de correlação, horários, identificadores de sessão fictícios e trechos mínimos das respostas. Uma captura isolada mostra um comportamento; a comparação entre sessões ajuda a explicar a fronteira que deveria ter sido respeitada.

Perguntas frequentes

PKCE substitui o segredo de um cliente confidencial?

Não. PKCE protege o vínculo da troca do código. A autenticação de um cliente confidencial continua sendo uma responsabilidade separada.

Decodificar um JWT prova que sua assinatura é válida?

Não. Decodificação apenas permite ler a estrutura. A validação precisa aplicar assinatura, emissor, audiência e as demais condições esperadas para aquele uso.

Como organizar as evidências no Android?

Comece pelo guia de JWT e evidências no CatSuite e pelo roteiro de comparação de requests no Repetir. Trabalhe apenas com ambientes sob autorização e preserve os registros do servidor de identidade para correlacionar os resultados.

Próximo passo: desenhe o percurso de um único login e marque todos os componentes que recebem código, token ou cookie. Essa representação torna os testes mais objetivos do que uma lista de parâmetros examinados sem contexto.

Escrito por

Daniel Felipe é criador do NetCatTest e produz conteúdos sobre cibersegurança, privacidade digital, OSINT, laboratórios autorizados e ferramentas para estudo técnico responsável.

Compartilhar

Enviar este artigo