Headless MFA supports only one verified TOTP device per user.
1. Component Setup & Hooks
First, set up your component state and import the necessary hooks. You’ll need to manage the user’s devices, the current UI view (e.g., device list, QR code, or OTP input), and errors.2. Fetching User Devices
On component mount, if the user is logged in, fetch their MFA devices to display them.3. Handling the MFA Flow
TheuseSyncMfaFlow
hook is key for account-based MFA. It detects when an MFA challenge is required and calls your handler, letting you update the UI to prompt the user.
4. Adding a New Device
Create a function to start theaddDevice
flow. This generates a secret and URI for displaying a QR code.
5. Authenticating the Device
After the user scans the QR code and enters an OTP from their authenticator app, useauthenticateDevice
to verify the code.
For Account-Based MFA
For account-based MFA, you don’t need to create a long-lived token. Authenticating the device completes the login flow.For Action—Based MFA
For action-based MFA, you need to create a token to authorize sensitive actions. This can be a single-use or persistent token.6. Building the UI
Finally, build the UI to handle the different views in your MFA flow.- Users can use recovery codes instead of their device.
- Each code is single-use.
- Generate new codes after a user exhausts their supply.
Troubleshooting
- Error: “401 Unauthorized” when adding second TOTP device: Only one TOTP device is supported per user. Delete the existing device before adding a new one.
- QR code not displaying: Ensure you have the
qrcode
package installed:npm install qrcode @types/qrcode
. - Recovery codes not working: Each recovery code is single-use. Generate new codes if all have been consumed.