Skip to main content
The UserMFAMgmt component lets users enroll, view, and delete their own multi-factor authentication factors in a single card-based interface using the My Account API. It uses the My Account API’s authentication methods management capabilities to render a complete UI for managing a user’s authentication methods. With the UserMFAMgmt component, you do not need to orchestrate navigation, call API endpoints, or manage state.

Supported factors

The component handles every authentication method factor configured with the My Account API.
FactorWhat the component renders
Email OTPEmail input → 6-digit OTP verification
SMS OTPCountry-code picker + phone entry → 6-digit OTP verification
TOTP (Authenticator application)QR code with manual-entry key → 6-digit OTP verification
Push notificationsQR code for Auth0 Guardian scan → “waiting for approval” state
PasskeysEducational screen → OS biometric prompt → enrolled entry in the list
Recovery codesDisplay-once code list with a copy action and an “I’ve saved my codes” confirmation

Configure your application

Select your framework to configure environment variables and universal components.

Setup requirements

Before rendering the UserMFAMgmt component, follow Build Account Security UI to configure your Auth0 tenant and applications.

Enable MFA methods and scopes

Enable MFA methods
  1. Navigato to Dashboard > Security > Multi-factor Auth.
  2. Enable the desired factors. To learn more, read Multi-Factor Authentication Factors.
Add My Account API scopesAdd the following My Account API scopes to your application:
  • enroll:authencicators
  • remove:authenticators

Install the component

pnpm add @auth0/universal-components-react
The install command also adds the @auth0/universal-components-core dependency for shared utilities and Auth0 integration.

Get started

import { UserMFAMgmt } from "@auth0/universal-components-react";

export function SecurityPage() {
  return <UserMFAMgmt />;
}
  • Components are always imported from the root entry @auth0/universal-components-react, regardless of framework.
  • Only the Auth0ComponentProvider component uses a framework-specific subpath: /spa for React applications, /rwa for Next.js applications.
import React from "react";
import { UserMFAMgmt } from "@auth0/universal-components-react";
import { Auth0Provider } from "@auth0/auth0-react";
import { Auth0ComponentProvider } from "@auth0/universal-components-react/spa";
import { analytics } from "./lib/analytics";

function SecurityPage() {
  return (
    <div className="max-w-3xl mx-auto p-6">
      <UserMFAMgmt
        factorConfig={{
          sms: { visible: true, enabled: true },
          otp: { visible: true, enabled: true },
          "push-notification": { visible: true, enabled: true },
          email: { visible: true, enabled: true },
          "recovery-code": { visible: true, enabled: true },
          "webauthn-platform": { visible: false },
          "webauthn-roaming": { visible: false },
        }}
        onEnroll={() => {
          analytics.track("MFA Factor Enrolled");
        }}
        onDelete={() => {
          analytics.track("MFA Factor Deleted");
        }}
        onErrorAction={(error, action) => {
          console.error(`MFA ${action} failed:`, error.message);
        }}
        onBeforeAction={async (action, factorType) => {
          if (action === "delete") {
            return await confirmDialog(
              `Remove your ${factorType} authenticator?`
            );
          }
          return true;
        }}
        customMessages={{
          title: "Two-Factor Authentication",
          description: "Manage the extra verification methods used to protect your account.",
        }}
        styling={{
          variables: {
            light: { "--color-primary": "#4f46e5" },
            dark: { "--color-primary": "#818cf8" },
          },
        }}
      />
    </div>
  );
}

export default function App() {
  const domain = "YOUR_TENANT.auth0.com";
  const clientId = "YOUR_CLIENT_ID";

  return (
    <Auth0Provider
      domain={domain}
      clientId={clientId}
      authorizationParams={{ redirect_uri: window.location.origin }}
      interactiveErrorHandler="popup"
    >
      <Auth0ComponentProvider domain={domain}>
        <SecurityPage />
      </Auth0ComponentProvider>
    </Auth0Provider>
  );
}

Props

Display props

