Pular para o conteúdo
ecdsa.com
jose (JavaScript)Bibliotecas de JWT

Mensagem de erro

unexpected "iss" claim value

jose (JavaScript) — JWTClaimValidationFailed, code ERR_JWT_CLAIM_VALIDATION_FAILED

O que significa

O token foi verificado criptograficamente, mas a claim `iss` dele não é igual à opção `issuer` que você passou para `jwtVerify`. O jose compara as strings de forma exata (um array de emissores permitidos também é aceito), então qualquer diferença — uma barra final, outro caminho de locatário, outro ambiente — reprova a verificação. Fixar o emissor é o que impede que um token de outro provedor de identidade, ou de outro locatário do mesmo provedor, seja aceito.

Por que acontece

Como corrigir

  1. 1.

    Copiar a string do emissor do documento de descoberta

    O valor de `issuer` em `/.well-known/openid-configuration` é, por especificação, exatamente o que o provedor grava em `iss`. Copie-o byte a byte para sua configuração.

    bash
    # The issuer string is defined by the provider's discovery document.
    curl -s https://login.example.com/.well-known/openid-configuration | jq -r .issuer
  2. 2.

    Fixar esse valor exato no jwtVerify

    Mantenha a opção `issuer` — sem ela, o jose não verifica o `iss` de forma alguma — e guarde o valor em uma única constante, compartilhada pela URL do JWKS e pelo verificador.

    js
    import { createRemoteJWKSet, jwtVerify } from "jose";
    
    const ISSUER = "https://login.example.com/"; // exactly as in "issuer" from discovery
    const jwks = createRemoteJWKSet(new URL("https://login.example.com/.well-known/jwks.json"));
    
    const { payload } = await jwtVerify(token, jwks, { algorithms: ["ES256"], issuer: ISSUER });
  3. 3.

    Aceitar vários emissores com um conjunto de chaves para cada um

    Se seu serviço realmente confia em mais de um emissor, selecione o conjunto de chaves pelo `iss` (ainda não verificado) do token, a partir de uma lista explícita de emissores permitidos, e depois verifique com esse emissor fixado. Nunca deixe que as chaves de um emissor verifiquem os tokens de outro emissor.

    js
    import { createRemoteJWKSet, decodeJwt, jwtVerify } from "jose";
    
    // Each trusted issuer gets its own key set; an unknown iss is rejected before any key is used.
    const trusted = new Map([
      ["https://login.example.com/", createRemoteJWKSet(new URL("https://login.example.com/.well-known/jwks.json"))],
      ["https://partner.example.org", createRemoteJWKSet(new URL("https://partner.example.org/jwks"))],
    ]);
    
    const { iss } = decodeJwt(token);
    const keys = trusted.get(iss);
    if (!keys) throw new Error("untrusted issuer");
    await jwtVerify(token, keys, { algorithms: ["ES256", "RS256"], issuer: iss });

Erros relacionados

Ver toda a base de erros de assinatura