AWS Cognito User Pool without a password

this may work, but storing password in dynamoDB may have issues, considering security. instead we can try like this:

option#1: - user sign ups with username and password.

  1. setup cognito triggers - we can use lambda functions.
  2. A. Create Auth Challenge B. Define Auth Challenge C. Verify Auth Challenge Response
  3. client app should implement CUSTOM_CHALLENGE authentication flow.
  4. ask user to enter registered phone number, pass this in username field. trigger B will understand the request and passes flow to trigger A, Trigger A will generate random code 5. use AWS SNS service to send SMS to user mobile number
  5. Trigger C will validate OTP and allows login points to consider: a. setup phone number as alias (select Also allow sign in with verified phone number) b. make phone number field as verifiable (this allows user to receive OTP)

option#1: - user sign ups without username and password. cognito setup

  1. setup phone number as alias (select Also allow sign in with verified phone number)
  2. make phone number field as verifiable (this allows user to receive OTP)
  3. during signup don't ask user to provide username and password, just ask phone number
  4. generate UUID for both username and password to be unique and pass these to cognito along with phone number
  5. Cognito sends OTP code to user for account confirmation.
  6. for phone number with OTP login setup triggers as explained in above option.

for triggers code,refer aws cognito pool with multiple sign in options


Since AWS Cognito is not currently supporting passwordless authentication you need to implement a workaround with random password stored externally. You can implement the authentication flow as follows.

  • After user Signup (Also ask for mobile number and make it mandatory), store the Mobile number, Username and Password also in Dynamodb encrypted with AWS KMS (For additional security).
  • You can use MFA with mobile number for authentication challenge so that after the user enters mobile number and press login(In frontend), in the backend you can automatically do username password matching(Passthrough) and trigger the MFA to send a code for user's mobile and verify that using the AWS Cognito SDK (Without implementing custom mobile message and challenge).
  • If you plan to implement the flow manually(Without MFA) to send the SMS & validation, you can use AWS SNS for the purpose.

Check the following code sample to understand the insight of MFA and refer this link for more details.

    var userData = { 
        Username : 'username',
        Pool : userPool
    };

    cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);

    var authenticationData = {
        Username : 'username',
        Password : 'password',
    };

    var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);

    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            alert('authentication successful!')
        },

        onFailure: function(err) {
            alert(err);
        },

        mfaRequired: function(codeDeliveryDetails) {
            var verificationCode = prompt('Please input verification code' ,'');
            cognitoUser.sendMFACode(verificationCode, this);
        }

    });

Note: Here the MFA with mobile number is not used for the purpose of MFA but as a workaround to meet your requirement.


This is a slightly different spin to what the OP is requesting as it uses a single secret, but I think it may help others who land on this question.

I was able to do this by creating custom lambdas for the Cognito triggers: Define Auth Challenge, Create Auth Challenge & Verify Auth Challenge.

My requirement was that I wanted my backend to use a secret to then get access & refresh tokens for any Cognito user.

Define Auth Challenge Lambda

exports.handler = async event => {
  if (
    event.request.session &&
    event.request.session.length >= 3 &&
    event.request.session.slice(-1)[0].challengeResult === false
  ) {
    // The user provided a wrong answer 3 times; fail auth
    event.response.issueTokens = false;
    event.response.failAuthentication = true;
  } else if (
    event.request.session &&
    event.request.session.length &&
    event.request.session.slice(-1)[0].challengeResult === true
  ) {
    // The user provided the right answer; succeed auth
    event.response.issueTokens = true;
    event.response.failAuthentication = false;
  } else {
    // The user did not provide a correct answer yet; present challenge
    event.response.issueTokens = false;
    event.response.failAuthentication = false;
    event.response.challengeName = 'CUSTOM_CHALLENGE';
  }
  return event;
};

Create Auth Challenge Lambda

exports.handler = async event => {
  if (event.request.challengeName == 'CUSTOM_CHALLENGE') {
    // The value set for publicChallengeParameters is arbitrary for our
    // purposes, but something must be set
    event.response.publicChallengeParameters = { foo: 'bar' };
  }
  return event;
};

Verify Auth Challenge Lambda

exports.handler = async event => {
  if (event.request.challengeName == 'CUSTOM_CHALLENGE') {
    // The value set for publicChallengeParameters is arbitrary for our
    // purposes, but something must be set
    event.response.publicChallengeParameters = { foo: 'bar' };
  }
  return event;
};

I was then able to use some JS, using amazon-cognito-identity-js, to provide the secret and get the tokens:

var authenticationData = {
  Username : 'username'
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var poolData = {
  UserPoolId : '...', // Your user pool id here
  ClientId : '...' // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
  Username : 'username',
  Pool : userPool
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);

cognitoUser.setAuthenticationFlowType('CUSTOM_AUTH');

cognitoUser.initiateAuth(authenticationDetails, {
  onSuccess: function(result) {
    // User authentication was successful
  },
  onFailure: function(err) {
    // User authentication was not successful
  },
  customChallenge: function(challengeParameters) {
    // User authentication depends on challenge response
    var challengeResponses = 'secret'
    cognitoUser.sendCustomChallengeAnswer(challengeResponses, this);
  }
});