Display props control how the component renders without affecting its behavior.
PropTypeDefaultDescription
hideHeaderbooleanfalseHide the component header (title and description).
readOnlybooleanfalseDisable all mutation actions (enroll and delete). Factors are shown but cannot be added or removed.
showActiveOnlybooleanfalseShow only factor types that the user has at least one active enrollment for. Factor types with no enrollments are hidden.
disableEnrollbooleanfalseHide the enroll button for all factor types. Users can still delete existing factors.
disableDeletebooleanfalseHide the delete button on all enrolled factor rows. Users can still enroll new factors.
factorConfigPartial
<Record<MFAType,
{ visible?: boolean;
enabled?: boolean }>>
{}Per-factor-type visibility and enabled state.
factorConfig Use factorConfig to show or grey-out specific factor types without editing the tenant configuration. Each key is a factor type string; both fields are optional and default to true. Supported factor type keys: sms, otp, email, push-notification, webauthn-platform, webauthn-roaming, recovery-code.
  • visible render the factor row in the list (false to hide).
  • enabled render the factor row is interactive (false renders it greyed-out and non-interactive).
<UserMFAMgmt
  factorConfig={{
    sms: { visible: true, enabled: true },
    otp: { visible: true, enabled: true },
    email: { visible: true, enabled: false }, // shown but greyed-out
    "webauthn-platform": { visible: false },  // hidden entirely
  }}
/>

Action props

Action props let you hook into the component’s lifecycle events and trigger or cancel operations.
PropTypeDescription
onEnroll() => voidTriggered after a factor is successfully enrolled.
onDelete() => voidTriggered after a factor is successfully deleted.
onFetch() => voidTriggered after the user’s factors are successfully loaded.
onErrorAction(error: Error, action: ‘enroll’ |
‘delete’ | ‘confirm’) => void
Triggered when any action fails. Use this to surface errors to logs or logging system.
onBeforeAction(action: ‘enroll’ | ‘delete’ | ‘confirm’,
factorType: MFAType)
=> boolean | Promise<boolean>
Triggered before an action executes. Return false (or a Promise resolving to false) to cancel.
onEnroll Triggers after a factor enrollment completes successfully. Use this to refresh related UI (for example, an account security score card) or send analytics.
<UserMFAMgmt
  onEnroll={() => {
    analytics.track("MFA Factor Enrolled");
  }}
/>
onDelete Triggers after a factor is deleted successfully. Use this to refresh any UI that reflects the count of enrolled factors.
<UserMFAMgmt
  onDelete={() => {
    analytics.track("MFA Factor Deleted");
  }}
/>
onFetch Triggers after the component’s initial factor list load. Useful for showing or hiding adjacent UI that depends on whether the user has any enrolled factors.
<UserMFAMgmt
  onFetch={() => {
    setMFALoaded(true);
  }}
/>
onErrorAction Triggers when an enroll, delete, or confirm step fails. The action parameter identifies which stage errored: 'enroll' (initiating enrollment), 'confirm' (submitting the OTP or QR code), or 'delete'.
<UserMFAMgmt
  onErrorAction={(error, action) => {
    console.error(`MFA ${action} failed:`, error.message);
    toast.error(`Something went wrong while trying to ${action} your factor.`);
  }}
/>
onBeforeAction Triggers before an action executes. Return false or a Promise that resolves to false to cancel the operation. The factorType parameter identifies which factor type is involved.
  • 'delete' triggers before the built-in confirmation dialog is shown. Return false to cancel the deletion without ever showing the dialog.
  • 'enroll' / 'confirm' use this for pre-flight checks (for example, rate limiting, policy checks).
<UserMFAMgmt
  onBeforeAction={async (action, factorType) => {
    if (action === "delete") {
      return await confirmDialog(
        `Remove your ${factorType} authenticator? You may be locked out if this is your only factor.`
      );
    }
    return true;
  }}
/>

Customize props

Customization props let you adapt copy, validation rules, and styling without modifying source code.
PropTypeDescription
customMessagesPartial<MFAMessages>Override default UI text and translations.
stylingComponentStyling<UserMFAMgmtClasses>CSS variables and class overrides.
schema{ email?: RegExp; phone?: RegExp }Custom validation patterns for email and phone number input fields.
customMessages Customize all text and translations. Every field is optional.
Top-level title, description, enabled (badge label on enrolled factors), no_active_mfa (empty state when showActiveOnly is true)Actions enroll (enroll button label), delete (delete button label), enroll_factor (success message), remove_factor (success message), deleting (in-progress label), cancelDelete confirmation delete_mfa_title, delete_mfa_contentPer factor type (replace {factor} with sms, otp, email, push-notification, webauthn-platform, webauthn-roaming, recovery-code) {factor}.title, {factor}.description, {factor}.button-textErrors errors.factors_loading_error, errors.delete_factor, errors.failed
<UserMFAMgmt
  customMessages={{
    title: "Two-Factor Authentication",
    description: "Add extra layers of security to protect your account.",
    no_active_mfa: "You haven't enrolled any authentication methods yet.",
    enroll: "Add method",
    delete_mfa_title: "Remove authentication method?",
    delete_mfa_content:
      "You will no longer be able to use this method to verify your identity.",
    sms: {
      title: "Text message (SMS)",
      description: "Receive a one-time code via text message.",
    },
    otp: {
      title: "Authenticator app",
      description: "Use Google Authenticator, Authy, or any TOTP app.",
    },
    errors: {
      factors_loading_error: "Unable to load your security methods.",
    },
  }}
