# 代码交换证明密钥（Proof Key for Code Exchange，简称PKCE）

代码交换证明密钥（Proof Key for Code Exchange，简称PKCE）是一种用于增强OAuth 2.0授权码流程安全性的扩展机制。PKCE主要用于公共客户端（如原生应用和单页应用），这些客户端无法安全地存储客户端密钥（Client Secret）。PKCE通过引入一个额外的“证明密钥”来防止授权码被拦截和滥用。

#### PKCE的工作原理

1. **生成Code Verifier**： 客户端生成一个随机的、足够长的字符串，称为`code_verifier`。这个字符串是唯一的，并且只在当前授权请求中使用。
2. **生成Code Challenge**： 客户端对`code_verifier`进行哈希处理（通常使用SHA-256算法），并将结果进行Base64 URL编码，得到`code_challenge`。
3. **发起授权请求**： 客户端将`code_challenge`和`code_challenge_method`（例如“S256”表示使用SHA-256算法）一起发送到授权服务器的授权端点（/authorize）。
4. **用户认证和授权**： 用户在授权服务器上进行认证并授权，授权服务器生成授权码并将其返回给客户端。
5. **交换授权码**： 客户端将授权码和之前生成的`code_verifier`一起发送到授权服务器的令牌端点（/token）。
6. **验证Code Verifier**： 授权服务器使用收到的`code_verifier`和之前存储的`code_challenge`进行验证。如果验证通过，授权服务器返回访问令牌和刷新令牌。

#### PKCE的安全性

PKCE通过引入`code_verifier`和`code_challenge`，确保只有发起授权请求的客户端才能成功交换授权码。这有效地防止了授权码拦截攻击，因为即使攻击者截获了授权码，也无法在没有`code_verifier`的情况下成功交换令牌。

#### 示例代码

以下是一个使用PKCE的伪代码示例：

```python
import hashlib
import base64
import os

# 生成code_verifier
code_verifier = base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8').rstrip('=')

# 生成code_challenge
code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode('utf-8')).digest()).decode('utf-8').rstrip('=')

# 发起授权请求
authorization_url = f"https://authorization-server.com/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&code_challenge={code_challenge}&code_challenge_method=S256"
print("请访问以下URL进行授权:", authorization_url)

# 用户完成授权后，使用code_verifier交换授权码
authorization_code = input("请输入授权码: ")
token_response = requests.post("https://authorization-server.com/token", data={
    'grant_type': 'authorization_code',
    'code': authorization_code,
    'redirect_uri': 'YOUR_REDIRECT_URI',
    'client_id': 'YOUR_CLIENT_ID',
    'code_verifier': code_verifier
})

print("访问令牌:", token_response.json().get('access_token'))
```

#### 参考资料

* [Auth0: Authorization Code Flow with Proof Key for Code Exchange (PKCE)](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce)
* [Curity: Proof Key for Code Exchange Overview](https://curity.io/resources/learn/oauth-pkce/)
* [Cloudentity: Proof Key of Code Exchange (PKCE)](https://cloudentity.com/developers/basics/oauth-extensions/authorization-code-with-pkce/)
* [RFC 7636: Proof Key for Code Exchange](https://oauth.net/2/pkce/)
