Skip to main content
Enrolling in MFA does not automatically verify the user for wallet operations. Once enrolled, subsequent wallet actions will require MFA verification. See the verification guides for how to complete MFA verification.
Enroll users in MFA using TOTP (Time-based One-Time Password), where they authenticate with a 6-digit code from an authenticator app like Authy or Google Authenticator.

Setup

To enroll users in MFA with TOTP, use the initEnrollmentWithTotp and submitEnrollmentWithTotp methods returned by the useMfaEnrollment hook:
import {useMfaEnrollment} from '@privy-io/react-auth';

const {initEnrollmentWithTotp, submitEnrollmentWithTotp} = useMfaEnrollment();

Initiating enrollment

First, initiate enrollment by calling Privy’s initEnrollmentWithTotp method with no parameters. This method returns a Promise for an authUrl and secret that the user will need in order to complete enrollment.
const {authUrl, secret} = await initEnrollmentWithTotp();
Then, to have the user enroll, you can either:
  • Display the TOTP authUrl as a QR code to the user, and prompt them to scan it with their TOTP client (commonly, a mobile app like Google Authenticator or Authy)
  • Allow the user to copy the TOTP secret and paste it into their TOTP client
You can directly pass in the authUrl from above into a library like react-qr-code to render the URL as a QR code to your user.

Completing enrollment

Once your user has successfully scanned the QR code, an enrollment code for Privy will appear within their TOTP client. Prompt the user to enter this code in your app, and call Privy’s submitEnrollmentWithTotp method. As a parameter, pass a JSON object with an mfaCode field that contains the MFA code from the user as a string.
const mfaCodeInput = 'insert-mfa-code-from-user-totp-app'; // Prompt the user for the code in their TOTP app
await submitEnrollmentWithTotp({mfaCode: mfaCodeInput});
The component below serves as a reference implementation for how to enroll your users in MFA with TOTP!
Example enrolling a TOTP client for MFA
import {useMfaEnrollment} from '@privy-io/react-auth';
import QRCode from 'react-qr-code';
import {CopyableElement} from '../components/CopyableElement';

export default function MfaEnrollmentWithTotp() {
  const {initEnrollmentWithTotp, submitEnrollmentWithTotp} = useMfaEnrollment();
  const [totpAuthUrl, setTotpAuthUrl] = useState<string | null>(null);
  const [totpSecret, setTotpSecret] = useState<string | null>(null);
  const [mfaCode, setMfaCode] = useState<string | null>(null);

  // Handler for when the user is ready to enroll in TOTP MFA
  const onGenerateTotpUrl = async () => {
    const {authUrl, secret} = await initEnrollmentWithTotp();
    setTotpAuthUrl(authUrl);
    setTotpSecret(secret);
  }

  // Handler for when the user enters the MFA code from their TOTP client
  const onEnteredMfaCode = async () => {
    await submitEnrollmentWithTotp({mfaCode: mfaCode});
    // See the error handling guide for details on how to handle errors
  }

  return(
    <div>
      {/* QR code for the user to scan */}
      {totpAuthUrl && totpSecret ?
        {/* If TOTP values have been generated... */}
        <>
          {/* ...show the user a QR code with the `authUrl` that they can scan...  */}
          <QRCode value={totpAuthUrl} />
          {/* ...or give them the option to copy the `secret` into their TOTP client  */}
          <CopyableElement value={totpSecret} />
        </> :
        {/* Else, show a button to generate the totpAuthUrl */}
        <button onClick={() => onGenerateTotpUrl()}>Show QR Code</button>
      }
      {/* Input field for the user to enter their MFA code */}
      <p>Enter the code from your authenticator app below.</p>
      <input placeholder='123456' onChange={(event) => setMfaCode(event.target.value)}/>
      <button onClick={() => submitEnrollmentWithTotp({mfaCode: mfaCode})}>Submit Enrollment Code</button>
    </div>
  );
}