在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用户池。
打印boto.Version 2.49.0
AWS Amplify Javascript JDK不支持Github中所述的客户端机密,但到目前为止在Boto3上未找到任何报告。
在创建应用程序时,必须取消选中“生成客户端密码”框,因为JavaScript SDK不支持具有客户端密码的应用程序。
答案 0 :(得分:0)
该行为是否符合预期将得到确认。目前,要解决该问题。
AWS人员确定的原因和解决方法。
当用户名中有一个“ @”时,您将在REFRESH_TOKEN_AUTH调用中收到该错误。 Cognito会为其生成UUID样式的用户名。而且您必须在刷新调用中使用它。
提供了刷新令牌的示例代码。
private void setupList() {
ListView listView = getView().findViewById(R.id.list_view);
adapter = new ListAdapter(getContext(), createList(20));
listView.setAdapter(adapter);
}
private List<String> createList(int n) {
List<String> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
list.add("View " + i);
}
return list;
}
该示例使用Python2。要安装所需的软件包。
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 = "james@bond.com"
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)
答案 1 :(得分:0)
花了一天的时间后,我发现secret_hash要求的username_for_srp值不是唯一的用户名(例如电子邮件或手机)。
username_for_srp-使用 ADMIN_NO_SRP_AUTH 值调用 admin_initiate_auth 后将获得的值。在此通话中,您需要使用实际的用户名(例如电子邮件或手机)来创建秘密哈希。
我希望这对其他人有用。