“无法验证客户端的秘密哈希...”,请参阅REFRESH_TOKEN_AUTH身份验证流程。
{
"Error": {
"Code": "NotAuthorizedException",
"Message": "Unable to verify secret hash for client 3tjdt39cq4lodrn60kjmsb****"
},
"ResponseMetadata": {
"HTTPHeaders": {
"connection": "keep-alive",
"content-length": "114",
"content-type": "application/x-amz-json-1.1",
"date": "Tue, 29 Jan 2019 22:22:35 GMT",
"x-amzn-errormessage": "Unable to verify secret hash for client 3tjdt39cq4lodrn60kjmsbv3jq",
"x-amzn-errortype": "NotAuthorizedException:",
"x-amzn-requestid": "610368ec-2414-11e9-9671-f11a8cac1e43"
},
"HTTPStatusCode": 400,
"RequestId": "610368ec-2414-11e9-9671-f11a8cac1e43",
"RetryAttempts": 0
}
}
遵循AWS文档(如以下参考文献中所述。
对于REFRESH_TOKEN_AUTH / REFRESH_TOKEN:REFRESH_TOKEN(必填),SECRET_HASH(如果应用客户端配置了客户端密码,则是必需的),DEVICE_KEY
response = get_client().admin_initiate_auth(
UserPoolId=USER_POOL_ID,
ClientId=CLIENT_ID,
AuthFlow='REFRESH_TOKEN_AUTH',
AuthParameters={
'REFRESH_TOKEN': refresh_token,
'SECRET_HASH': get_secret_hash(username)
}
)
在具有相同秘密哈希值的ADMIN_NO_SRP_AUTH身份验证流中不会发生。
response = get_client().admin_initiate_auth(
UserPoolId=USER_POOL_ID,
ClientId=CLIENT_ID,
AuthFlow='ADMIN_NO_SRP_AUTH',
AuthParameters={
'USERNAME': username,
'SECRET_HASH': get_secret_hash(username),
'PASSWORD': password
},
ClientMetadata={
'username': username,
'password': password
}
)
相同的秘密哈希适用于200。
{
"AuthenticationResult": {
"AccessToken": ...,
"TokenType": "Bearer"
},
"ChallengeParameters": {},
"ResponseMetadata": {
"HTTPHeaders": {
"connection": "keep-alive",
"content-length": "3865",
"content-type": "application/x-amz-json-1.1",
"date": "Tue, 29 Jan 2019 22:25:33 GMT",
"x-amzn-requestid": "cadf53cf-2414-11e9-bba9-4b60b3285418"
},
"HTTPStatusCode": 200,
"RequestId": "cadf53cf-2414-11e9-bba9-4b60b3285418",
"RetryAttempts": 0
}
}
两者都使用相同的逻辑来生成秘密哈希。
def get_secret_hash(username):
msg = username + CLIENT_ID
digest = hmac.new(
str(CLIENT_SECRET).encode('utf-8'),
msg = str(msg).encode('utf-8'),
digestmod=hashlib.sha256
).digest()
hash = base64.b64encode(digest).decode()
log_debug("secret hash for cognito UP is [{0}]".format(hash))
return hash
值是相同的:
secret hash for cognito UP is [6kvmKb8almXpYKvfEbE9q4r1Iq/SuQvP8H**********].
启用了客户端密钥的Cognito用户池。
print boto.Version2.49.0
[AWS Amplify Javascript JDK不支持Github中所述的客户端机密,但到目前为止在Boto3上未找到任何报告。
创建应用程序时,必须取消选中生成客户端密码框,因为JavaScript SDK不支持具有客户端密码的应用程序。
无论行为是否符合预期,都需要确认。目前,要解决该问题。
AWS人员确定的原因和解决方法。
如果用户名中包含“ @”,则在REFRESH_TOKEN_AUTH调用中会收到该错误。 Cognito会为其生成UUID样式的用户名。而且您必须在刷新调用期间使用它。
提供示例代码以刷新令牌。
import boto3
import hmac
import hashlib
import base64
import time
import jwt
Region = "us-east-1"
UserPoolId = "Your userpool ID"
AppClientId = "yyyy"
AppClientSecret = "zzzz"
Username = "[email protected]"
Password = "shakennotstirred"
Signature = hmac.new(AppClientSecret, Username+AppClientId,digestmod=hashlib.sha256)
Hash = base64.b64encode(Signature.digest())
Cognito = boto3.client("cognito-idp", region_name=Region)
AuthResponse = Cognito.admin_initiate_auth(
AuthFlow="ADMIN_NO_SRP_AUTH",
ClientId=AppClientId,
UserPoolId=UserPoolId,
AuthParameters={"USERNAME":Username, "PASSWORD":Password, "SECRET_HASH":Hash})
IdToken = AuthResponse["AuthenticationResult"]["IdToken"]
RefreshToken = AuthResponse["AuthenticationResult"]["RefreshToken"]
Decoded = jwt.decode(IdToken, verify=False)
DecodedUsername = Decoded["cognito:username"]
NewSignature = hmac.new(AppClientSecret, DecodedUsername+AppClientId, digestmod=hashlib.sha256) #!! Generate new signature and hash
NewHash = base64.b64encode(NewSignature.digest())
RefreshResponse = Cognito.admin_initiate_auth(
AuthFlow="REFRESH_TOKEN_AUTH",
ClientId=AppClientId,
UserPoolId=UserPoolId,
AuthParameters={"REFRESH_TOKEN":RefreshToken, "SECRET_HASH":NewHash}) #!! Use the new hash
NewIdToken = RefreshResponse["AuthenticationResult"]["IdToken"]
print("NewIdToken: "+NewIdToken)
该示例使用Python2。要安装所需的软件包。
pip2 install cryptography -t .
pip2 install PyJWT -t .
花了一天后,我发现secret_hash要求的username_for_srp值不是唯一的用户名(例如电子邮件或手机)。>>
username_for_srp-使用ADMIN_NO_SRP_AUTH
值调用admin_initiate_auth后将获得的值。在此通话中,您需要使用实际的用户名(例如电子邮件或手机)来创建秘密哈希。我希望这对其他人有用。