Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Custom auth flow

You are currently viewing the AWS SDK for Mobile documentation which is a collection of low-level libraries. Use the Amplify libraries for all new app development. Learn more

You can view the Mobile SDK API reference here.

Amazon Cognito User Pools supports customizing the authentication flow to enable custom challenge types. These challenge types may include CAPTCHAs or dynamic challenge questions. To define your challenges you need to implement three Lambda triggers.

For more information about working with Lambda Triggers for custom authentication challenges visit Amazon Cognito Developer Documentation.

Custom Authentication in Amplify

To enable a custom authentication flow update your awsconfiguration.json file and set authenticationFlowType to CUSTOM_AUTH.

"CognitoUserPool": {
"Default": {
"PoolId": "XX-XXXX-X_abcd1234",
"AppClientId": "XXXXXXXX",
"Region": "XX-XXXX-X"
"Auth": {
"Default": {
"authenticationFlowType": "CUSTOM_AUTH"

In your app code call signIn with a dummy password. Custom challenges need to be answered using the confirmSignIn method:

username: username,
password: "dummyPassword"
) { (signInResult, error) in
if let signInResult = signInResult {
if (signInResult.signInState == .customChallenge) {
// Retrieve challenge details

Get the challenge details from the user and then call confirmSignIn

challengeResponse: "<Challenge Response>",
completionHandler: { (signInResult, error) in
if let error = error {
} else if let signInResult = signInResult {
switch (signInResult.signInState) {
case .signedIn:
print("User is signed in.")

Lambda Trigger Setup

The Amplify CLI can be used to generate triggers required by a custom authentication flow. See the CLI Documentation for details. The CLI will create a custom auth flow skeleton that you can manually edit.

More information on available triggers can be found in the Cognito documentation.

AWSMobileClient assumes the custom auth flow starts with username and password. If you want a passwordless authentication flow, modify your Define Auth Challenge Lambda trigger to bypass the initial username/password verification and proceed to the custom challenge:

exports.handler = (event, context) => {
if (
event.request.session.length === 1 &&
event.request.session[0].challengeName === 'SRP_A'
) {
event.response.issueTokens = false;
event.response.failAuthentication = false;
event.response.challengeName = 'CUSTOM_CHALLENGE';
} else if (
event.request.session.length === 2 &&
event.request.session[1].challengeName === 'CUSTOM_CHALLENGE' &&
event.request.session[1].challengeResult === true
) {
event.response.issueTokens = true;
event.response.failAuthentication = false;
} else {
event.response.issueTokens = false;
event.response.failAuthentication = true;
context.done(null, event);