Skip to main content
Client-side MFA UI powered by @niledatabase/react. These components pair with useMultiFactor (and the low-level mfa helper) to enroll authenticator or email factors, verify challenges, and disable MFA when needed. The User object (obtained via useSession) will include a multiFactor property if MFA is enabled for the user.

Authenticator setup

<MultiFactorAuthenticator /> renders the otpauth QR, recovery codes, and a verification form. Pair it with useMultiFactor to start setup and render the payload.

Email setup

<MultiFactorEmail /> shows masked email messaging and a verification form. Pair it with useMultiFactor to start setup and render the payload.
import { useMultiFactor, MultiFactorEmail } from '@niledatabase/react';

export function EmailSetupCard() {
  const { setup, loading, startSetup, errorType } = useMultiFactor({
    method: 'email',
    currentMethod: null,
  });

  return (
    <div className="space-y-4">
      <button onClick={startSetup} disabled={loading}>
        {loading ? 'Starting...' : 'Enable email MFA'}
      </button>

      {setup?.method === 'email' && setup.scope === 'setup' ? (
        <MultiFactorEmail
          setup={setup}
          onSuccess={(scope) => scope === 'setup' && window.location.reload()}
        />
      ) : null}

      {errorType ? <p className="text-red-600">Unable to start MFA ({errorType})</p> : null}
    </div>
  );
}

Challenge content (sign-in or disable)

<MultiFactorChallenge /> verifies a code during sign-in, setup verification, or disable flows. Feed it the setup payload returned from useMultiFactor (or the /auth/mfa API) and handle success.

Hooks

useMultiFactor(options)

Manages MFA setup and disable flows and provides the payloads rendered by the components above.
NameTypeDefaultDescription
method'authenticator' | 'email'(required)MFA mechanism to enable or disable.
currentMethod'authenticator' | 'email' | nullnullCurrently enrolled method; blocks switching until disabled.
onRedirect(url: string) => voidwindow.location.assignHandle { url } redirect responses (ChallengeRedirect).
onChallengeRedirect(params: { token; method; scope; destination? }) => voidInternal /mfa/prompt navigationOverride the default challenge redirect builder.
Returns { setup, loading, errorType, startSetup, startDisable }.
  • setup: MFA payload for rendering components. Authenticator shape: { method: 'authenticator'; token; scope; otpauthUrl?; secret?; recoveryKeys? }. Email shape: { method: 'email'; token; scope; maskedEmail? }.
  • startSetup(): begins enrollment (POST /auth/mfa); setup.scope can be "setup" or "challenge" when verification is required.
  • startDisable(): starts removal for the given method. If verification is required, setup.scope will be "challenge".
  • errorType: one of setup, disable, parseSetup, parseDisable, or null.

mfa(options) (low-level helper)

Wrapper around /auth/mfa from @niledatabase/client. Use it for custom prompts or headless flows; the React components call this under the hood.
  • POST { method, scope: 'setup' } → returns a setup payload.
  • PUT { token, code, method, scope } → verifies a challenge; returns { ok: true; scope; recoveryCodesRemaining? }.
  • DELETE { token?, code?, method, remove: true } → disables MFA; may require a valid code/token depending on backend settings.
  • Redirects surface as { url: string } (ChallengeRedirect); parse error from the query string for messaging.
Notes
  • Codes are 6 digits for authenticator/email verification; recovery codes are string tokens issued during setup.
  • Tokens expire; expect 410 for stale tokens and 404 for missing challenges.
  • Email MFA may require the same token for verification and disable flows.