Skip to main content

Dashboard Setup

  1. Go to the Security page.
  2. In the Account MFA section, enable your desired methods (TOTP and/or Passkeys).
  3. (Optional) Toggle “Require at onboarding” to force MFA setup during signup.
  4. (Optional) Toggle “Session-based MFA” to require MFA for every new session.

Your UI SDK Implementation

  • TOTP
  • Passkey
  • Trigger gating: Check userWithMissingInfo?.scope for requiresAdditionalAuth.
  • Detect MFA: Use useSyncMfaFlow to know when to prompt.
  • Add device: Call addDevice() → show QR from uri (install qrcode).
  • Verify: authenticateDevice({ code }) → fetch and show recovery codes → completeAcknowledgement().
  • Refresh: Call getUserDevices() after verification.
import { useMfa, useSyncMfaFlow, useDynamicContext } from "@dynamic-labs/sdk-react-core";

export function AccountTotpMfa() {
const {
    addDevice,
    authenticateDevice,
    getUserDevices,
    getRecoveryCodes,
    completeAcknowledgement,
} = useMfa();
const { userWithMissingInfo } = useDynamicContext();

useSyncMfaFlow({
    handler: async () => {
    if (userWithMissingInfo?.scope?.includes("requiresAdditionalAuth")) {
        const devices = await getUserDevices();
        if (devices.length === 0) {
        const { uri } = await addDevice();
        // Render QR from `uri`, then prompt for OTP
        return;
        }
        // Prompt for OTP
    } else {
        // MFA already satisfied; show recovery codes if needed
        const codes = await getRecoveryCodes();
        // Show `codes` to the user, then:
        await completeAcknowledgement();
    }
    },
});

const verifyOtp = async (code: string) => {
    await authenticateDevice({ code });
    const codes = await getRecoveryCodes();
    // Show `codes` to the user, then:
    await completeAcknowledgement();
    // Refresh device list
    await getUserDevices();
};

return null;
}
Only one verified TOTP device per user
  • Recovery codes are single-use. Regenerate with getRecoveryCodes(true) if needed.
Troubleshooting
  • Error: “401 Unauthorized” when adding a second TOTP device — only one device is supported; delete the existing device first.
  • QR code not displaying — ensure qrcode is installed: npm install qrcode @types/qrcode.
  • Recovery codes not working — each code is single-use; generate new codes if exhausted.

Dynamic UI Implementation

With the Dynamic UI, account-based MFA prompts appear automatically during onboarding/login when additional authentication is required. To explicitly trigger in your app, use useSyncMfaFlow to detect the requirement and usePromptMfaAuth to open the UI. Note: The Dynamic UI is method-agnostic. It automatically prompts with whichever MFA method(s) you have enabled (TOTP and/or Passkeys), so separate TOTP/Passkey tabs are not required here.
import { useSyncMfaFlow, useDynamicContext, usePromptMfaAuth } from "@dynamic-labs/sdk-react-core";

const { userWithMissingInfo } = useDynamicContext();
const promptMfaAuth = usePromptMfaAuth();

useSyncMfaFlow({
  handler: async () => {
    if (userWithMissingInfo?.scope?.includes("requiresAdditionalAuth")) {
      // Opens the Dynamic UI to complete account-based MFA
      await promptMfaAuth(); // No MFA token needed for account-based MFA
    }
  },
});
I