/>
Customize style Customize appearance with CSS variables and class overrides. Supports light/dark themes.
Variables—CSS custom properties
  • common Applied to both themes
  • light Light mode only
  • dark Dark mode only
Class overrides
  • UserMFAMgmt-card the outer card wrapping the factor list
  • UserMFASetupForm-dialogContent the enrollment multi-step dialog content area
  • DeleteFactorConfirmation-dialogContent the delete confirmation dialog content area
<UserMFAMgmt
  styling={{
    variables: {
      light: { "--color-primary": "#4f46e5" },
      dark: { "--color-primary": "#818cf8" },
    },
    classes: {
      "UserMFAMgmt-card": "rounded-2xl shadow-md border-2",
      "UserMFASetupForm-dialogContent": "max-w-lg",
      "DeleteFactorConfirmation-dialogContent": "max-w-sm",
    },
  }}
/>
schema Override the built-in regex patterns used to validate user input during enrollment. Both fields are optional; unset fields keep their default patterns.
  • email validates the email address entered during email-OTP enrollment (default: standard RFC-5322-style pattern).
  • phone validates the phone number entered during SMS enrollment (default: accepts international E.164 format).
<UserMFAMgmt
  schema={{
    // Restrict to company domain only
    email: /^[a-zA-Z0-9._%+-]+@example\.com$/,
    // US numbers only
    phone: /^\+1[2-9]\d{2}[2-9]\d{6}$/,
  }}
/>

TypeScript definitions

type MFAType =
  | "sms"
  | "otp"
  | "email"
  | "push-notification"
  | "webauthn-platform"
  | "webauthn-roaming"
  | "recovery-code";

interface FactorConfigOptions {
  visible?: boolean;
  enabled?: boolean;
}

interface UserMFAMgmtClasses {
  "UserMFAMgmt-card"?: string;
  "UserMFASetupForm-dialogContent"?: string;
  "DeleteFactorConfirmation-dialogContent"?: string;
}

interface UserMFAMgmtProps {
  hideHeader?: boolean;
  showActiveOnly?: boolean;
  disableEnroll?: boolean;
  disableDelete?: boolean;
  readOnly?: boolean;
  factorConfig?: Partial<Record<MFAType, FactorConfigOptions>>;
  customMessages?: Partial<MFAMessages>;
  styling?: ComponentStyling<UserMFAMgmtClasses>;
  schema?: { email?: RegExp; phone?: RegExp };
  onEnroll?: () => void;
  onDelete?: () => void;
  onFetch?: () => void;
  onErrorAction?: (error: Error, action: "enroll" | "delete" | "confirm") => void;
  onBeforeAction?: (
    action: "enroll" | "delete" | "confirm",
    factorType: MFAType
  ) => boolean | Promise<boolean>;
}

Advanced customization

The UserMFAMgmt component is composed of a stateless view component and a hook. Import them individually to build custom workflows.

Available subcomponents

For advanced use cases, you can import individual subcomponents to build custom interfaces.
SubcomponentDescription
UserMFAMgmtViewStateless view layer; bring your own data and handlers via useUserMFA.
Dialogs (shared sub-components)
Shared sub-componentsDescription
UserMFASetupFormMulti-step enrollment dialog. Handles the full enrollment flow: contact entry (phone/email), OTP verification, QR-code scanning (for TOTP and push), and recovery-code display.
DeleteFactorConfirmationConfirmation dialog shown before a factor is deleted.
FactorsListRenders the list of active enrollments within a factor-type row, with per-enrollment delete buttons.

Available hooks

HookDescription
useUserMFAFull data and interaction layer: factor query, enrollment mutation, delete mutation, OTP confirmation, dialog state, and all event handlers.

Learn more

UserPasskeyMgmt

Manage WebAuthn passkeys with the same lifecycle pattern.

Build a Self-Service Account Security Interface

Overview, prerequisites, and framework setup for all My Account components.