排查 JWT 验证问题

如果客户端应用在对 API 的请求中包含 JSON 网络令牌 (JWT),可扩展服务代理 (ESP) 会在向 API 后端发送请求之前验证 JWT。如果 JWT 验证失败并且 ESP 在对客户端的响应中返回错误,您可以参考本页面的问题排查信息。如需详细了解 JWT,请参阅 RFC7519

错误:401: Jwt issuer is not configured

在 Cloud Run 中部署 ESPv2 时,如果未在 gcloud run deploy 命令中使用 --allow-unauthenticated 标志,就可能会发生这种情况。如果未使用此标志,则 JWT 令牌将被 Cloud Run <a=" docs="" managing-access"="" run="" securing="">访问权限控制 IAM 服务器拦截并验证,而非由 ESPv2 进行验证。IAM 使用的颁发者可能与 ESPv2 不同。 </a=">

错误:BAD_FORMAT

请按如下所述进行检查:

  • 确保 JWT 包含有效的 JSON。
  • 检查 JWT 标头是否含有 "alg" 字段以及是否被设置为以下某个值:"RS256""HS256""RS384""HS384""RS512""HS512"
  • 检查 JWT 负载中以下字段的数据类型(如果存在这些字段):
    • "iat"(颁发时间)、"exp"(过期时间)和 "nbf"(不早于)声明是大于 0 的数字而不是字符串。
    • "sub"(主题)、"iss"(签发者)和 "jti" (JWT ID) 字段为字符串。
    • "aud"(受众群体)声明是字符串或字符串数组。
  • 确保 JWT 负载中存在以下声明:"sub"(主题)、"iss"(颁发者)和 "aud"(受众群体)。

以下是有效的已解码 JWT 令牌的示例:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "42ba1e234ac91ffca687a5b5b3d0ca2d7ce0fc0a"
}

Payload:
{
  "iss": "myservice@myproject.iam.gserviceaccount.com",
  "iat": 1493833746,
  "aud": "myservice.appspot.com",
  "exp": 1493837346,
  "sub": "myservice@myproject.iam.gserviceaccount.com"
}
错误:TIME_CONSTRAINT_FAILURE

使用 jwt.io 解码 JWT 并确保:

  • 存在 "exp"(过期时间)声明。
  • "exp"(过期时间)声明值是将来的日期/时间。当前日期/时间必须晚于或等于 "exp" 声明中所列的日期/时间。
  • "nbf"(不早于)声明(如果存在)是过去的日期/时间。当前日期/时间必须晚于或等于 "nbf" 声明中所列的日期/时间。
错误:UNKNOWN

使用 jwt.io 解码 JWT 并确保:

  • 如果 "iss"(颁发者)声明是电子邮件地址,则 "sub"(主题)和 "iss" 声明应该相同。这是为了确保对于电子邮件颁发者而言,JWT 是自颁发的。

错误:KEY_RETRIEVAL_ERROR

  • 检查 OpenAPI 文件中的 x-google-jwks_uri 字段指定的公钥 URI 是否正确且有效。

错误:Issuer not allowed

  • 检查 JWT 令牌中的 "iss"(颁发者)声明是否与 OpenAPI 文件中安全对象的 securityDefinitions 部分的 x-google-issuer 字段相匹配。

  • 在 OpenAPI 文件中,检查是否为调用的 API 方法启用了安全对象。

请参阅示例 openapi.yaml 文件,了解关于如何使用 securityDefinitionsecurity 对象在方法级别描述安全性的示例。

错误:Audience not allowed

查看 JWT 令牌中的 "aud"(受众)声明,看它是否与 Endpoints 服务名称(对应于 OpenAPI 文件中的 host 字段)相匹配:

如果 "aud" 声明与 Endpoints 服务名称不同,请执行下列操作:

  • 检查 JWT 中的 "aud" 声明是否与 OpenAPI 文件中指定的某个 x-google-audiences 值相匹配。

  • 确保 x-google-audiencesx-google-issuer 位于 OpenAPI 文件的同一 securityDefinitions 对象中。

如果 "aud" 声明与 Endpoints 服务名称相同,ESP 会验证受众并忽略 OpenAPI 文件中的 x-google-audiences 值。例如,如果您的服务名称是 "myservice.endpoints.example-project-12345.cloud.goog",则 "aud" 设置为 "myservice.endpoints.example-project-12345.cloud.goog""https://myservice.endpoints.example-project-12345.cloud.goog" 的 JWT 为有效受众群体。