I’m working on setting up conditional MFA based on a few factors. To start with I was just trying to set based on the last time they had an MFA session.
The issue I am seeing is that when I hit api.authentication.challengeWith or .enrollWith the actions start over again. If I don’t have a break condition it will just loop forever. I have 3 other actions in Post-Login and they all restart. Am I missing something in my MFA api.authentication.challengeWith()?
Code
const mfaSeconds = 60;
exports.onExecutePostLogin = async (event, api) => {
console.log('MFA Filter - onExecutePostLogin');
console.log(event.authentication.methods);
if (event?.user?.email?.startsWith("mytestuser")) {
if (event != null && event.user != null && event.user.app_metadata != null && event.user.app_metadata["last_mfa"] != null) {
var timestamp = Math.floor(Date.now() / 1000);
console.log("timestamp:", timestamp);
var mfaTimestamp = Number(event.user.app_metadata["last_mfa"]);
console.log("mfaTimestamp:", mfaTimestamp)
console.log("mfaTimestamp + mfaSeconds: ", mfaTimestamp + mfaSeconds);
if ((mfaTimestamp + mfaSeconds) > timestamp) {
console.log("Skipping MFA check, only " + (mfaTimestamp + mfaSeconds - timestamp) + " seconds since last MFA");
return event;
}
}
}
if (event?.user?.email?.startsWith("mytestuser")) {
console.log('MFA enrollment');
var enrolledFactors = event.user.enrolledFactors;
if (enrolledFactors && enrolledFactors.length) {
console.log("Already enrolled, challenging...");
let challengeFactors = enrolledFactors.map(m => ({type: m.type}));
for (let i = 0; i < enrolledFactors.length; i++) {
console.log("enrolledFactors:" + enrolledFactors[i]);
console.log("challengeFactors:" + challengeFactors[i]);
}
api.authentication.challengeWith({type: 'otp'});
UpdateLastMFA(event, api);
} else {
console.log("No enrollment, enrolling...");
api.authentication.enrollWith({type: 'otp'}, {type: 'phone'});
UpdateLastMFA(event, api);
}
}
return event;
};
function UpdateLastMFA(event, api) {
if (event.user.email.startsWith("mytestuser")) {
console.log('UpdateLastMFA');
const FORM_ID = 'ap_heLu3AM1Rd8GDCg6MNdtqG';
api.prompt.render(FORM_ID);
}
}
Logs
3:27:15 PM: sandbox runtime ready
3:27:16 PM: Check Reset Password - onExecutePostLogin
3:27:16 PM: finished webtask request
3:27:16 PM: sandbox runtime ready
3:27:16 PM: finished webtask request
3:27:16 PM: sandbox runtime ready
3:27:16 PM: MFA Filter - onExecutePostLogin
3:27:16 PM: [ { name: 'federated', timestamp: '2024-11-01T20:27:15.305Z' } ]
3:27:16 PM: timestamp: 1730492836
mfaTimestamp: 1730492443
mfaTimestamp + mfaSeconds: 1730492503
3:27:16 PM: MFA enrollment
Already enrolled, challenging...
enrolledFactors:[object Object]
3:27:16 PM: challengeFactors:[object Object]
3:27:16 PM: UpdateLastMFA
3:27:16 PM: finished webtask request
3:27:18 PM: sandbox runtime ready
3:27:18 PM: finished webtask request
3:27:19 PM: Check Reset Password - onExecutePostLogin
3:27:19 PM: finished webtask request
3:27:19 PM: sandbox runtime ready
3:27:20 PM: finished webtask request
3:27:20 PM: MFA Filter - onExecutePostLogin
[ { name: 'federated', timestamp: '2024-11-01T20:27:15.305Z' } ]
3:27:20 PM: timestamp: 1730492840
3:27:20 PM: mfaTimestamp: 1730492837
mfaTimestamp + mfaSeconds: 1730492897
Skipping MFA check, only 57 seconds since last MFA
3:27:20 PM: finished webtask request
3:27:20 PM: sandbox runtime ready
3:27:20 PM: Add User Name - onExecutePostLogin
3:27:20 PM: finished webtask request