当我尝试访问 Amazon Cognito 用户池 API 时,收到“Unable to verify secret hash for client”(无法验证客户端的密钥哈希)错误。我想对此问题进行故障排除。
解决方法
将用户池应用程序客户端配置为客户端密钥时,必须在 API 的查询参数中包含密钥哈希值。如果您不包含密钥哈希值,则 Amazon Cognito 会返回 Unable to verify secret hash for client(无法验证密钥哈希是否存在客户端)错误。
要解决此问题,请计算密钥哈希值。然后,在调用接受密钥哈希的 Amazon Cognito API(例如 InitiateAuth 或 ForgotPassword)时包含该值。
**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI。
计算密钥哈希值
要计算密钥哈希值,必须具备以下信息:
- 应用程序客户端 ID
- 应用程序客户端密钥
- 您的 Amazon Cognito 用户池中用户的用户名
要实现流程自动化,请完成以下步骤:
- 在 Python 网站上下载最新版本的 Windows 版 Python。然后,在本地计算机上安装 Python。
- 将以下示例 Python 脚本另存为 .py 文件。例如,您可以将该文件另存为 secret_hash.py。以下脚本使用应用程序客户端密钥作为密钥和 SHA256 哈希函数来显示 HMAC 摘要的计算:
import sys, hmac, hashlib, base64
# Unpack command line arguments
username, app_client_id, key = sys.argv[1:4]
# Create message and key bytes
message, key = (username + app_client_id).encode('utf-8'), key.encode('utf-8')
# Calculate secret hash
secret_hash = base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest()).decode()
print(f"Secret Hash for user '{username}': {secret_hash}")
**注意:**将 username 替换为用户池中用户的用户名。此外,将 app_client_id 替换为用户池的应用程序客户端 ID,将 key 替换为应用程序客户端的密钥。
- 要获取密钥哈希值,请运行以下命令:
python3 secret_hash.py username app_client_id app_client_secret
**注意:**如果您运行的是早于 Python 3.0 的 Python 版本,请将 python3 替换为 python。将 secret_hash.py 替换为您的文件名,将 username 替换为用户池用户名,将 app_client_id 替换为您的应用程序客户端 ID,将 app_client_secret 替换为您的应用程序客户端的密钥。
在 API 调用中包含密钥哈希值
将您的密钥哈希值作为 SECRET_HASH 参数添加到 API 调用的查询字符串参数中。
包含 SECRET_HASH 参数的 InitiateAuth API 调用示例:
aws cognito-idp initiate-auth --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME=username,PASSWORD=password,SECRET_HASH=secret_hash --client-id example_client-id
InitiateAuth API 调用输出示例:
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "<HIDDEN>",
"ExpiresIn": 3600,
"TokenType":
"Bearer",
"RefreshToken": "<HIDDEN>",
"IdToken": "<HIDDEN>"
}
}
**注意:**如果您使用 USER_PASSWORD_AUTH 身份验证流程,请为应用程序客户端启用 ALLOW_USER_PASSWORD_AUTH。
包含 SECRET_HASH 参数的 ForgotPassword API 调用示例:
aws cognito-idp forgot-password --client-id example_client-id --username example_username --secret-hash example_secret-hash
**注意:**将 username 替换为您的用户名,将 secret-hash 替换为您的密钥哈希值。
ForgotPassword API 调用输出示例:
{
"CodeDeliveryDetails": {
"Destination": "+***********",
"DeliveryMedium": "SMS",
"AttributeName": "phone_number"
}
}