验证 JSON Web 令牌 - Amazon Cognito

验证 JSON Web 令牌

这些步骤描述了验证用户池 JSON Web 令牌(JWT)的过程。

先决条件

您的库、开发工具包或软件框架可能已处理本部分中的任务。例如,Amazon Cognito 开发工具包提供在客户端上的用户池令牌处理和管理。与此类似,如果满足以下两个条件,适用于 iOS 的 Mobile SDK 和 适用于 Android 的 Mobile SDK 会自动刷新您的 ID 令牌和访问令牌:必须存在有效的(非过期)刷新令牌,而且 ID 令牌和访问令牌至少有 5 分钟的剩余有效时间。有关 SDK 以及适用于 JavaScript、Android 和 iOS 的示例代码的信息,请参阅 Amazon Cognito 用户池 SDK

许多库可用于解码和验证 JSON Web 令牌 (JWT)。如果您必须手动处理用于服务器端 API 处理的令牌,或者您使用的是其他编程语言,则此类库可以帮助您。请参阅用于处理 JWT 令牌库的 OpenID Foundation 列表

步骤 1:确认 JWT 的结构

一个 JSON Web 令牌 (JWT) 包含三个部分:

  1. 标头

  2. 有效负载

  3. 签名

11111111111.22222222222.33333333333

这些部分以 base64url 字符串的格式编码,并且使用点 (.) 字符分隔。如果您的 JWT 不符合此结构,请将其视为无效,且不得接受它。

步骤 2:验证 JWT 签名

JWT 签名是标头和负载的哈希组合。Amazon Cognito 为每个用户池生成两对 RSA 加密密钥。其中一对私有密钥用于对令牌进行签名。

验证 JWT 令牌的签名

  1. 解码 ID 令牌。

    您可以使用 AWS Lambda 解码用户池 JWT。有关更多信息,请参阅使用 AWS Lambda 解码并验证 Amazon Cognito JWT 令牌

    OpenID Foundation 还维护用于处理 JWT 令牌的库列表

  2. 将本地密钥 ID(kid)与公有 kid 进行比较。

    1. 下载并存储适用于用户池的对应的公有 JSON Web Key(JWK)。它可作为 JSON Web Key Set (JWKS) 的一部分提供。您可以通过为您的环境构建以下 URL 来找到它:

      https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

      有关 JWK 和 JWK 集的更多信息,请参阅 JSON Web 密钥 (JWK)

      注意

      在 Web API 操作可以处理令牌之前,为您的用户池下载和存储 JWK 是一次性步骤。这样做后,每当 ID 令牌或访问令牌用于您的 Web API 操作时,您都可以执行以下步骤。

      这是个 jwks.json 文件示例:

      { "keys": [{ "kid": "1234example=", "alg": "RS256", "kty": "RSA", "e": "AQAB", "n": "1234567890", "use": "sig" }, { "kid": "5678example=", "alg": "RS256", "kty": "RSA", "e": "AQAB", "n": "987654321", "use": "sig" }] }
      密钥 ID(kid

      kid 是一个提示,指示哪些密钥用于保护令牌的 JSON Web Signature(JWS)。

      算法(alg

      alg 标头参数表示用于保护 ID 令牌的加密算法。用户池使用 RS256 加密算法,这是一种采用 SHA-256 的 RSA 签名。有关 RSA 的更多信息,请参阅 RSA 加密

      密钥类型(kty

      kty 参数标识与密钥结合使用的加密算法系列,例如,在本示例中为“RSA”。

      RSA 指数(e

      e 参数包含 RSA 公有密钥的指数值。它表示为采用 Base64urlUInt 编码的值。

      RSA 模数(n

      n 参数包含 RSA 公有密钥的模数值。它表示为采用 Base64urlUInt 编码的值。

      使用(use

      use 参数描述了公有密钥的预期用途。在本示例中,usesig 表示签名。

    2. 搜索与您 JWT 的 kid 相匹配的 kid 的公有 JSON Web 密钥。

  3. 使用 JWT 库,例如 GitHub 上的 aws-jwt-verify 库,以便将发布者的签名与令牌中的签名进行比较。发布者签名来自在 jwks.json 中的 kid 公有密钥(RSA 模数 "n"),该公有密钥与令牌 kid 匹配。您可能首先需要将 JWK 转换为 PEM 格式。以下示例采用 JWT 和 JWK 格式,并且使用 Node.js 库、jsonwebtoken 来验证 JWT 签名:

    Node.js
    var jwt = require('jsonwebtoken'); var jwkToPem = require('jwk-to-pem'); var pem = jwkToPem(jwk); jwt.verify(token, pem, { algorithms: ['RS256'] }, function(err, decodedToken) { });

步骤 3:验证声明

验证 JWT 声明

  1. 确认该令牌没有过期。

  2. ID 令牌中的 aud 声明和访问令牌中的 client_id 声明应与在 Amazon Cognito 用户池中创建的应用程序客户端 ID 匹配。

  3. 发布者 (iss) 声明应与您的用户池匹配。例如,在 us-east-1 区域中创建的用户池将有下列 iss 值:

    https://cognito-idp.us-east-1.amazonaws.com/<userpoolID>.

  4. 检查 token_use 声明。

    • 如果您在 Web API 操作中只接受访问令牌,则其值必须为 access

    • 如果您只使用 ID 令牌,则其值必须为 id

    • 如果您同时使用 ID 令牌和访问令牌,则 token_use 声明必须为 idaccess

您现在可以信任该令牌内的声明。