Mensagem de erro
unexpected "aud" claim value
jose (JavaScript) — JWTClaimValidationFailed, code ERR_JWT_CLAIM_VALIDATION_FAILED
O que significa
A assinatura foi verificada, mas a claim `aud` do token não contém o valor que você passou como `audience` para `jwtVerify`. O jose compara strings exatas: a verificação passa quando pelo menos um valor do `aud` do token (uma string ou um array) é igual a um dos públicos-alvo que você permite. O token é autêntico — ele simplesmente foi emitido para outro destinatário, e aceitá-lo permitiria que um token gerado para uma API fosse reutilizado contra outra.
Por que acontece
O token foi emitido para outra API
comumUm mesmo servidor de autorização muitas vezes atende vários servidores de recursos. Um cliente que obteve um token para a API de pedidos e o envia para a API de faturamento recebe exatamente este erro — a verificação está cumprindo seu papel. A propriedade `err.payload` do erro mostra as claims que o token realmente traz.
Mesma API, identificador escrito de outro jeito
comumA comparação do público-alvo é exata, byte a byte: `https://api.example.com` e `https://api.example.com/` (barra final), http e https, ou um nome lógico como `api://orders` e a URL da API são todos valores diferentes. Os provedores de identidade copiam o identificador literalmente da configuração deles, então o verificador precisa usar a mesma grafia.
Um token de ID enviado onde se espera um token de acesso
ocasionalNo OpenID Connect, o `aud` do token de ID é o ID do cliente do aplicativo em que o usuário fez login, e não a sua API. Por isso, front-ends que encaminham o token de ID em vez do token de acesso falham na verificação do público-alvo de todas as APIs por trás deles.
O cliente não solicitou um público-alvo específico
ocasionalVários provedores (Auth0, servidores de autorização personalizados do Okta, Keycloak com audience mappers) só colocam sua API em `aud` quando a requisição de token a menciona. Sem o parâmetro `audience` ou o parâmetro `resource` da RFC 8707, o token é emitido para um público-alvo padrão, como o endpoint userinfo.
Como corrigir
- 1.
Imprimir o que o token traz ao lado do que você espera
Decodifique as claims sem confiar nelas e compare `aud` com sua opção `audience` caractere por caractere. Corrija o lado que estiver errado — a opção do verificador ou a configuração do emissor —, mas mantenha a verificação.
js import { decodeJwt, jwtVerify } from "jose"; console.log("token aud:", decodeJwt(token).aud); // string or array of strings await jwtVerify(token, jwks, { algorithms: ["ES256"], issuer: "https://issuer.example.com", audience: "https://api.example.com/orders", // exact string match }); - 2.
Solicitar um token para a API que você está chamando
Quando o token foi emitido para outro público-alvo, a correção cabe ao cliente: indique a API de destino na requisição de token para que o servidor de autorização a coloque em `aud`.
bash # OAuth 2.0 client credentials: ask the authorization server for a token # minted for the API you are about to call (Auth0 uses "audience", # RFC 8707 resource indicators use "resource"). curl -s https://issuer.example.com/oauth/token \ -d grant_type=client_credentials \ -d client_id="$CLIENT_ID" -d client_secret="$CLIENT_SECRET" \ -d audience=https://api.example.com/orders - 3.
Permitir vários identificadores explicitamente, se todos forem seus
A opção `audience` aceita um array. Liste todos os identificadores que nomeiam legitimamente esta API (por exemplo, durante uma migração de uma URL para um nome lógico) em vez de remover a opção — sem `audience`, o jose não verifica o `aud` de forma alguma.
js await jwtVerify(token, jwks, { algorithms: ["ES256"], audience: ["https://api.example.com/orders", "orders-api"], // any one must match });