Once users have successfully enrolled in MFA with Privy, they will be required to complete MFA whenever the private key for their embedded wallet must be used. This includes:
Signing messages and transactions
Recovering the embedded wallet on new devices
Exporting the wallet’s private key
Setting a password on the wallet
Enrolling another MFA method or unenrolling an existing one
Once a user has completed MFA on a given device, they can continue to use the wallet on that device without needing to complete MFA for 15 minutes.After 15 minutes have elapsed, Privy will require that the user complete MFA again to re-authorize use of the wallet’s private key.
Requesting an MFA challenge (e.g. sendCode for SMS) - Sends an MFA code to the user’s enrolled method
Submitting the MFA verification (submit) - Verifies the code provided by the user
If your app uses an MFA required listener, you must call privy.mfa.resumeBlockedActions() after successful verification to unblock any pending wallet operations.
If you do not call this, the initial call that triggered MFA will never resolve.
To set up a flow to have the user complete MFA, access the verification interfaces via the authenticated user.mfa namespace:
val user = privy.getUser() ?: return// SMS verificationuser.mfa.sms.verify.sendCode()user.mfa.sms.verify.submit(mfaCode)// TOTP verificationuser.mfa.totp.verify.submit(mfaCode)// Passkey verificationuser.mfa.passkeys.verify.submit(relyingParty = "https://yourdomain.com")
This flow has two core components:
Requesting an MFA challenge (e.g. sendCode for SMS) - Sends an MFA code to the user’s enrolled method
Submitting the MFA verification (submit) - Verifies the code provided by the user
If your app uses an MFA required listener, you must call privy.mfa.resumeBlockedActions() after successful verification to unblock any pending wallet operations.
If you do not call this, the initial call that triggered MFA will never resolve.
After init has been called and the corresponding submit call has not yet occurred, the user may cancel their in-progress MFA flow if they wish.To cancel the current MFA flow, call the cancel method from the useMfa hook:
cancel();
After init has been called and the corresponding submit call has not yet occurred, the user may cancel their in-progress MFA flow if they wish.To cancel the current MFA flow, call the cancel method from the useMfa hook:
cancel();
If the user cancels the MFA flow or verification fails, you must still call resumeBlockedActions to unblock any pending wallet operations. Pass an error to indicate the verification was cancelled.
// Cancel the MFA flow by resuming with an errorawait privy.mfa.resumeBlockedActions(throwing: MyError.mfaCancelled)
If the user cancels the MFA flow or verification fails, you must still call resumeBlockedActions to unblock any pending wallet operations. Pass an error to indicate the verification was cancelled.
// Cancel the MFA flow by resuming with an errorprivy.mfa.resumeBlockedActions(mfaError = Exception("User cancelled MFA"))