You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cognito自定义认证挑战未触发问题求助

问题:Cognito自定义认证流跳过CUSTOM_CHALLENGE直接返回令牌

我在Cognito中用Python创建了三个自定义认证挑战触发器(Define auth challenge、Create auth-challenge、Verify auth challenge),逻辑与官方示例一致。已为用户池客户端开启ALLOW_CUSTOM_AUTH授权流,编写Python测试客户端完成SRP_A和PASSWORD_VERIFIER挑战后,未触发预期的CUSTOM_CHALLENGE,直接获取了访问令牌和ID令牌。Define auth challenge Lambda在SRP_A流程中执行正常,请问该问题原因是什么?

Define auth challenge 代码

def lambda_handler(event, context):
    if (len(event['request']['session']) == 1 and event['request']['session'][0]['challengeName'] == "SRP_A"):
        event['response']['issueTokens'] = False
        event['response']['failAuthentication'] = False
        event['response']['challengeName'] = "PASSWORD_VERIFIER"
    elif (len(event['request']['session']) == 2 and event['request']['session'][1]['challengeName'] == "PASSWORD_VERIFIER" and event['request']['session'][1]['challengeResult'] is True):
        event['response']['issueTokens'] = False
        event['response']['failAuthentication'] = False
        event['response']['challengeName'] = "CUSTOM_CHALLENGE"
    elif (len(event['request']['session']) == 3 and event['request']['session'][2]['challengeName'] == "CUSTOM_CHALLENGE" and event['request']['session'][2]['challengeResult'] is True):
        event['response']['issueTokens'] = False
        event['response']['failAuthentication'] = False
        event['response']['challengeName'] = "CUSTOM_CHALLENGE"
    elif (len(event['request']['session']) == 4 and event['request']['session'][3]['challengeName'] == "CUSTOM_CHALLENGE" and event['request']['session'][3]['challengeResult'] is True):
        event['response']['issueTokens'] = True
        event['response']['failAuthentication'] = False
    else:
        event['response']['issueTokens'] = False
        event['response']['failAuthentication'] = True

    return event

Create auth-challenge 代码

def lambda_handler(event, context):
    if event['request']['challengeName'] != "CUSTOM_CHALLENGE":
        return event

    if len(event['request']['session']) == 2:
        event['response']['publicChallengeParameters'] = {}
        event['response']['privateChallengeParameters'] = {}
        event['response']['publicChallengeParameters']['captchaUrl'] = "url/123.jpg"
        event['response']['privateChallengeParameters']['answer'] = "5"

    if len(event['request']['session']) == 3:
        event['response']['publicChallengeParameters'] = {}
        event['response']['privateChallengeParameters'] = {}
        event['response']['publicChallengeParameters']['securityQuestion'] = "Who is your favorite team mascot?"
        event['response']['privateChallengeParameters']['answer'] = "Peccy"

    return event

Verify auth challenge 代码

def lambda_handler(event, context):
    if event['request']['privateChallengeParameters']['answer'] == event['request']['challengeAnswer']:
        event['response']['answerCorrect'] = True
    else:
        event['response']['answerCorrect'] = False

    return event

测试客户端代码

import boto3
from pycognito import AWSSRP

session = boto3.Session(profile_name="aws-profile")
cognito = session.client('cognito-idp')

cognito_user_pool_id = "xx-xxxx-x_xxxxxxxxx"
cognito_user_pool_client_id = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
username = "xxxx"
password = "xxxx"

aws_srp = AWSSRP(
    username=username,
    password=password,
    pool_id=cognito_user_pool_id,
    client_id=cognito_user_pool_client_id,
    client=cognito
)

print("\nInitiate CUSTOM_AUTH with SRP_A challenge")
auth_params = aws_srp.get_auth_params()
resp = cognito.initiate_auth(
    AuthFlow='CUSTOM_AUTH',
    AuthParameters={**auth_params, **{
        "CHALLENGE_NAME": "SRP_A"
    }},
    ClientId=cognito_user_pool_client_id
)
print(resp)

print("\nRespond to PASSWORD_VERIFIER challenge")
assert resp["ChallengeName"] == "PASSWORD_VERIFIER"
challenge_response = aws_srp.process_challenge(resp["ChallengeParameters"], auth_params)
resp = cognito.respond_to_auth_challenge(
    ClientId=cognito_user_pool_client_id,
    ChallengeName="PASSWORD_VERIFIER",
    ChallengeResponses={**challenge_response}
)
print(resp)

问题原因与解决方法

核心原因

  1. 用户池客户端同时启用了USER_SRP_AUTH流
    即使开启了ALLOW_CUSTOM_AUTH,只要USER_SRP_AUTH(默认开启)未被禁用,Cognito会优先走标准SRP认证流程。当客户端完成PASSWORD_VERIFIER挑战后,Cognito判定标准SRP流程已完成,直接返回令牌,不会触发自定义挑战的后续逻辑。

  2. Define auth challenge Lambda的触发验证
    虽然SRP_A流程中Lambda执行正常,但需要确认该Lambda是否正确关联到用户池的Define Auth Challenge触发器,且Cognito服务拥有调用该Lambda的权限(比如配置了正确的IAM角色)。

解决步骤

  • 禁用USER_SRP_AUTH流
    登录AWS控制台,进入目标Cognito用户池的客户端设置页面,在"认证流"选项中,仅保留ALLOW_CUSTOM_AUTH的勾选,取消USER_SRP_AUTH的勾选。这会强制Cognito走自定义认证流路径。

  • 验证Lambda的session逻辑
    在Define auth challenge Lambda中添加日志输出,查看实际的session结构:

    import logging
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    logger.info(f"Session details: {event['request']['session']}")
    

    通过CloudWatch日志检查session的长度和挑战名称是否符合预期,调整代码中的判断条件。

  • 确认客户端AuthFlow参数
    确保测试客户端发起认证时,AuthFlow参数严格设置为'CUSTOM_AUTH',避免混入其他流程参数(你的测试代码已正确设置,但需确认无其他配置冲突)。


内容的提问来源于stack exchange,提问作者João Pedro Schmitt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 15:07:33