跳到主要内容
ecdsa.com
jose (JavaScript)JWT 库

错误信息

unexpected "aud" claim value

jose (JavaScript) — JWTClaimValidationFailed, code ERR_JWT_CLAIM_VALIDATION_FAILED

含义

签名验证通过了,但令牌的 `aud` 声明中不包含你作为 `audience` 传给 `jwtVerify` 的值。jose 按字符串精确比较:只要令牌 `aud`(字符串或数组)中至少有一个值等于你允许的某个受众,检查就会通过。令牌本身是真实的——只是它签发给了另一个接收方;接受它就意味着为一个 API 签发的令牌可以被重放到另一个 API。

原因

修复方法

  1. 1.

    把令牌携带的值与你期望的值并排打印出来

    解码声明(但不要信任它们),逐个字符比较 `aud` 与你的 `audience` 选项。哪一边错了就修正哪一边——验证方的选项或颁发者的配置——但要保留这项检查。

    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. 2.

    为你要调用的 API 请求令牌

    如果令牌是签发给另一个受众的,就应该在客户端修复:在令牌请求中指明目标 API,让授权服务器把它写入 `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. 3.

    显式允许多个标识符,前提是它们都属于你

    `audience` 接受数组。列出每个合法指代这个 API 的标识符(例如从 URL 迁移到逻辑名称期间),而不是删除该选项——没有 `audience`,jose 根本不会检查 `aud`。

    js
    await jwtVerify(token, jwks, {
      algorithms: ["ES256"],
      audience: ["https://api.example.com/orders", "orders-api"], // any one must match
    });

相关错误

浏览完整的签名错误库