Skip to main content
The mfa client export provides a singleton API for handling multi-factor authentication operations from the client side. All methods are thin wrappers around fetch calls to server-side MFA routes where the actual business logic executes.

Import

import { mfa } from '@auth0/nextjs-auth0/client';

Methods

getAuthenticators

List enrolled MFA authenticators for the current MFA session.
async getAuthenticators(options: { mfaToken: string }): Promise<Authenticator[]>
options.mfaToken
string
required
Encrypted MFA token received from MfaRequiredError
authenticators
Authenticator[]
Array of available authenticators
Example:
'use client';
import { mfa } from '@auth0/nextjs-auth0/client';
import { useState, useEffect } from 'react';

export function AuthenticatorList({ mfaToken }) {
  const [authenticators, setAuthenticators] = useState([]);

  useEffect(() => {
    mfa.getAuthenticators({ mfaToken })
      .then(setAuthenticators)
      .catch(console.error);
  }, [mfaToken]);

  return (
    <ul>
      {authenticators.map(auth => (
        <li key={auth.id}>{auth.authenticatorType}</li>
      ))}
    </ul>
  );
}
Throws:
  • MfaTokenExpiredError - Token TTL exceeded
  • MfaTokenInvalidError - Token tampered or malformed
  • MfaGetAuthenticatorsError - Auth0 API error

challenge

Initiate an MFA challenge (e.g., send SMS code).
async challenge(options: {
  mfaToken: string;
  challengeType: string;
  authenticatorId?: string;
}): Promise<ChallengeResponse>
options.mfaToken
string
required
Encrypted MFA token
options.challengeType
string
required
Type of challenge (e.g., “oob” for SMS/email, “otp” for authenticator apps)
options.authenticatorId
string
Specific authenticator to use (required for some challenge types)
response
ChallengeResponse
Challenge response object
Example:
'use client';
import { mfa } from '@auth0/nextjs-auth0/client';

async function sendSmsCode(mfaToken, authenticatorId) {
  const challenge = await mfa.challenge({
    mfaToken,
    challengeType: 'oob',
    authenticatorId
  });
  // SMS sent, now collect binding code from user
  return challenge.oobCode;
}
Throws:
  • MfaTokenExpiredError - Token TTL exceeded
  • MfaTokenInvalidError - Token tampered or malformed
  • MfaChallengeError - Auth0 API error

verify

Verify MFA code and complete authentication.
async verify(options: VerifyMfaOptions): Promise<MfaVerifyResponse>
The VerifyMfaOptions is a union type that accepts different verification methods:
{
  mfaToken: string;
  otp: string;
}
For authenticator app codes (6-digit TOTP codes).
response
MfaVerifyResponse
Token response after successful verification
Example:
'use client';
import { mfa } from '@auth0/nextjs-auth0/client';
import { useState } from 'react';

export function MfaVerification({ mfaToken }) {
  const [otp, setOtp] = useState('');
  const [error, setError] = useState(null);

  async function handleVerify() {
    try {
      await mfa.verify({ mfaToken, otp });
      window.location.href = '/dashboard'; // Redirect after success
    } catch (err) {
      setError(err.message);
    }
  }

  return (
    <form onSubmit={e => { e.preventDefault(); handleVerify(); }}>
      <input 
        value={otp} 
        onChange={e => setOtp(e.target.value)}
        placeholder="Enter 6-digit code"
      />
      <button type="submit">Verify</button>
      {error && <p>{error}</p>}
    </form>
  );
}
Throws:
  • MfaTokenExpiredError - Token TTL exceeded
  • MfaTokenInvalidError - Token tampered or malformed
  • MfaRequiredError - Additional MFA factor required (chained MFA)
  • MfaVerifyError - Auth0 API error (wrong code, rate limit, etc.)
If Auth0 returns mfa_required, this indicates chained MFA where multiple factors are required sequentially. The error will contain a new mfa_token for the next factor.

enroll

Enroll a new MFA authenticator.
async enroll(options: EnrollOptions): Promise<EnrollmentResponse>
options.mfaToken
string
required
Encrypted MFA token
options.authenticatorTypes
string[]
required
Array of authenticator types to enroll (e.g., [“otp”], [“oob”], [“email”])
options.phoneNumber
string
Phone number for SMS enrollment (required for oob type)
options.email
string
Email address for email enrollment (required for email type)
response
EnrollmentResponse
Enrollment response with authenticator details
Example:
'use client';
import { mfa } from '@auth0/nextjs-auth0/client';
import { useState } from 'react';
import QRCode from 'qrcode.react';

export function EnrollOtp({ mfaToken }) {
  const [enrollment, setEnrollment] = useState(null);

  async function handleEnroll() {
    const result = await mfa.enroll({
      mfaToken,
      authenticatorTypes: ['otp']
    });
    setEnrollment(result);
  }

  return enrollment ? (
    <div>
      <QRCode value={enrollment.barcodeUri} />
      <p>Scan this QR code with your authenticator app</p>
      {enrollment.recoveryCodes && (
        <div>
          <h3>Recovery Codes</h3>
          <ul>
            {enrollment.recoveryCodes.map(code => (
              <li key={code}>{code}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  ) : (
    <button onClick={handleEnroll}>Enroll Authenticator</button>
  );
}
Throws:
  • MfaTokenExpiredError - Token TTL exceeded
  • MfaTokenInvalidError - Token tampered or malformed
  • MfaEnrollmentError - Auth0 API error

Usage Pattern

The typical MFA flow using the client API:
1

Catch MfaRequiredError

When authentication fails with MFA required, extract the mfaToken from the error.
try {
  await someAuthOperation();
} catch (error) {
  if (error instanceof MfaRequiredError) {
    // Store mfaToken for MFA flow
    setMfaToken(error.mfa_token);
  }
}
2

List available authenticators

const authenticators = await mfa.getAuthenticators({ mfaToken });
3

Challenge (if needed)

For SMS/email, initiate a challenge:
await mfa.challenge({
  mfaToken,
  challengeType: 'oob',
  authenticatorId: authenticators[0].id
});
4

Verify

Collect the code from the user and verify:
const tokens = await mfa.verify({ mfaToken, otp: userCode });
// Authentication complete, redirect to protected page

See Also

Build docs developers (and LLMs) love