0

我一直在尝试使用 AWS Cognito & API Gateway & Lambda (Python) 实现无密码身份验证

我关注了这些文章: https ://medium.com/digicred/password-less-authentication-in-cognito-cafa016d4db7 https://medium.com/@pjatocheseminario/passwordless-api-using-cognito-and-serverless-框架-7fa952191352

我已经配置了 Cognito(接受 CUSTOM_AUTH),添加了 Lambda,并创建了 API 端点:

/sign-up 
/initiate-auth (aka initiate login)
/respond-to-auth-challenge (aka (verify login)

调用initiateAuth时,我收到以下响应:调用InitiateAuth操作时发生错误(NotAuthorizedException):用户名或密码不正确。”

我正在使用不需要密码的 CUSTOM_AUTH,并且用户名绝对正确,因为它实际上启动了身份验证流程并且我收到了一个代码,但是因为 boto3 没有通过会话响应我无法继续身份验证。

这就是我所说的 Cognito:

res = cognito.initiate_auth(
        ClientId=client_id,
        AuthFlow="CUSTOM_AUTH",
        AuthParameters={
            "USERNAME": email,
            "PASSWORD": random_password  
            }
        )

这可能是我缺少的一些小东西,但我不知道是什么。

4

2 回答 2

3

您的客户端代码看起来ClientId不错,我的代码中有参数,但如果您的代码没有引发异常,那么它应该没问题。除非您在Generate client secret创建应用程序客户端时选中了选项。如果是这种情况,那么您必须SECRET_HASHAuthParameters下面这样传入:

import hmac
import hashlib
import base64

def get_secret_hash(email, client_id, client_secret):                                                                   
     """                                                                                                                 
     A keyed-hash message authentication code (HMAC) calculated using                                                    
     the secret key of a user pool client and username plus the client                                                   
     ID in the message.                                                                                                  
     """                                                                                                                 
     message = email + client_id                                                                                         
     client_secret = str.encode(client_secret)                                                                           
     dig = hmac.new(client_secret, msg=message.encode('UTF-8'), digestmod=hashlib.sha256).digest()                       
     return base64.b64encode(dig).decode()
                                                                                                                 
client.admin_initiate_auth(                                                                                  
    UserPoolId=COGNITO_USER_POOL_ID,                                                                                    
    ClientId=CLIENT_ID,                                                                                                 
    AuthFlow='CUSTOM_AUTH',                                                                                             
    AuthParameters={                                                                                                    
        'USERNAME': email,                                                                                              
        'SECRET_HASH': get_secret_hash(email, CLIENT_ID, CLIENT_SECRET) # Omit if secret key option is disabled.                                                          
    },
) 

接下来,仔细检查以下内容:

在 下App clients > * > Auth Flows Configuration,是否ALLOW_CUSTOM_AUTH为您的客户启用了选项?

在 下App integration > App client settings > * > Enabled Identity Providers,您的用户池是否被选中?

如果您正确设置了 Cognito 并且您的代码仍然无法工作,那么它可能是 lambda 代码。您可能知道这一点,但对于无密码自定义身份验证,您需要使用 3 个 lambda 触发器:Define Auth ChallengeCreate Auth ChallengeVerify Auth Challenge.

自定义身份验证 lambdas 事件按以下顺序触发:

  1. 定义AuthChallenge_Authentication:
    • 从技术上讲,可以在此处将 issueTokens 设置为 True 以返回令牌,而无需执行其余步骤。
def lambda_handler(event, context):
    if event['triggerSource'] == 'DefineAuthChallenge_Authentication':
        event['response']['challengeName'] = 'CUSTOM_CHALLENGE'
        event['response']['issueTokens'] = False
        event['response']['failAuthentication'] = False

        if event['request']['session']:  # Needed for step 4.
            # If all of the challenges are answered, issue tokens.
            event['response']['issueTokens'] = all(
                answered_challenge['challengeResult'] for answered_challenge in event['request']['session'])
    return event
  1. CreateAuthChallenge_Authentication:
def lambda_handler(event, context):
    if event['triggerSource'] == 'CreateAuthChallenge_Authentication':
        if event['request']['challengeName'] == 'CUSTOM_CHALLENGE':
            event['response']['privateChallengeParameters'] = {}
            event['response']['privateChallengeParameters']['answer'] = 'YOUR CHALLENGE ANSWER HERE'
            event['response']['challengeMetadata'] = 'AUTHENTICATE_AS_CHALLENGE'
    return event

然后您的客户必须回应挑战:

client.respond_to_auth_challenge(                                                                            
    ClientId=CLIENT_ID,                                                                                                 
    ChallengeName='CUSTOM_CHALLENGE',                                                                                   
    Session=session,                                                                                                    
    ChallengeResponses={                                                                                                
        'USERNAME': email,                                                                                              
        'ANSWER': 'Extra Protection!',                                                                                  
        'SECRET_HASH': get_secret_hash(email, CLIENT_ID, CLIENT_SECRET)  # Omit if secret key option is disabled.                                                 
    }                                                                                                                   
)    
  1. 验证验证挑战响应_验证:
def lambda_handler(event, context):
    if event['triggerSource'] == 'VerifyAuthChallengeResponse_Authentication':
        if event['request']['challengeAnswer'] == event['request']['privateChallengeParameters']['answer']:
            event['response']['answerCorrect'] = True
    return event
  1. 定义AuthChallenge_Authentication:
    • 设置event['response']['issueTokens']True返回令牌(步骤 1 中显示的代码),或发出另一个质询以继续重复步骤 1-3。

最后,确保您的用户池是否也启用了不区分大小写选项。CUSTOM_AUTH此外,如果用户处于FORCE_CHANGE_PASSWORD状态,我无法准确回忆流是否有效。如果用户处于该状态,则尝试使用 sdk 设置永久密码以将状态设置为CONFIRMED.

于 2021-01-04T22:14:30.597 回答
1

我面临同样的错误,我认为错误信息具有误导性。当您在 Create-Auth-Challenge lambda 中没有正确响应时,您将收到此错误。因此,请确保您的 lambda 中的所有内容都正确。

于 2020-12-01T05:35:35.403 回答