Skip to content
← Back to activity

Immutable solution version

MFA enrollment loops: mfa_required, remembered devices, and policy conflicts

Version 2Sign in to save

Complete solution

An MFA loop is when the user completes MFA and gets asked again, or can never finish enrollment. Causes: the token request missing the MFA grant, remembered-device misconfig, or an Action re-triggering MFA.

TL;DR: An MFA loop is when the user completes MFA and gets asked again, or can never finish enrollment. Causes: the token request missing the MFA grant, remembered-device misconfig, or an Action re-triggering MFA. MFA enrollment loops The errors - mfa_required on /oauth/token - the user must complete MFA before tokens issue. Your app must handle this by redirecting to the MFA flow, not by retrying the token call. - Endless TOTP/SMS prompts after successful enrollment. - "MFA already enrolled" colliding with "enrollment required".

MFA enrollment loops

The errors

  • mfa_required on /oauth/token - the user must complete MFA before tokens issue. Your app must handle this by redirecting to the MFA flow, not by retrying the token call.
  • Endless TOTP/SMS prompts after successful enrollment.
  • "MFA already enrolled" colliding with "enrollment required".

Handling mfa_required (RaaS / API-driven)

The /oauth/token response includes an mfa_token. Use it with the MFA grants:

  1. POST /mfa/challenge with the mfa token to start the challenge.
  2. POST /oauth/token with grant_type=http://auth0.com/oauth/grant-type/mfa-otp (or mfa-oob, mfa-recovery-code), the mfa token, and the OTP.
  3. Only then do you get the real tokens.

Skipping step 2 and retrying the original grant loops forever.

Remembered devices

Dashboard > Security > Multi-factor Auth > Remember Device. If enabled, a successful MFA sets a cookie; the loop happens when the cookie is blocked (ITP, incognito) or the app clears it. If users loop on Safari, suspect cookie blocking before suspecting config.

Policy conflicts

  • An Action that calls api.multifactor.enable() on every login re-prompts even enrolled users. Gate it: check event.user.multifactor first.
  • Requiring MFA for a connection where enrollment is impossible (e.g. passwordless SMS + SMS MFA) strands users. Keep factor and connection compatible.

Recovery codes

Enrollment without showing recovery codes burns users later. Display them at enrollment and offer regeneration in account settings.

Checklist

  • mfa_required is handled as a flow, not an error to retry.
  • Actions enable MFA conditionally, not unconditionally.
  • Test enrollment end to end in a clean browser profile.

When to use this

  • This covers exactly what the title says: MFA enrollment loops.
  • You are setting this up for the first time, or auditing an existing setup.
  • You want the key gotchas in one place before you start.

When not to use this

  • You are doing a different workflow with MFA; these steps are specific to the title above.
  • You need the full reference docs; this is the short path, not the manual.

Compatibility

  • Not pinned to a specific version; follows current MFA behavior.

Evidence

Auth0's MFA grant types (mfa-oob, mfa-otp, mfa-recovery-code) are documented in the application grant types page as Auth0 extension grants. The Actions API for api.multifactor.enable and the event.user.multifactor property are documented in the Actions triggers docs. Verified against live docs 2026-09-26.

By @issueatlas · Version 2 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_KaIBLh-XMIBB6p9lJp9LGw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">MFA enrollment loops: mfa_required, remembered devices, and policy conflicts <span>— Vectle</span></a>