无法在REFRESH_TOKEN_AUTH上为客户端验证秘密哈希

问题描述 投票:1回答:2

问题

“无法验证客户端的秘密哈希...”,请参阅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
    }
}

REFRESH_TOKEN_AUTH的Boto3代码

遵循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身份验证流中不会发生。

ADMIN_NO_SRP_AUTH的Boto3代码

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 Javascript JDK

[AWS Amplify Javascript JDK不支持Github中所述的客户端机密,但到目前为止在Boto3上未找到任何报告。

创建应用程序时,必须取消选中生成客户端密码框,因为JavaScript SDK不支持具有客户端密码的应用程序。

相关问题

参考

amazon-cognito
2个回答
5
投票

无论行为是否符合预期,都需要确认。目前,要解决该问题。

从AWS

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 .

0
投票

花了一天后,我发现secret_hash要求的username_for_srp值不是唯一的用户名(例如电子邮件或手机)。>>

username_for_srp-使用ADMIN_NO_SRP_AUTH

值调用admin_initiate_auth后将获得的值。在此通话中,您需要使用实际的用户名(例如电子邮件或手机)来创建秘密哈希。

我希望这对其他人有用。

© www.soinside.com 2019 - 2024. All rights reserved.