Action Triggered MFA Using enrollWith and challengeWith

Problem statement

This article details how to use “enrollWith” and “challengeWith” via the Action to force users to enroll in a new factor if they already enrolled in one other.

Solution

If the user is already enrolled into one factor, e.g., “phone”, the “enrollWith” command will fail as the user must verify the existing factor before enrolling an additional factor.

Here is a sample Action script that shows the correct sequence:

exports.onExecutePostLogin = async (event, api) => {
  console.log(`Action started`);
  const alreadyEnrolled = event.user.enrolledFactors;
  console.log(`Check if the user already has any MFA enrollments`);
  if (alreadyEnrolled.length > 0) {
    console.log(`The user already enrolled in some MFAs. Needs to pass a challenge.`);
    api.authentication.challengeWithAny([
      { type: 'phone' }, { type: 'push-notification' }, { type: 'email' }, { type: 'otp' }
    ]); // here we ask the user to verify the existing MFA
    const enrolledInOTP = (event.user.enrolledFactors || []).filter(f => f.type === 'otp').map(f => ({ type: f.type }));
    if (enrolledInOTP.length === 0) { // here we check if the user is enrolled into OTP
      console.log(`The user is not enrolled in OTP`);
      api.authentication.enrollWith(
        { type: 'otp' }
      ) // here we invite the user to enrol into OTP
    }
  } else {
    console.log(`The user doesn't have any MFAs`);
    api.authentication.enrollWithAny([
      { type: 'phone' }, { type: 'push-notification' }, { type: 'otp' }
    ]) // here we allow the user to enrol into one of the factors listed above
  }
};

Related References