如何才能解码和验证 Amazon Cognito JSON Web Token 签名?

上次更新时间:2020 年 9 月 14 日

我想使用 Amazon Cognito 用户池作为我的应用程序的身份验证方法。验证客户端发送到我的应用程序的 ID 和访问令牌的安全方法是什么?

简短描述

当客户端使用用户池对您的应用程序进行身份验证时,Amazon Cognito 会发送 ID 令牌。如有下列类似情形,您可能需要手动验证 ID 令牌:

  • 您创建了 Web 应用程序,并希望使用 Amazon Cognito 用户池进行身份验证。
  • 您可以使用 Amazon Cognito 用户池进行身份验证,并使用 Amazon Cognito 身份池来检索 AWS Security Token Service (AWS STS) 临时证书。使用这些证书调用 AWS Lambda,但 Lambda 没有关于最初通过用户池进行身份验证的用户的信息。

要获取 Amazon Cognito JSON Web Token (JWT) 中包含的 Amazon Cognito 用户详细信息,您可以对其进行解码,然后验证签名。有关如何使用 AWS Lambda 解码与验证 Amazon Cognito JWT 的代码示例,请参阅 GitHub 网站上的解码和验证 Amazon Cognito JWT 令牌

解决方法

用户登录后,Amazon Cognito 用户池将返回 JWT。JWT 是一个 Base64 编码的 JSON 字符串,其中包含有关用户的信息(称为声明)。Amazon Cognito 返回三个令牌:ID 令牌、访问令牌和刷新令牌。ID 令牌包含在 Amazon Cognito 用户池中定义的用户字段。

令牌包括三个部分:标头、有效负载和签名。

以下是示例 ID 令牌的标头。标头包含密钥 ID(“kid”)以及用于签名令牌的算法(“alg”)。在此示例中,该算法是“RS256”,它是带有 SHA-256 的 RSA 签名。

{
  "kid": "abcdefghijklmnopqrsexample=",
  "alg": "RS256"
}

以下是有效负载的示例,其中包含有关用户的信息以及令牌创建和到期的时间戳: 

{
  "sub": "aaaaaaaa-bbbb-cccc-dddd-example",
  "aud": "xxxxxxxxxxxxexample",
  "email_verified": true,
  "token_use": "id",
  "auth_time": 1500009400,
  "iss": "https://cognito-idp.ap-southeast-2.amazonaws.com/ap-southeast-2_example",
  "cognito:username": "anaya",
  "exp": 1500013000,
  "given_name": "Anaya",
  "iat": 1500009400,
  "email": "anaya@example.com"
}

最后一部分是签名,它是标头和有效负载的哈希加密组合。

Amazon Cognito 为每个用户池生成两个 RSA 密钥对。每对的私钥用于签名相应的 ID 令牌或访问令牌。公钥在以下格式的地址提供: 

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

JSON 文件 (jwks.json) 采用如下格式的结构: 

{
    "keys": [{
        "alg": "RS256",
        "e": "AQAB",
        "kid": "abcdefghijklmnopqrsexample=",
        "kty": "RSA",
        "n": "lsjhglskjhgslkjgh43lj5h34lkjh34lkjht3example",
        "use": "sig"
    }, {
        "alg":
        "RS256",
        "e": "AQAB",
        "kid": "fgjhlkhjlkhexample=",
        "kty": "RSA",
        "n": "sgjhlk6jp98ugp98up34hpexample",
        "use": "sig"
    }]
}

要验证 Amazon Cognito JWT 的签名,请首先搜索具有与令牌标头中的密钥 ID 匹配的密钥 ID 的公钥。然后,您可以使用库(如 jwt.ioOpenID Foundation 建议的库)来验证令牌的签名并提取值(如到期信息和用户名)。

除了签名之外,验证以下内容也是最佳做法:

  • 令牌未到期。
  • 在有效负载中指定的受众(“aud”)与在 Amazon Cognito 用户池中创建的应用程序客户端 ID 匹配。

有关如何使用 AWS Lambda 解码和验证 Amazon Cognito JWT 的代码示例,请参阅 解码和验证 Amazon Cognito JWT 令牌


这篇文章对您有帮助吗?


您是否需要账单或技术支持?