简体   繁体   English

使用 Cognito & API Gateway & Lambda (Python) 的无密码身份验证流程

[英]Passwordless authentication flow using Cognito & API Gateway & Lambda (Python)

I've been trying to implement passwordless authentication using AWS Cognito & API Gateway & Lambda (Python)我一直在尝试使用 AWS Cognito & API Gateway & Lambda (Python) 实现无密码身份验证

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

I have configured Cognito (to accept CUSTOM_AUTH), added the Lambdas, and created the API endpoints:我已经配置了 Cognito(接受 CUSTOM_AUTH),添加了 Lambda,并创建了 API 端点:

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

When calling initiateAuth I receive the following response: An error occurred (NotAuthorizedException) when calling the InitiateAuth operation: Incorrect username or password."调用initiateAuth 时,我收到以下响应:调用InitiateAuth 操作时发生错误(NotAuthorizedException):用户名或密码不正确。”

I'm using CUSTOM_AUTH which doesn't require password, and the user name is definitely correct because it actually initiates the authentication flow and I receive a code, however because boto3 doesn't respond with a session I can't continue the authentication.我正在使用不需要密码的 CUSTOM_AUTH,并且用户名绝对正确,因为它实际上启动了身份验证流程并且我收到了一个代码,但是因为 boto3 不响应会话,我无法继续身份验证。

This is how I call Cognito:这就是我调用 Cognito 的方式:

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

It's probably something small I'm missing but I can't figure out what.这可能是我遗漏的一些小东西,但我不知道是什么。

Your client code looks OK, mine has ClientId param in it but if your code is not raising an exception then it should be fine.您的客户端代码看起来不错,我的客户端代码中有ClientId参数,但如果您的代码没有引发异常,那么应该没问题。 Unless you had Generate client secret option checked when you created your app client.除非您在创建应用程序客户端时选中了Generate client secret选项。 If that is the case then you have to pass in SECRET_HASH in AuthParameters like the following:如果是这样的话,那么你必须在通过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.                                                          
    },
) 

Next, double check the following:接下来,仔细检查以下内容:

Under App clients > * > Auth Flows Configuration , is ALLOW_CUSTOM_AUTH option enabled for your client?App clients > * > Auth Flows Configuration ,是否为您的客户端启用了ALLOW_CUSTOM_AUTH选项?

Under App integration > App client settings > * > Enabled Identity Providers , is your user pool selected?App integration > App client settings > * > Enabled Identity Providers ,是否选择了您的用户池?

If you have Cognito setup correctly and your code still doesn't work then it is probably the lambda code.如果您正确设置了 Cognito 并且您的代码仍然无法工作,那么它可能是 lambda 代码。 You probably know this but for password-less custom auth you need to use 3 lambda triggers: Define Auth Challenge , Create Auth Challenge , and Verify Auth Challenge .您可能知道这一点,但对于无密码自定义身份验证,您需要使用 3 个 lambda 触发器: Define Auth Challenge身份Define Auth ChallengeCreate Auth Challenge身份Create Auth ChallengeVerify Auth Challenge身份Verify Auth Challenge

Custom auth lambdas events are triggered in the following order:自定义 auth lambdas 事件按以下顺序触发:

  1. DefineAuthChallenge_Authentication:定义AuthChallenge_Authentication:
    • Technically, issueTokens can be set to True here to return tokens without going through the rest of the steps.从技术上讲,可以在此处将 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: 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

Then your client must respond to the challenge:然后您的客户必须应对挑战:

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. VerifyAuthChallengeResponse_Authentication:验证AuthChallengeResponse_Authentication:
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. DefineAuthChallenge_Authentication:定义AuthChallenge_Authentication:
    • Set event['response']['issueTokens'] to True to return tokens (code shown in step 1), or issue another challenge to keep repeating steps 1-3.event['response']['issueTokens']True以返回令牌(步骤 1 中显示的代码),或发出另一个质询以继续重复步骤 1-3。

Finally, make sure that if case-insensitivity option is enabled for your user pool too.最后,请确保是否也为您的用户池启用了不区分大小写选项。 Also, I can't exactly recall if CUSTOM_AUTH flow worked if the user is in FORCE_CHANGE_PASSWORD status.另外,如果用户处于FORCE_CHANGE_PASSWORD状态,我无法完全回忆CUSTOM_AUTH流程是否FORCE_CHANGE_PASSWORD If the user is in that state, then try settings a permanent password with the sdk to set the status to CONFIRMED .如果用户处于该状态,则尝试使用 sdk 设置永久密码以将状态设置为CONFIRMED

I was facing the same error, and I think that the error message is misleading.我遇到了同样的错误,我认为错误消息具有误导性。 When you did not respond correctly in Create-Auth-Challenge lambda, you will get this error.当您在 Create-Auth-Challenge lambda 中没有正确响应时,您将收到此错误。 So make sure everything is right in your lambda.因此,请确保您的 lambda 中一切正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Python 中的 API 网关请求中使用 AWS Cognito 访问令牌 - Using AWS Cognito access token in requests for API gateway in Python 如何通过API Gateway将Cognito User Pool信息传递给Lambda - How to pass Cognito User Pool information to Lambda through API Gateway AWS Lambda(Python + Flask)基本功能无法使用 API 网关 - AWS Lambda (Python + Flask) basic functionality not working using API Gateway 如何在 Python 中使用 Cognito 凭据调用 API 网关 - How do I call an API Gateway with Cognito credentials in Python JSON 有效负载,AWS Lambda(Python),API 网关 - JSON Payload, AWS Lambda (Python), API Gateway AWS API Gateway 和 Python Lambda 返回 HTML - AWS API Gateway and Python Lambda returning HTML API网关+ Lambda + Python:处理异常 - API Gateway + Lambda + Python: Handling Exceptions 使用AWS Lambda和api-gateway创建API时出错(python) - Error when creating API using AWS Lambda and api-gateway (python) 如何使用python3中的无密码身份验证通过子进程方法在REMOTE机器中运行命令? - How to run commands in REMOTE machine with the subprocess approach using passwordless authentication in python3? 使用 AWS API Gateway 进行 JWT 身份验证和转发 - JWT authentication and forwarding using AWS API Gateway
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM