Auth0 trigger > post login: User can skip webauth enrollment by clicking "No thanks" and the next subsequent action is called

Hi,

Context:
I have the following code in Auth0 Trigger: Post login

     api.authentication.enrollWith({type: 'webauthn-platform'})
     return api.authentication.enrollWith({type: 'recovery-code'})

This code is intended to enroll a recovery code after successfully enrolling webauthn-platform

Current Behavior
Auth0 trigger > post login: User can skip webauth enrollment by clicking “No thanks” and the next subsequent action “api.authentication.enrollWith({type: ‘recovery-code’})” is called

Expected Behavior
Auth0 trigger > post login: User can skip webauth enrollment by clicking “No thanks” and the next subsequent action should not be called

My goal is to ensure that api.authentication.enrollWith({type: 'recovery-code'}) is not called if the user hasn’t successfully registered for WebAuthn

You can fix this by handling the WebAuthn enrollment response properly.

Here’s how we can modify the code:

/**
 * Handler for post-login Actions trigger
 * @param {Event} event - The event object
 * @param {API} api - The Actions API interface
 */
exports.onExecutePostLogin = async (event, api) => {
  try {
    // Attempt WebAuthn enrollment
    const webAuthnResult = await api.authentication.enrollWith({
      type: 'webauthn-platform'
    });

    // Only proceed with recovery code if WebAuthn was successful
    if (webAuthnResult.status === 'completed') {
      return api.authentication.enrollWith({
        type: 'recovery-code'
      });
    }

    // If WebAuthn was skipped or failed, log it and end
    console.log('WebAuthn enrollment was not completed');
    return;

  } catch (error) {
    console.error('Error during enrollment process:', error);
    // Handle error appropriately
    return;
  }
};

This approach ensures that:

  1. Recovery code enrollment only happens after successful WebAuthn enrollment
  2. Users who click “No thanks” won’t be prompted for recovery code enrollment
  3. Any errors in the process are properly handled

Note: You need to check the WebAuthmResult statue and compare inside if block.

Supported documentation:

HI,

I checked, and enrollWith method does not return a value, so I can’t check the WebAuthResult.status

Hi @chin ,

Apology for overlooking into this.

Here is what you can try:

async function main(event, api) {
  try {
    // First attempt WebAuthn enrollment
    await api.authentication.enrollWith({type: 'webauthn-platform'});
    
    // Check if webauthn-platform is now in enrolled factors
    const hasWebAuthn = event.user.enrolledFactors?.some(
      factor => factor.type === 'webauthn-platform'
    );
    
    // Only proceed with recovery code if WebAuthn was successfully enrolled
    if (hasWebAuthn) {
      return api.authentication.enrollWith({type: 'recovery-code'});
    }
    
  } catch (error) {
    console.log('Enrollment error:', error);
    return;
  }
}

However, there’s one potential limitation to consider: The event.user.enrolledFactors might not be immediately updated after the WebAuthn enrollment in the same action execution. If this is the case, we might need to handle this differently, perhaps by:

  1. Using a Post MFA trigger instead of Post Login
  2. Splitting this into two separate actions
  3. Using app metadata to track the enrollment state

Let me know if this doesn’t work

Thank you for your responses.

Unfortunately, event.user.enrolledFactors is not updated immediately, and the other suggested solutions don’t work for me.

For now, I’ll have to skip “recovery-code” enrollment if the first enrollment is “webauthn-platform.”

1 Like