

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

# 在授权代码授予中使用 PKCE
<a name="using-pkce-in-authorization-code"></a>

Amazon Cognito 在授权代码授予中支持代码交换的证明密钥（PKCE）身份验证。PKCE 是公共客户端的 OAuth 2.0 授权代码授予的扩展。PKCE 可防止兑换拦截的授权代码。

## Amazon Cognito 如何使用 PKCE
<a name="how-pkce-works"></a>

要开始使用 PKCE 进行身份验证，您的应用程序必须生成一个唯一的字符串值。此字符串是代码验证程序，Amazon Cognito 使用该密钥值将请求初始授权授予的客户端与使用授权代码交换令牌的客户端进行比较。

您的应用程序必须对代码验证器字符串应用 SHA256 哈希值，并将结果编码为 base64。将经过哈希处理的字符串作为请求正文中的 `code_challenge` 参数传递到 [对端点授权](authorization-endpoint.md)。当您的应用程序将授权代码交换为令牌时，它必须以纯文本形式包括代码验证程序字符串，作为请求正文中的 `code_verifier` 参数传递到 [令牌端点](token-endpoint.md)。Amazon Cognito 对代码验证器执行相同的 hash-and-encode操作。Amazon Cognito 仅在确定代码验证程序产生的代码质询与在授权请求中收到的代码质询相同时，才会返回 ID 令牌、访问令牌和刷新令牌。

**使用 PKCE 实现授权授予流程**

1. 打开 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/home)。如果出现提示，请输入您的 AWS 凭据。

1. 选择**用户池**。

1. 从列表中选择一个现有用户池，或创建一个用户池。如果您创建用户池，系统将在向导期间提示您设置应用程序客户端并配置托管登录。

   1. 如果您创建新用户池，请在引导式设置期间设置应用程序客户端并配置托管登录。

   1. 如果您配置现有用户池，请添加[域](cognito-user-pools-assign-domain.md)和[公共应用程序客户端](user-pool-settings-client-apps.md)（如果尚未添加）。

1. 生成一个随机的字母数字字符串 [通常是一个全局唯一标识符（[UUID](cognito-terms.md#terms-uuid)）]，以便为 PKCE 创建代码质询。此字符串是您将在发送给 [令牌端点](token-endpoint.md) 的请求中提交的 `code_verifier` 参数的值。

1. 用 SHA256 算法对`code_verifier`字符串进行哈希处理。将哈希操作的结果编码为 base64。此字符串是您将在发送给 [对端点授权](authorization-endpoint.md) 的请求中提交的 `code_challenge` 参数的值。

   以下 Python 示例生成 `code_verifier` 并计算 `code_challenge`：

   ```
   #!/usr/bin/env python3
   
   import secrets
   from base64 import urlsafe_b64encode
   from hashlib import sha256
   from string import ascii_letters
   from string import digits
   
   # use the secrets module for cryptographically strong random values
   alphabet = ascii_letters + digits
   code_verifier = ''.join(secrets.choice(alphabet) for _ in range(128))
   code_verifier_hash = sha256(code_verifier.encode()).digest()
   code_challenge = urlsafe_b64encode(code_verifier_hash).decode().rstrip('=')
   
   print(f"code challenge: {code_challenge}")
   print(f"code verifier: {code_verifier}")
   ```

   以下是 Python 脚本的示例输出：

   ```
   code challenge: Eh0mg-OZv7BAyo-tdv_vYamx1boOYDulDklyXoMDtLg
   code verifier: 9D-aW_iygXrgQcWJd0y0tNVMPSXSChIc2xceDhvYVdGLCBk-JWFTmBNjvKSdOrjTTYazOFbUmrFERrjWx6oKtK2b6z_x4_gHBDlr4K1mRFGyE8yA-05-_v7Dxf3EIYJH
   ```

1. 使用 PKCE 的授权码授予请求完成托管登录的登录。以下是示例 URL：

   ```
   https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=1example23456789&redirect_uri=https://www.example.com&code_challenge=Eh0mg-OZv7BAyo-tdv_vYamx1boOYDulDklyXoMDtLg&code_challenge_method=S256
   ```

1. 收集授权 `code` 并使用令牌端点将其兑换为令牌。以下是一个示例请求：

   ```
   POST /oauth2/token HTTP/1.1
   Host: mydomain.auth.us-east-1.amazoncognito.com
   Content-Type: application/x-www-form-urlencoded
   Content-Length: 296
   
   redirect_uri=https%3A%2F%2Fwww.example.com&
   client_id=1example23456789&
   code=7378f445-c87f-400c-855e-0297d072ff03&
   grant_type=authorization_code&
   code_verifier=9D-aW_iygXrgQcWJd0y0tNVMPSXSChIc2xceDhvYVdGLCBk-JWFTmBNjvKSdOrjTTYazOFbUmrFERrjWx6oKtK2b6z_x4_gHBDlr4K1mRFGyE8yA-05-_v7Dxf3EIYJH
   ```

1. 查看响应。响应将包含 ID 令牌、访问令牌和刷新令牌。有关使用 Amazon Cognito 用户池令牌的更多信息，请参阅[了解用户池 JSON 网络令牌 (JWTs)](amazon-cognito-user-pools-using-tokens-with-identity-providers.md)。