Skip to content

Documentation / expo / useMfa

Function: useMfa()

useMfa(): UseMfa

Use this hook to execute the MFA flow with Privy.

Returns

UseMfa

init - starts the MFA verification flow

submit - completes the MFA verification flow

cancel - cancels the MFA verification flow

Example

ts
// MFA flow

const MFAModal = ({ mfaMethods, isOpen, setIsOpen }: Props) => {
  const {init, submit, cancel} = useMfa();
  const [selectedMethod, setSelectedMethod] = useState(null)
  const [mfaCode, setMfaCode] = useState('')

  const handleClose = () => {
    cancel();
    setIsOpen(false);
  };

  return (
    <Modal isOpen={isOpen} onClose={handleClose}>
      // Capture the user's MFA code
      {selectedMethod && (
        <button
          onClick={async () => {
            await submit({mfaMethod: selectedMethod, mfaCode})
            setSelectedMethod(null)
            setIsOpen(false)
          }}
        />
      )}
      {mfaMethods.map((mfaMethod) => (
        <button
          onClick={async () => {
            await init({mfaMethod});
            setSelectedMethod(mfaMethod)
          }}
        >
          Choose {mfaMethod} for MFA
        </button>
      ))}
    </Modal>
  )
};

Example

ts
// Error handling

import {
  errorIndicatesMfaVerificationFailed,
  errorIndicatesMfaTimeout,
  errorIndicatesMfaMaxAttempts
} from '@privy-io/expo';
const {submit} = useMfa();
const [errorState, setErrorState] = useState<string | null>(null);

<button
  onClick={async () => {
    try {
      submit('sms', '<user-mfa-code>');
    }
    catch (e) {
      if (errorIndicatesMfaVerificationFailed(e)) {
        setErrorState('Verification failed, resubmit.')
      }
      else if (errorIndicatesMfaMaxAttempts(e)) {
        setErrorState('Max attempts reached, re-initialize MFA.')
      }
      else if (errorIndicatesMfaTimeout(e)) {
        setErrorState('Timeout reached, re-initialize MFA.')
      }
  }}
>
  {errorState ?? 'Verify SMS MFA Code'}
</button>