We have an app that uses Cognito to authenticate users and process MFA. We also use CUSTOM_AUTH flow because we need to use CUSTOM_CHALLENGE with defineauth, createauth, and verifyauth lambdas that allow us to handle email MFA that Cognito doesn't support out of the box.
Now I need to implement additional MFA for performing some of the actions in the app, and I'm a bit stuck. The idea is to only trigger one of the MFA challenges (depending on what a user has configured) and apply a few other security controls using CUSTOM_CHALLENGE, but I can't get Cognito to trigger any of its MFA challenges in CUSTOM_AUTH.
To simplify things, imagine we only have a following createauth lambda function:
def lambda_handler(event, context):
print("received event:", event)
process_event(event)
print("response event:", event)
return event
def process_event(event):
if len(event["request"]["session"]) == 0:
event["response"]["issueTokens"] = False
event["response"]["failAuthentication"] = False
event["response"]["challengeName"] = "SOFTWARE_TOKEN_MFA"
return
s = event["request"]["session"][len(event["request"]["session"]) - 1]
if s["challengeName"] == "SOFTWARE_TOKEN_MFA" and s["challengeResult"]:
event["response"]["issueTokens"] = True
event["response"]["failAuthentication"] = False
return
event["response"]["issueTokens"] = False
event["response"]["failAuthentication"] = True
Basically, it assumes that the user has SOFTWARE_TOKEN_MFA
enabled (just for testing) and sends SOFTWARE_TOKEN_MFA
challenge as the first challenge in the flow. Then it checks that if it has passed validation, issues an access token to the user.
When I start authentication:
aws cognito-idp initiate-auth --auth-flow CUSTOM_AUTH \
--client-id <client-id> \
--region ap-southeast-2 \
--auth-parameters 'USERNAME=<username>'
Everything works as expected:
{
"ChallengeName": "SOFTWARE_TOKEN_MFA",
"Session": "<session>",
"ChallengeParameters": {
"USERNAME": "<user-id>"
}
}
However, when I provide a valid code (I can prove it's valid because I've configured MFA for this user in "a normal way" and can log in using the authenticator app codes):
aws cognito-idp respond-to-auth-challenge
--client-id <client-id>
--region ap-southeast-2
--challenge-name SOFTWARE_TOKEN_MFA
--challenge-responses 'USERNAME=<user-id>,SOFTWARE_TOKEN_MFA_CODE=612345'
--session <session>
I get this error:
An error occurred (CodeMismatchException) when calling the RespondToAuthChallenge operation: Invalid code or auth state for the user.
So, basically my question is: is it possible to trigger any of the MFA challenges from the CUSTOM_AUTH flow and if yes, how can I do it without asking the user's password?
I've googled it, tried to find it on stackoverflow, talked to chat gpt, but hasn't found an answer. If you have just any bits of information regarding the matter, I'd appreciate if you shared it.