

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 了解用户池 JSON 网络令牌 (JWTs)
用户池令牌

令牌是身份验证的构件，您的应用程序可以将其用作 OIDC 身份验证的证明并请求访问资源。令牌中的*声明*是有关您的用户的信息。ID 令牌包含有关用户身份的声明，例如他们的用户名、姓氏和电子邮件地址。访问令牌包含诸如经过身份验证`scope`的用户可用于访问第三方 APIs、Amazon Cognito 用户自助服务 API 操作以及. [userInfo 端点](userinfo-endpoint.md) 访问令牌和 ID 令牌均包含 `cognito:groups` 声明，其中包含用户在用户池中的组成员资格。有关用户池组的更多信息，请参阅 [向用户池添加组](cognito-user-pools-user-groups.md)。

Amazon Cognito 还有刷新令牌，您可以使用它来获取新的令牌或撤销现有令牌。[刷新令牌](amazon-cognito-user-pools-using-the-refresh-token.md)来检索新的 ID 令牌和访问令牌。[撤销令牌](amazon-cognito-user-pools-using-the-refresh-token.md#amazon-cognito-identity-user-pools-revoking-all-tokens-for-user)来撤销刷新令牌允许的用户访问权限。

Amazon Cognito 以 [base64url](https://datatracker.ietf.org/doc/html/rfc4648#section-5) 编码字符串的形式发布令牌。您可以将任何 Amazon Cognito ID 或访问令牌从 `base64url` 解码为纯文本 JSON。Amazon Cognito 刷新令牌已加密，对用户池用户和管理员不透明，并且只能由您的用户池读取。

**使用令牌进行身份验证**  
当用户登录您的应用程序时，Amazon Cognito 会验证登录信息。如果登录成功，Amazon Cognito 会创建会话并为经过身份验证的用户返回 ID 令牌、访问令牌和刷新令牌。您可以使用这些令牌向您的用户授予对下游资源的访问权限， APIs 例如 Amazon API Gateway。或者，您可以用它们交换用于访问其他 Amazon Web Services 服务的临时 Amazon 凭证。

![\[身份验证概述\]](http://docs.amazonaws.cn/cognito/latest/developerguide/images/scenario-authentication-cup2.png)


**存储令牌**  
您的应用程序必须能够存储不同大小的令牌。令牌大小变化的原因可能包括但不限于其它声明、编码算法的更改以及加密算法的更改等。当您在用户池中启用令牌吊销时，Amazon Cognito 会向 JSON Web 令牌添加其他声明，从而增加令牌大小。新 `origin_jti` 和 `jti` 声明已添加到访问和 ID 令牌中。有关令牌撤销的更多信息，请参阅[撤销令牌](https://docs.amazonaws.cn/cognito/latest/developerguide/token-revocation.html)。

**重要**  
最佳实践是在应用程序环境中保护传输和存储中的所有令牌。令牌可以包含有关用户的个人识别信息，以及有关用于用户池的安全模型的信息。

**自定义令牌**  
您可以自定义 Amazon Cognito 传递给应用程序的访问令牌和 ID 令牌。在 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 中，您可以添加、修改和隐藏令牌声明。令牌生成前触发器是一个 Lambda 函数，Amazon Cognito 会向其发送一组默认声明。声明包括 OAuth 2.0 范围、用户池群组成员资格、用户属性等。然后，该函数可以根据这些信息在运行时进行更改，并将更新的令牌声明返回给 Amazon Cognito。

使用版本 2 事件自定义访问令牌需要支付额外费用。有关更多信息，请参阅 [Amazon Cognito 定价](https://www.amazonaws.cn/cognito/pricing/)。

**Topics**
+ [

# 了解身份（ID）令牌
](amazon-cognito-user-pools-using-the-id-token.md)
+ [

# 了解访问令牌
](amazon-cognito-user-pools-using-the-access-token.md)
+ [

# 刷新令牌
](amazon-cognito-user-pools-using-the-refresh-token.md)
+ [

# 通过令牌撤销来结束用户会话
](token-revocation.md)
+ [

# 验证 JSON Web 令牌
](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)
+ [

# 管理用户池令牌到期和缓存
](amazon-cognito-user-pools-using-tokens-caching-tokens.md)

# 了解身份（ID）令牌
ID 令牌

ID 令牌是一个 [JSON Web 令牌（JWT）](https://tools.ietf.org/html/rfc7519)，其中包含有关经身份验证的用户的身份声明，如 `name`、`email` 和 `phone_number`。您可以在应用程序中使用此身份信息。此外，ID 令牌还可用于针对资源服务器或服务器应用程序对用户进行身份验证。您还可以将应用程序外部的 ID 令牌用于 Web API 操作。在这些情况下，您必须先验证 ID 令牌的签名，然后才能信任 ID 令牌内的任何声明。请参阅[验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

您可以将 ID 令牌过期时间设置为 5 分钟到 1 天之间的任何值。您可以按应用程序客户端设置此值。

**重要**  
当您的用户使用托管登录信息登录时，Amazon Cognito 会设置有效期为 1 小时的会话 Cookie。如果您在应用程序中使用托管登录信息进行身份验证，并为访问和 ID 令牌指定不到 1 小时的最短持续时间，则您的用户在 Cookie 过期前仍将拥有有效的会话。如果用户的令牌在一小时的会话期间过期，则用户可以刷新他们的令牌，而无需重新身份验证。

## ID 令牌标头


标头包含两部分信息：密钥 ID (`kid`) 和算法 (`alg`)。

```
{
"kid" : "1234example=",
"alg" : "RS256"
}
```

**`kid`**  
 密钥 ID。其值指示用于保护令牌的 JSON Web Signature (JWS) 的密钥。您可以在`jwks_uri`终端节点上查看您的用户池签 IDs 名密钥。  
有关 `kid` 参数的更多信息，请参阅[密钥标识符 (kid) 标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.5)。

**`alg`**  
Amazon Cognito 用于保护访问令牌的加密算法。用户池使用 RS256 加密算法，即带有 SHA-256 的 RSA 签名。  
有关 `alg` 参数的更多信息，请参阅[算法（alg）标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.4)。

## ID 令牌默认有效载荷


这是来自 ID 令牌的示例有效载荷。它包含有关经过身份验证的用户的声明。有关 OpenID Connect（OIDC）标准声明的更多信息，请参阅 [OIDC 标准声明](http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)列表。您可以使用 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 添加自有设计的声明。

```
<header>.{
    "sub": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "cognito:groups": [
        "test-group-a",
        "test-group-b",
        "test-group-c"
    ],
    "email_verified": true,
    "cognito:preferred_role": "arn:aws:iam::111122223333:role/my-test-role",
    "iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_example",
    "cognito:username": "my-test-user",
    "middle_name": "Jane",
    "nonce": "abcdefg",
    "origin_jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "cognito:roles": [
        "arn:aws:iam::111122223333:role/my-test-role"
    ],
    "aud": "xxxxxxxxxxxxexample",
    "identities": [
        {
            "userId": "amzn1.account.EXAMPLE",
            "providerName": "LoginWithAmazon",
            "providerType": "LoginWithAmazon",
            "issuer": null,
            "primary": "true",
            "dateCreated": "1642699117273"
        }
    ],
    "event_id": "64f513be-32db-42b0-b78e-b02127b4f463",
    "token_use": "id",
    "auth_time": 1676312777,
    "exp": 1676316377,
    "iat": 1676312777,
    "jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "email": "my-test-user@example.com"
}
.<token signature>
```

**`sub`**  
经过身份验证的用户的唯一标识符（[UUID](cognito-terms.md#terms-uuid)）或主题。用户名在您的用户群体中可能不是唯一的。`sub` 声明是识别给定用户的最佳方法。

**`cognito:groups`**  
以您的用户为成员的用户群体组的名称数组。组可以是您提供给应用程序的标识符，也可以从身份池为首选 IAM 角色生成请求。

**`cognito:preferred_role`**  
与用户的最高优先级用户池组关联的 IAM 角色的 ARN。有关您的用户池如何选择此角色声明的更多信息，请参阅[将优先级值分配到组](cognito-user-pools-user-groups.md#assigning-precedence-values-to-groups)。

**`iss`**  
颁发令牌的身份提供者。声明采用以下格式。  
`https://cognito-idp.<Region>.amazonaws.com/<your user pool ID>`

**`cognito:username`**  
用户池中用户的用户名。

**`nonce`**  
`nonce`声明来自同名参数，您可以将其添加到对 OAuth 2.0 `authorize` 终端节点的请求中。添加参数时，`nonce` 声明包含在 Amazon Cognito 颁发的 ID 令牌中，您可以使用它来防范重播攻击。如果在您的请求中未提供 `nonce` 值，当您通过第三方身份提供商进行身份验证时，Amazon Cognito 会自动生成并验证随机数，然后将其作为 `nonce` 声明添加到 ID 令牌中。Amazon Cognito 中的 `nonce` 声明的实现基于 [OIDC 标准](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation)。

**`origin_jti`**  
与用户的刷新令牌关联的令牌撤消标识符。Amazon Cognito 在检查您是否通过[撤销端点](revocation-endpoint.md)或 API 操作撤销了用户的令牌时会引用该`origin_jti`声明。[RevokeToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)当您撤销令牌时，Amazon Cognito 会使所有具有相同 `origin_jti` 值的访问令牌和 ID 令牌失效。

**`cognito:roles`**  
与您的用户组关联的 IAM 角色的名称的数组。每个用户池组可以有一个与之关联的 IAM 角色。此数组显示了您的用户组的所有 IAM 角色，不按优先级排列。有关更多信息，请参阅 [向用户池添加组](cognito-user-pools-user-groups.md)。

**`aud`**  
对用户进行身份验证的用户群体应用程序客户端。Amazon Cognito 在访问令牌 `client_id` 声明中呈现相同的值。

**`identities`**  
用户的 `identities` 属性的内容。该属性包含有关您通过联合登录或通过[将联合用户与本地配置文件关联](cognito-user-pools-identity-federation-consolidate-users.md)而与用户关联的每个第三方身份提供者配置文件的信息。此信息包含其提供商名称、提供商唯一 ID 和其它元数据。

**`token_use`**  
令牌的预期用途。在 ID 令牌中，其值为 `id`。

**`auth_time`**  
您的用户完成身份验证的身份验证时间，采用 Unix 时间格式。

**`exp`**  
您的用户令牌的过期时间，采用 Unix 时间格式。

**`iat`**  
Amazon Cognito 颁发您的用户令牌的时间，采用 Unix 时间格式。

**`jti`**  
JWT 的唯一标识符。

ID 令牌可包含 [OIDC 标准声明](https://openid.net/specs/openid-connect-core-1_0.html#Claims)中所定义的 OIDC 标准声明。ID 令牌还可包含您在用户池中定义的自定义属性。无论属性类型如何，Amazon Cognito 都会将自定义属性值作为字符串写入 ID 令牌。

**注意**  
用户池自定义属性始终以 `custom:` 为前缀。

## ID 令牌签名


ID 令牌的签名根据 JWT 令牌的标头和负载计算。在您接受应用程序收到的任何 ID 令牌中的声明之前，请验证该令牌的签名。有关更多信息，请参阅“验证 JSON Web 令牌”。[验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

# 了解访问令牌
访问令牌

用户池访问令牌包含有关经身份验证的用户声明、用户组列表以及作用域列表。访问令牌的目的是授权执行 API 操作。您的用户池接受访问令牌以授权用户执行自助操作。例如，您可以使用访问令牌授予用户访问权限以添加、更改或删除用户属性。

通过访问令牌中的 [OAuth 2.0 作用](https://www.rfc-editor.org/rfc/rfc6749#section-3.3)域（源自您添加到用户池中的自定义范围），您可以授权您的用户从 API 检索信息。例如，Amazon API Gateway 支持使用 Amazon Cognito 访问令牌进行授权。您可以使用用户池中的信息填充 REST API 授权方，也可以使用 Amazon Cognito 作为 HTTP API 的 JSON 网络令牌（JWT）授权方。要生成具有自定义作用域的访问令牌，您必须通过用户池[公有端点](https://docs.amazonaws.cn/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)请求访问令牌。

借助基础版或增值版[功能计划](cognito-sign-in-feature-plans.md)，您还可以实施令牌生成前 Lambda 触发器，在运行时为您的访问令牌添加作用域。有关更多信息，请参阅 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md)。

用户的 `openid` 作用域的访问令牌，是允许通过 [userInfo 端点](userinfo-endpoint.md)请求有关您的用户属性的更多信息的权限。来自 `userInfo` 端点的信息量源自访问令牌中的额外作用域：例如，`profile` 用于获取所有用户数据，`email` 用于获取用户的电子邮件地址。

用户的 `aws.cognito.signin.user.admin` 作用域的访问令牌，是读取和写入用户属性、列出身份验证因素、配置多重身份验证（MFA）首选项以及管理记住的设备的权限。您的访问令牌授予此范围的属性访问权限级别与您分配给应用程序客户端的属性 read/write 权限相匹配。

访问令牌是 [JSON Web 令牌 (JWT)](https://www.rfc-editor.org/rfc/rfc7519)。访问令牌的标头与 ID 令牌具有相同的结构。Amazon Cognito 使用与签署 ID 令牌的密钥所不同的密钥对访问令牌进行签名。访问密钥 ID (`kid`) 声明的值与来自同一用户会话的 ID 令牌中 `kid` 声明的值不匹配。在您的应用程序代码中，单独验证 ID 令牌和访问令牌。在验证签名之前，请勿信任访问令牌中的声明。有关更多信息，请参阅 [验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。您可以将访问令牌过期时间设置为 5 分钟到 1 天之间的任何值。您可以按应用程序客户端设置此值。

**重要**  
对于访问令牌和 ID 令牌，如果使用托管登录，请勿将最小值指定为少于一小时。托管登录会设置有效期为一小时的浏览器 Cookie。如果您将访问令牌的持续时间配置为小于一小时，这不会影响托管登录 Cookie 的有效性，也不会影响用户在初始登录后一小时内无需其他凭证即可重新进行身份验证的能力。

## 访问令牌标头


标头包含两部分信息：密钥 ID (`kid`) 和算法 (`alg`)。

```
{
"kid" : "1234example="
"alg" : "RS256",
}
```

**`kid`**  
 密钥 ID。其值指示用于保护令牌的 JSON Web Signature (JWS) 的密钥。您可以在`jwks_uri`终端节点上查看您的用户池签 IDs 名密钥。  
有关 `kid` 参数的更多信息，请参阅[密钥标识符 (kid) 标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.5)。

**`alg`**  
Amazon Cognito 用于保护访问令牌的加密算法。用户池使用 RS256 加密算法，即带有 SHA-256 的 RSA 签名。  
有关 `alg` 参数的更多信息，请参阅[算法（alg）标头参数](https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41#section-4.4)。

## 访问令牌默认有效载荷


这是来自访问令牌的示例负载。有关更多信息，请参阅 [JWT 声明](https://tools.ietf.org/html/rfc7519#section-4)。您可以使用 [令牌生成前 Lambda 触发器](user-pool-lambda-pre-token-generation.md) 添加自有设计的声明。

```
<header>.
{
   "sub":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "device_key": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "cognito:groups":[
      "testgroup"
   ],
   "iss":"https://cognito-idp.us-west-2.amazonaws.com/us-west-2_example",
   "version":2,
   "client_id":"xxxxxxxxxxxxexample",
   "aud": "https://api.example.com",
   "origin_jti":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "event_id":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "token_use":"access",
   "scope":"phone openid profile resourceserver.1/appclient2 email",
   "auth_time":1676313851,
   "exp":1676317451,
   "iat":1676313851,
   "jti":"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
   "username":"my-test-user"
}
.<token signature>
```

**`sub`**  
经过身份验证的用户的唯一标识符（[UUID](cognito-terms.md#terms-uuid)）或主题。用户名在您的用户群体中可能不是唯一的。`sub` 声明是识别给定用户的最佳方法。

**`cognito:groups`**  
以您的用户为成员的用户群体组的名称数组。

**`iss`**  
颁发令牌的身份提供者。声明采用以下格式。  
`https://cognito-idp.us-east-1.amazonaws.com/us-east-1_EXAMPLE`

**`client_id`**  
对用户进行身份验证的用户群体应用程序客户端。Amazon Cognito 在 ID 令牌 `aud` 声明中呈现相同的值。

**aud**  
访问令牌要授权的 API 的 URL。仅当您的应用程序向授权服务器请求[资源绑定](cognito-user-pools-define-resource-servers.md#cognito-user-pools-resource-binding)时才会显示。

**`origin_jti`**  
与用户的刷新令牌关联的令牌撤消标识符。Amazon Cognito 在检查您是否通过[撤销端点](revocation-endpoint.md)或 API 操作撤销了用户的令牌时会引用该`origin_jti`声明。[RevokeToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)当您撤销令牌时，Amazon Cognito 将不再对访问权限以及具有相同 `origin_jti` 值的 ID 令牌进行验证。

**`token_use`**  
令牌的预期用途。在访问令牌中，其值为 `access`。

**`scope`**  
向登录用户发布的 OAuth 2.0 范围列表。作用域定义令牌为`userInfo`端点上的外部 APIs、用户自助服务操作和用户数据提供的访问权限。[令牌端点](token-endpoint.md) 中的令牌可以包含您的应用程序客户端支持的任何作用域。来自 Amazon Cognito API 登录的令牌仅包含作用域 `aws.cognito.signin.user.admin`。

**`auth_time`**  
您的用户完成身份验证的身份验证时间，采用 Unix 时间格式。

**`exp`**  
您的用户令牌的过期时间，采用 Unix 时间格式。

**`iat`**  
Amazon Cognito 颁发您的用户令牌的时间，采用 Unix 时间格式。

**`jti`**  
JWT 的唯一标识符。

**`username`**  
用户池中用户的用户名。

**更多资源**
+ [如何在 Amazon Cognito 用户池中自定义访问令牌](https://www.amazonaws.cn/blogs/security/how-to-customize-access-tokens-in-amazon-cognito-user-pools/)

## 访问令牌签名


访问令牌的签名使用在 `.well-known/jwks.json` 端点公布的密钥进行签名，可验证令牌标头和有效载荷的完整性。当您使用访问令牌授权外部访问时 APIs，请务必将您的 API 授权方配置为根据签名该签名的密钥来验证此签名。有关更多信息，请参阅 [验证 JSON Web 令牌](amazon-cognito-user-pools-using-tokens-verifying-a-jwt.md)。

# 刷新令牌
刷新令牌

您可以使用刷新令牌来检索新的 ID 令牌和访问令牌。默认情况下，刷新令牌会在您的应用程序用户登录用户池的 30 天后过期。当您为用户池创建应用程序时，您可以将应用程序的刷新令牌到期时间设置为介于 60 分钟和 10 年之间的任何值。

## 使用刷新令牌获取新的访问权限和身份令牌
刷新令牌

Amazon Cognito 会在通过托管登录的授权代码流程以及 API 操作或 SDK 方法成功完成身份验证后，颁发刷新令牌。刷新令牌会返回新的 ID 和访问令牌，以及可选的新刷新令牌。可以通过以下方式使用刷新令牌。

**GetTokensFromRefreshToken**  
[GetTokensFromRefreshToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)API 操作从有效的刷新令牌中发布新的 ID 和访问令牌。如果您启用了刷新令牌轮换，则还会获得新的刷新令牌。

**InitiateAuth 和 AdminitiateAuth**  
[AdminInitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)或 [InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 操作包括`REFRESH_TOKEN_AUTH`身份验证流程。在此流程中，您可以传递刷新令牌，并获得新的 ID 令牌和访问令牌。在启用[刷新令牌轮换](#using-the-refresh-token-rotation)的应用程序客户端中，您无法使用 `REFRESH_TOKEN_AUTH` 进行身份验证。

**OAuth 令牌端点**  
在具有[域](cognito-user-pools-assign-domain.md)的用户池中，[令牌端点](token-endpoint.md)支持 `refresh_token` 授予类型，可通过一个有效的刷新令牌颁发新的 ID 令牌、访问令牌，并（通过[刷新令牌轮换](#using-the-refresh-token-rotation)）选择性地颁发刷新令牌。

## 刷新令牌轮换


您可以选择在应用程序客户端中配置刷新令牌轮换。通过刷新令牌轮换，您的客户端在每次刷新令牌时都会使原始刷新令牌失效，并颁发一个新的刷新令牌。启用此设置后，所有形式的令牌刷新请求成功后，都会返回一个新的 ID 令牌、访问令牌*和*刷新令牌。禁用此设置后，令牌刷新请求仅返回新的访问令牌和 ID 令牌，并且原始刷新令牌仍然有效。新的刷新令牌的有效期为原始刷新令牌的剩余有效时间。可以将[应用程序客户端](user-pool-settings-client-apps.md)配置为轮换刷新令牌或保留使用原始刷新令牌。为了支持短暂时间内的重试操作，还可以为原始刷新令牌配置最长 60 秒的宽限期。

**有关刷新令牌轮换的需知信息**
+ 启用刷新令牌轮换后，您的用户池的 JSON Web 令牌中会添加新的声明。`origin_jti` 和 `jti` 声明已添加到访问和 ID 令牌中。这些索赔增加了索赔的规模 JWTs。
+ 刷新令牌轮换与 `REFRESH_TOKEN_AUTH` 身份验证流程不兼容。要实现刷新令牌轮换，您必须在应用程序客户端中禁用此身份验证流程，并将您的应用程序设计为使用 [GetTokensFromRefreshToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)API 操作或等效的 SDK 方法提交令牌刷新请求。
+ 当刷新令牌轮换未启用时，您可以使用 `GetTokensFromRefreshToken` 或 `REFRESH_TOKEN_AUTH` 来完成令牌刷新请求。
+ 当您的用户池中启用了[设备记忆](amazon-cognito-user-pools-device-tracking.md)功能时，您必须在 `GetTokensFromRefreshToken` 请求中提供设备密钥。如果您的用户没有您的应用程序在初始身份验证请求中提交的已确认设备密钥，Amazon Cognito 会颁发一个新的密钥。在此置下进行令牌刷新时，无论您是在 `AuthParameters` 中指定了设备密钥，还是在身份验证响应中收到了新的设备密钥，都必须提供该设备密钥。
+ 可以在 `GetTokensFromRefreshToken` 请求中将 `ClientMetadata` 传递给令牌生成前 Lambda 触发器。这些数据将传递至触发器的输入事件，并提供额外上下文信息，可用于您的 Lambda 函数的自定义逻辑。

作为一项安全最佳实践，请在应用程序客户端启用刷新令牌轮换。

------
#### [ Enable refresh token rotation (console) ]

以下过程可用于为您的应用程序客户端打开或关闭刷新令牌轮换。此过程需要一个现有的应用程序客户端。要了解有关创建应用程序客户端的更多信息，请参阅[特定于应用程序的应用程序客户端设置](user-pool-settings-client-apps.md)。

**启用刷新令牌轮换**

1. 转到 [Amazon Cognito 控制台](https://console.amazonaws.cn/cognito/home)。如果出现提示，请输入您的 Amazon 凭据。

1. 选择 **User Pools**（用户池）。

1. 从列表中选择现有用户池。

1. 导航到**应用程序客户端**菜单，然后选择一个现有的应用程序客户端。

1. 从页面的**应用程序客户端信息**部分选择**编辑**。

1. 在**高级安全配置**下，找到**启用刷新令牌轮换**选项。

1. 要启用轮换，请选中该复选框。要禁用轮换，请取消选中该复选框。

1. 在**刷新令牌轮换宽限期**下，输入要设置为撤销轮换刷新令牌之前的延迟时间（最多 60 秒）。

------
#### [ Enable refresh token rotation (API) ]

在[CreateUserPoolClient](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)或 [UpdateUserPoolClient](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)API 请求中配置刷新令牌轮换。以下部分请求正文用于开启刷新令牌轮换并将宽限期设置为十秒。

```
"RefreshTokenRotation" : {
   "Feature" : "ENABLED,
   "RetryGracePeriodSeconds" : 10
}
```

------

## API 和 SDK 令牌刷新


可通过两种方法使用刷新令牌通过用户池 API 获取新 ID 令牌和访问令牌，具体取决于刷新令牌轮换是否已启用。在启用刷新令牌轮换的应用程序客户端中，使用 [GetTokensFromRefreshToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)API 操作。在没有刷新令牌轮换的应用程序客户端中，使用[AdminInitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)或 [InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 操作`REFRESH_TOKEN_AUTH`流程。

**注意**  
用户可以在[托管登录](cognito-user-pools-managed-login.md)或使用您构建的自定义应用程序 Amazon SDKs 和 Amazon Cognito API 操作中使用用户池进行身份验证。`REFRESH_TOKEN_AUTH` 流程和 `GetTokensFromRefreshToken` 都可以为托管登录用户完成令牌刷新。自定义应用程序中的令牌刷新不会影响托管登录会话。这些会话是在浏览器 Cookie 中设置的，有效期为 1 小时。`GetTokensFromRefreshToken` 响应会发出新的 ID 令牌、访问令牌、可选刷新令牌，但不会续订托管登录会话 Cookie。  
`REFRESH_TOKEN_AUTH` 在启用刷新令牌轮换的应用程序客户端中不可用。

------
#### [ GetTokensFromRefreshToken ]

[GetTokensFromRefreshToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GetTokensFromRefreshToken.html)返回您使用刷新令牌授权的请求中的新 ID、访问和刷新令牌。以下是 `GetTokensFromRefreshToken` 的一个请求正文示例。您可以通过此操作发起的请求，向 Lambda 触发器提交客户端元数据。

```
{
    "RefreshToken": "eyJjd123abcEXAMPLE",
    "ClientId": "1example23456789",
    "ClientSecret": "myappclientsecret123abc",
    "ClientMetadata": { 
      "MyMetadataKey" : "MyMetadataValue" 
   },
}
```

------
#### [ AdminInitiateAuth/InitiateAuth ]

要在刷新令牌轮换处于非活动状态时使用刷新令牌，请使用[AdminInitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)或 [InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 操作。为 `AuthFlow` 参数传递 `REFRESH_TOKEN_AUTH`。在 `AuthFlow` 的 `AuthParameters` 属性中，将用户的刷新令牌作为 `"REFRESH_TOKEN"` 的值进行传递。在您的 API 请求通过所有质询后，Amazon Cognito 会返回新的 ID 和访问令牌。

以下是使用 `InitiateAuth` 或 `AdminInitiateAuth` API 刷新令牌的请求正文示例。

```
{
    "AuthFlow": "REFRESH_TOKEN_AUTH",
    "ClientId": "1example23456789",
    "UserPoolId": "us-west-2_EXAMPLE",
    "AuthParameters": {
        "REFRESH_TOKEN": "eyJjd123abcEXAMPLE",
        "SECRET_HASH": "kT5acwCVrbD6JexhW3EQwnRSe6fLuPTRkEQ50athqv8="
    }
}
```

------

## OAuth 令牌刷新


您也可以将刷新令牌提交给用户池中您在其中配置了域的[令牌端点](token-endpoint.md)。在请求正文中，加入 `refresh_token` 的 `grant_type` 值和用户刷新令牌的 `refresh_token` 值。

可在启用和未启用刷新令牌轮换的应用程序客户端向令牌端点发出请求。当刷新令牌轮换启用时，令牌端点会返回一个新的刷新令牌。

以下是刷新令牌的一个请求示例。

```
POST /oauth2/token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZGpjOTh1M2ppZWRtaTI4M2V1OTI4OmFiY2RlZjAxMjM0NTY3ODkw
Content-Length: **

client_id=1example23456789&grant_type=refresh_token&refresh_token=eyJjd123abcEXAMPLE
```

## 撤消刷新令牌
撤消刷新令牌

您可以撤销属于用户的刷新令牌。有关撤销令牌的更多信息，请参阅[通过令牌撤销来结束用户会话](token-revocation.md)。

**注意**  
撤销刷新令牌将撤销 Amazon Cognito 从具有该令牌的刷新请求中发出的所有 ID 和访问令牌。

要让用户退出当前所有登录会话，请使用或 API 请求撤消其所有令牌。[GlobalSignOut[AdminUserGlobalSignOut](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html)](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html)注销用户后，会发生以下影响。
+ 用户的刷新令牌无法获取该用户的新令牌。
+ 用户的访问令牌无法发出经过令牌授权的 API 请求。
+ 用户必须重新进行身份验证以获取新的令牌。由于托管登录会话 Cookie 不会自动过期，因此，用户可以使用会话 Cookie 重新进行身份验证，而无需额外提示输入凭证。注销托管登录用户后，会将这些用户重定向到[注销端点](logout-endpoint.md)，Amazon Cognito 将在其中清除用户的会话 Cookie。

使用刷新令牌，您可以将用户的会话长时间保留在您的应用程序中。随着时间推移，您的用户可能希望取消对他们使用刷新令牌保持登录状态的某些应用程序的授权。要将您的用户从单个会话注销，请撤销其刷新令牌。当您的用户想要退出所有经过身份验证的会话时，请生成 [GlobalSignOut](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html)API 请求。应用程序可以为用户提供一个选择，如**从所有设备注销**。`GlobalSignOut` 接受用户的有效（即未更改、未过期、未撤销的）访问令牌。由于此 API 经过令牌授权，因此一个用户无法使用它来发起另一个用户的注销。

但是，您可以生成一个 [AdminUserGlobalSignOut](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html)API 请求，该请求由您使用您的 Amazon 凭据进行授权，以便将任何用户从其所有设备上注销。管理员应用程序必须使用 Amazon 开发者凭据调用此 API 操作，并将用户池 ID 和用户名作为参数传递。`AdminUserGlobalSignOut` API 可以在用户池中注销任何用户。

有关您可以使用 Amazon 凭证或用户访问令牌授权的请求的更多信息，请参阅[按授权模型分组的 API 操作列表](authentication-flows-public-server-side.md#user-pool-apis-auth-unauth)。

# 通过令牌撤销来结束用户会话
撤销令牌

您可以使用以下方法撤销刷新令牌和最终用户会话。撤销刷新令牌后，先前由该刷新令牌颁发的所有访问令牌都将失效。向用户颁发的其他刷新令牌不受影响。

**RevokeToken 操作**  
[RevokeToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)撤消给定刷新令牌的所有访问令牌，包括来自交互式登录的初始访问令牌。此操作不会影响用户的任何其他刷新令牌，也不会影响由这些其他刷新令牌派生的 ID 令牌和访问令牌。

**撤销端点**  
[撤销端点](revocation-endpoint.md)会撤销给定的刷新令牌以及该刷新令牌生成的所有 ID 令牌和访问令牌。此端点还会撤销交互式登录的初始访问令牌。对此端点的请求不会影响用户的任何其他刷新令牌，也不会影响由这些其他刷新令牌派生的 ID 令牌和访问令牌。

**GlobalSignOut 操作**  
[GlobalSignOut](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html)是一种自助操作，用户使用其访问令牌对其进行授权。此操作会撤销请求用户的所有刷新、ID 和访问令牌。

**AdminUserGlobalSignOut 操作**  
[AdminUserGlobalSignOut](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html)是管理员使用 IAM 凭证授权的服务器端操作。此操作会撤销目标用户的所有刷新、ID 和访问令牌。

**有关撤销令牌的需知信息**
+ 您撤销刷新令牌的请求必须包括用于获取该令牌的客户端 ID。
+ 用户池 JWTs 是独立的，其签名和到期时间是在创建令牌时分配的。已撤销令牌无法与任何需要令牌的 Amazon Cognito API 调用一起使用。但是，如果使用任何验证令牌签名和过期的 JWT 库进行验证，已撤销令牌仍然有效。
+ 当您创建新的用户池客户端时，默认会启用令牌撤销。
+ 您只能在启用令牌撤销的应用程序客户端中撤销刷新令牌。
+ 启用令牌吊销后，Amazon Cognito JSON Web 令牌中会添加新的声明。`origin_jti` 和 `jti` 声明已添加到访问和 ID 令牌中。这些声明增加应用程序客户端访问和 ID 令牌的大小。
+ 当您在之前已启用令牌撤销的应用程序客户端中禁用令牌撤销时，已撤销的令牌不会再次启用。
+ 当您[禁用用户账户](how-to-manage-user-accounts.md#manage-user-accounts-enable-disable)（会撤销刷新和访问令牌）后，如果您再次启用该用户账户，已撤销的令牌不会启用。
+ 使用 Amazon Web Services 管理控制台、或 Amazon API 创建新的用户池客户端时 Amazon CLI，默认情况下会启用令牌撤销。

## 启用令牌撤销


在您为现有的用户池客户端撤销令牌前，必须启用令牌撤销。您可以使用 Amazon CLI 或 Amazon API 为现有用户池客户端启用令牌撤销。为此，请调用 `aws cognito-idp describe-user-pool-client` CLI 命令或 `DescribeUserPoolClient` API 操作以从应用程序客户端检索当前设置。然后调用 `aws cognito-idp update-user-pool-client` CLI 命令或 `UpdateUserPoolClient` API 操作。包括来自您的应用程序客户端的当前设置并将 `EnableTokenRevocation` 参数设置为 `true`。

要使用 Amazon Cognito API 或软件开发工具包创建或修改启用令牌撤销功能的 Amazon 应用程序客户端，请在[CreateUserPoolClient](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html)您的[UpdateUserPoolClient](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPoolClient.html)或 API 请求中包含以下参数。

```
"EnableTokenRevocation": true
```

要在 Amazon Cognito 控制台中配置令牌撤销，请从用户池的**应用程序客户端**菜单中选择一个应用程序客户端。在**应用程序客户端信息**中选择**编辑**按钮，然后在**高级配置**下启用或禁用令牌撤销。

## 撤销令牌


您可以使用 [RevokeToken](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html)API 请求撤消刷新令牌，例如使用 `[aws cognito-idp revoke-token](https://docs.amazonaws.cn/cli/latest/reference/cognito-idp/revoke-token.html)` CLI 命令。您也可以使用[撤销端点](revocation-endpoint.md)撤销令牌。此端点在您将域添加到用户池后可用。您可以在 Amazon Cognito 托管域或您的自定义域上使用撤销端点。

以下是示例 `RevokeToken` API 请求的正文。

```
{
   "ClientId": "1example23456789",
   "ClientSecret": "abcdef123456789ghijklexample",
   "Token": "eyJjdHkiOiJKV1QiEXAMPLE"
}
```

以下是对使用自定义域的用户池的 `/oauth2/revoke` 端点发出的 cURL 请求示例。

```
curl --location 'auth.mydomain.com/oauth2/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic Base64Encode(client_id:client_secret)' \
--data-urlencode 'token=abcdef123456789ghijklexample' \
--data-urlencode 'client_id=1example23456789'
```

除非您的应用程序客户端具有客户端密钥，否则 `RevokeToken` 操作和 `/oauth2/revoke` 端点不需要额外授权。

# 验证 JSON Web 令牌
验证 JSON Web 令牌

JSON 网络令牌 (JWTs) 可以轻松解码、读取和修改。修改过的访问令牌会带来权限提升的风险。修改过的 ID 令牌会带来冒充身份的风险。您的应用程序信任您的用户池作为令牌颁发者，但如果用户拦截了传输中的令牌，该怎么办？ 您必须确保应用程序收到的令牌与 Amazon Cognito 颁发的令牌一致。

Amazon Cognito 颁发令牌，这些令牌使用 OpenID Connect（OIDC）规范的某些完整性和保密性特征。用户池令牌通过到期时间、颁发者和数字签名等对象来指示令牌的有效性。签名（`.` 分隔的 JWT 的第三个也是最后一个分段）是令牌验证的关键组件。恶意用户会修改令牌，但如果您的应用程序检索公钥并比较签名，则该令牌将不匹配。任何通过 OIDC 身份验证进行处理 JWTs 的应用程序都必须在每次登录时执行此验证操作。

在本页上，我们提出了一些一般和具体的验证建议 JWTs。在应用程序开发过程中，开发人员需要使用各种编程语言和平台。由于 Amazon Cognito 实施的 OIDC 足够接近公共规范，因此选择开发人员环境中任何声誉良好的 JWT 库都可以满足您的验证要求。

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

**Topics**
+ [

## 先决条件
](#amazon-cognito-user-pools-using-tokens-prerequisites)
+ [

## 使用验证令牌 aws-jwt-verify
](#amazon-cognito-user-pools-using-tokens-aws-jwt-verify)
+ [

## 了解和检查令牌
](#amazon-cognito-user-pools-using-tokens-manually-inspect)

## 先决条件
先决条件

您的库、SDK 或软件框架可能已经处理了本节中的任务。 Amazon SDKs 为应用程序中的 Amazon Cognito 用户池令牌处理和管理提供工具。 Amazon Amplify 包括检索和刷新 Amazon Cognito 令牌的功能。

有关更多信息，请参阅以下页面。
+ [将 Amazon Cognito 身份验证和授权与 Web 和移动应用程序集成](cognito-integrate-apps.md)
+ [使用 Amazon Cognito 身份提供商的代码示例 Amazon SDKs](https://docs.amazonaws.cn/cognito/latest/developerguide/service_code_examples.html)
+ *Amplify Dev Center*（Amplify 开发中心）中的 [Advanced workflows](https://docs.amplify.aws/lib/auth/advanced/q/platform/js/#retrieve-jwt-tokens)（高级工作流）

许多库可用于解码和验证 JSON Web 令牌 (JWT)。如果您要手动处理用于服务器端 API 处理的令牌，或者您使用的是其他编程语言，则这些库可以为您提供帮助。请参阅[用于处理 JWT 令牌库的 OpenID Foundation 列表](http://openid.net/developers/jwt/)。

## 使用验证令牌 aws-jwt-verify


在 Node.js 应用程序中， Amazon 建议使用该[aws-jwt-verify库](https://github.com/awslabs/aws-jwt-verify)来验证用户传递给您的应用程序的令牌中的参数。使用 `aws-jwt-verify`，您可以使用要为一个或多个用户池验证的声明值填充 `CognitoJwtVerifier`。它可以检查的一些值包括以下内容。
+ 该访问令牌或 ID 令牌的格式不正确或已过期，但具有有效的签名。
+ 这些访问令牌来自[正确的用户池和应用程序客户端](https://github.com/awslabs/aws-jwt-verify#verifying-jwts-from-amazon-cognito)。
+ 该访问令牌声明包含[正确的 OAuth 2.0 范围](https://github.com/awslabs/aws-jwt-verify#checking-scope)。
+ 对访问令牌和 ID 令牌进行签名的密钥[与用户池的 *JWKS URI* 中的签名密钥 `kid` 匹配](https://github.com/awslabs/aws-jwt-verify#the-jwks-cache)。

  JWKS URI 包含有关对用户令牌进行签名的私有密钥的公有信息。您可以在以下位置找到用户池的 JWKS URI：`https://cognito-idp.<Region>.amazonaws.com/<userPoolId>/.well-known/jwks.json`。

有关您可以在 Node.js 应用程序或 Amazon Lambda 授权方中使用的更多信息和示例代码，请参阅[https://github.com/awslabs/aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify)上 GitHub的。

## 了解和检查令牌


在将令牌检查与应用程序集成之前，请考虑一下 Amazon Cognito 是如何组装的。 JWTs从用户池中检索示例令牌。解码并详细检查它们，以了解它们的特征，并确定要验证的内容和时间。例如，您可能希望检查一个场景中的组成员资格，而在另一个场景中，您可能想要检查作用域。

以下各节描述了在准备应用程序时手动检查 Amazon Cognito JWTs 的过程。

### 确认 JWT 的结构
确认 JWT 的结构

JSON Web 令牌 (JWT) 包括三个部分，各部分之间有一个 `.`（圆点）分隔符。

**标题**  
Amazon Cognito 用来对令牌进行签名的密钥 ID `kid` 和 RSA 算法 `alg`。Amazon Cognito 使用 `alg` (`RS256`) 对令牌进行签名。`kid` 是对您的用户池持有的 2048 位 RSA 私有签名密钥的截断引用。

**有效载荷**  
令牌声明。在 ID 令牌中，声明包括用户属性和有关用户池 `iss` 和应用程序客户端 `aud` 的信息。在访问令牌中，有效载荷包括作用域、组成员资格、用户池身份 (`iss`) 和应用程序客户端 (`client_id`)。

**签名**  
签名不是像标头和有效载荷那样的可解码 base64url。它是从签名密钥和参数派生的 RSA256 标识符，您可以在 JWKS URI 中观察到这些标识符。

标头和有效载荷是以 base64url 编码的 JSON。您可以通过解码为起始字符 `eyJ` 的开头字符 `{` 来识别它们。如果用户向您的应用程序提供了以 base64url 编码的 JWT，但其格式不是 `[JSON Header].[JSON Payload].[Signature]`，则它不是有效的 Amazon Cognito 令牌，您可以将其丢弃。

以下示例应用程序使用 `aws-jwt-verify` 验证用户池令牌。

```
// cognito-verify.js
// Usage example: node cognito-verify.js eyJra789ghiEXAMPLE

const { CognitoJwtVerifier } = require('aws-jwt-verify');

// Replace with your Amazon Cognito user pool ID
const userPoolId = 'us-west-2_EXAMPLE';

async function verifyJWT(token) {
  try {
    const verifier = CognitoJwtVerifier.create({
      userPoolId,
      tokenUse: 'access', // or 'id' for ID tokens
      clientId: '1example23456789', // Optional, only if you need to verify the token audience
    });

    const payload = await verifier.verify(token);
    console.log('Decoded JWT:', payload);
  } catch (err) {
    console.error('Error verifying JWT:', err);
  }
}

// Example usage
if (process.argv.length < 3) {
  console.error('Please provide a JWT token as an argument.');
  process.exit(1);
}

const MyToken = process.argv[2];
verifyJWT(MyToken);
```

### 验证 JWT
验证 JWT 签名

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

**验证 JWT 令牌的签名**

1. 解码 ID 令牌。

   OpenID Foundation 还[维护用于处理 JWT 令牌的库列表](http://openid.net/developers/jwt/)。

   您也可以使用 Amazon Lambda 解码用户池 JWTs。有关更多信息，请参阅使用[解码和验证 Amazon Cognito J](https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt) WT 令牌。 Amazon Lambda

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

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

      ```
      https://cognito-idp.<Region>.amazonaws.com/<userPoolId>/.well-known/jwks.json
      ```

      有关更多 JWK 和 JWK 集的更多信息，请参阅 [JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517)。
**注意**  
Amazon Cognito 可能会轮换用户池中的签名密钥。最佳做法是使用 `kid` 作为缓存密钥在应用程序中缓存公有密钥，并定期刷新缓存。将您的应用程序收到的令牌中的 `kid` 与缓存进行比较。  
如果您收到的令牌的颁发者是正确的，但 `kid` 不同，则 Amazon Cognito 可能已经轮换了签名密钥。从您的用户池 `jwks_uri` 端点刷新缓存。

      这是个 `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 签名（JWS）。  
**算法（`alg`）**  
`alg` 标头参数表示用于保护 ID 令牌的加密算法。用户池使用 RS256加密算法，即带有 SHA-256 的 RSA 签名。有关 RSA 的更多信息，请参阅 [RSA 加密](https://tools.ietf.org/html/rfc3447)。  
**密钥类型（`kty`）**  
`kty` 参数标识与密钥结合使用的加密算法系列，例如，在本示例中为“RSA”。  
**RSA 指数（`e`）**  
`e` 参数包含 RSA 公有密钥的指数值。它以 base64URL UInt 编码的值表示。  
**RSA 模数（`n`）**  
`n` 参数包含 RSA 公有密钥的模数值。它以 base64URL UInt 编码的值表示。  
**使用（`use`）**  
`use` 参数描述了公有密钥的预期用途。在本示例中，`use` 值 `sig` 表示签名。

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

### 验证声明
验证声明

**验证 JWT 声明**

1. 通过以下方法之一，验证令牌是否未过期。

   1. 对令牌解码并将 `exp` 声明与当前时间进行比较。

   1. 如果您的访问令牌包含`aws.cognito.signin.user.admin`索赔，请向类似的 API 发送请求[GetUser](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_GetUser.html)。如果令牌已过期，您[使用访问令牌进行授权](https://docs.amazonaws.cn/cognito/latest/developerguide/user-pools-API-operations.html#user-pool-apis-auth-unauth)的 API 请求会返回错误。

   1. 在针对[userInfo 端点](userinfo-endpoint.md)的请求中提供您的访问令牌。如果您的令牌已过期，则请求会返回错误。

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

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

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

1. 检查 `token_use` 声明。
   + 如果您在 Web API 操作中只接受访问令牌，则其值必须为 `access`。
   + 如果您只使用 ID 令牌，则其值必须为 `id`。
   + 如果您同时使用 ID 令牌和访问令牌，则 `token_use` 声明必须为 `id` 或 `access`。

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

# 管理用户池令牌到期和缓存
缓存令牌

每次您想要获取新的 JSON Web 令牌（JWT）时，应用程序都必须成功完成以下请求之一。
+ 从[令牌端点](token-endpoint.md)请求客户端凭证或授权码[授予](https://www.rfc-editor.org/rfc/rfc6749#section-1.3)。
+ 从您的托管登录页面请求隐式授权。
+ 在 Amazon Cognito API 请求中对本地用户进行身份验证，例如。[InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)

您可以将用户池配置为将令牌设置为在数分钟、数小时或数天后过期。要确保应用程序的性能和可用性，请使用 Amazon Cognito 令牌至大约 75% 的令牌生命周期，并且仅在那时获取新令牌。您为应用程序构建的缓存解决方案可保持令牌可用，并可防止 Amazon Cognito 在您的请求速率过高时拒绝请求。客户端应用程序必须将令牌存储在内存缓存中。服务器端应用程序可以添加加密的缓存机制来存储令牌。

当您的用户池生成大量用户或 machine-to-machine活动时，您可能会遇到 Amazon Cognito 对您可以发出的令牌请求数量设定的限制。要减少您向 Amazon Cognito 端点发出的请求数量，可以安全地存储和重复使用身份验证数据，也可以实施指数回退和重试。

身份验证数据来自两类端点。Amazon Cognito [OAuth2.0 终端](https://docs.amazonaws.cn/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)节点包括令牌终端节点，该终端节点为客户端凭证和托管登录授权码请求提供服务。[服务端点](https://docs.amazonaws.cn/general/latest/gr/cognito_identity.html#cognito_identity_your_user_pools_region)应答用户池 API 请求，例如 `InitiateAuth` 和 `RespondToAuthChallenge`。每种类型的请求都有自己的限制。有关限制的更多信息，请参阅[Amazon Cognito 中的限额](quotas.md)。

## 使用 Amazon API Gateway 缓存 machine-to-machine访问令牌


借助 API Gateway 令牌缓存，您的应用程序可以扩展以响应大于 Amazon Cognito OAuth 终端节点默认请求速率配额的事件。

![\[API Gateway 为 M2M 维护访问令牌缓存的示意图。API 代理处理令牌请求，如果已经有一个缓存的令牌有效，则返回缓存的令牌。\]](http://docs.amazonaws.cn/cognito/latest/developerguide/images/user-pools-m2m-caching.png)


您可以缓存访问令牌，以便您的应用程序仅在缓存的令牌过期时才请求新的访问令牌。否则，您的缓存端点会从缓存中返回一个令牌。这会阻止对 Amazon Cognito API 端点的其他调用。当您使用 Amazon API Gateway 作为 [令牌端点](token-endpoint.md)的代理时，您的 API 会响应大多数原本会计入您的请求配额的请求，从而避免由于速率限制而导致的请求失败。

以下基于 API Gateway 的解决方案提供了低延迟、低代码/无代码的令牌缓存实施。API Gateway APIs 在传输过程中进行加密，也可以选择静态加密。API Gateway 缓存非常适合 OAuth 2.0 [客户端凭证授予](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4)，这是一种通常是大批量的授予类型，用于生成用于授权 machine-to-machine和微服务会话的访问令牌。在诸如流量激增导致您的微服务水平扩展的情况下，您最终可能会有许多系统使用相同的客户端凭据，但其数量超过用户池或应用程序客户端的 Amazon 请求速率限制。要保持应用程序可用性和低延迟，缓存解决方案是此类情况下的最佳实践。

在此解决方案中，您可以在 API 中定义一个缓存，以便为要在应用中请求的 OAuth 范围和应用程序客户端的每种组合存储单独的访问令牌。当您的应用程序发出与缓存键匹配的请求时，您的 API 会使用 Amazon Cognito 向与缓存键匹配的第一个请求颁发的访问令牌进行响应。当您的缓存键持续时间到期时，API 会将请求转发到令牌端点并缓存新的访问令牌。

**注意**  
您的缓存键持续时间必须短于应用程序客户端的访问令牌持续时间。

缓存密钥是您在请求正文`scope`参数中请求的 OAuth 作用域和请求`Authorization`标头的组合。`Authorization` 标头包含您的应用程序客户端 ID 和客户端密钥。您无需在应用程序中实施其他逻辑即可实施此解决方案。您只必须更新配置以更改用户池令牌端点的路径。

您也可以使用 [ElastiCache (Redis OSS)](https://docs.amazonaws.cn/elasticache/index.html) 实现令牌缓存。要使用 Amazon Identity and Access Management (IAM) 策略进行精细控制，请考虑 [Amazon DynamoDB](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/authentication-and-access-control.html#authentication) 缓存。

**注意**  
在 API Gateway 中缓存需要支付额外费用。[有关更多详细信息，请参阅定价。](https://www.amazonaws.cn/api-gateway/pricing)<a name="amazon-cognito-user-pools-using-tokens-caching-tokens-API-gateway-how-to"></a>

**使用 API Gateway 设置缓存代理**

1. 打开 [API Gateway 控制台](https://console.amazonaws.cn/apigateway/main/apis)，然后创建一个 REST API。

1. 在 **Resources**（资源）中，创建一个 POST 方法。

   1. 选择 HTTP **Integration type**（集成类型）。

   1. 选择 **Use HTTP proxy integration**（使用 HTTP 代理集成）。

   1. 输入 **Endpoint URL**（端点 URL）`https://<your user pool domain>/oauth2/token`。

1. 在 **Resources**（资源）中，配置缓存键。

   1. 编辑 POST 方法的 **Method request**（方法请求）。
**注意**  
此方法请求验证用于令牌请求中的 `client_secret_basic` 授权，其中客户端密钥被编码在 `Authorization` 请求标头中。对于使用 `client_secret_post` 授权方式对 JSON 请求正文的验证，应创建一个[数据模型](https://docs.amazonaws.cn/apigateway/latest/developerguide/models-mappings-models.html)，明确要求请求正文中必须包含 [client\$1secret](token-endpoint.md#post-token-request-parameters-in-body)。在此模型中，您的**请求验证程序**应**验证正文、查询字符串参数和标头**。

   1. 配置**请求验证程序**方法以**验证查询字符串参数和标头**。有关请求验证的更多信息，请参阅 *Amazon API Gateway 开发者指南*中的[请求验证](https://docs.amazonaws.cn/apigateway/latest/developerguide/api-gateway-method-request-validation.html)。

   1. 将您的 `scope` 参数和 `Authorization` 标头设置为缓存键。

      1. 将一个查询字符串添加到 **URL 查询字符串参数**。输入 `scope` 作为查询字符串的**名称**，然后选择**必填项**和**缓存**。

      1. 将一个标头添加到 **HTTP 请求标头**。输入 `Authorization` 作为请求标头的**名称**，然后选择**必填项**和**缓存**。

1. 在 **Stages**（阶段）中，配置缓存。

   1. 选择要修改的阶段，然后从**阶段详细信息**中选择**编辑**。

   1. 在**其他设置**下，对于**缓存设置**，开启**配置 API 缓存**选项。

   1. 选择 **Cache capacity**（缓存容量）。较高的缓存容量可以提高性能，但需要额外付费。

   1. 清除**需要授权**复选框。选择**继续**。

   1. API Gateway 仅将缓存策略应用于阶段级别的 GET 方法。您必须对 POST 方法应用缓存策略覆盖。

      展开您配置的阶段并选择 `POST` 方法。要为该方法创建缓存设置，请选择**创建覆盖**。

   1. 激活**启用方法缓存**选项。

   1. 输入 3600 秒的****缓存 time-to-live (TTL)****。选择**保存**。

1. 在 **Stages**（阶段）中，注意 **Invoke URL**（调用 URL）。

1. 更新您的应用程序，以将令牌请求发布到 API 的 **Invoke URL**（调用 URL）而不是用户池的 `/oauth2/token` 端点。