Skip to Content
Clerk logo

Clerk Docs

Ctrl + K
Go to clerkstage.dev

Multi-factor

Clerk supports multifactor authentication (MFA), often referred to as two-factor authentication or 2FA. By enabling MFA, you can encourage or require your users to perform a second verification check during sign-in.

The term multi-factor comes from the 3 main types of verifications:

  • Knowledge-based - something you know, i.e. a password
  • Possession-based - something you have, i.e. a phone or yubikey
  • Inherent based - something you are, i.e. a fingerprint or a facial scan

By enforcing two different types of verifications, you can drastically improve your user's security. Most websites make this step optional, empowering their users with their own security.

Interested in single-factor authentication? Check out our guides on password-based and passwordless authentication.

Before you start

  • You need to create a Clerk Application in your Clerk Dashboard. For more information, check out our Set up your application guide.
  • You need to install the correct SDK for your application. You can find steps on how to do so through Clerk's quickstart guides.

Configuration

Although not available as an option in the initial new application screen, you can opt to turn on multifactor authentication (MFA) from the configuration screen in the Clerk Dashboard. Go to User & Authentication > Multi-factor.

Clerk currently offers the following MFA strategies:

  • SMS verification code
  • Authenticator application (also known as TOTP - Time-based One-time Password)
  • Backup codes
The 'Multi-factor' tab under the 'User & Authentication' section of the Clerk Dashboard.

Once MFA is turned on, registered users can turn on MFA for their own account through their User Profile page.

Custom flow

If you want more flexibility, you can make use of lower-level commands and create a completely custom multi-factor authentication flow.

You still need to configure your instance in order to enable mutli-factor authentication, and your users will also need to explicitly enable MFA for their account, as described at the top of this guide.

Signing in to an MFA-enabled account is identical to the regular sign-in process. However, in the case of an MFA-enabled account, a sign-in won't convert until both verifications (first factor and second factor) are completed.

  • Initiate the sign-in process by collecting the user's authentication identifier.
  • Prepare the first factor verification.
  • Attempt to complete the first factor verification.
  • Prepare the second factor verification. (This is where MFA comes into play)
  • Attempt to complete the second factor verification.

Let's see the above in action.

import { useSignIn } from "@clerk/clerk-react"; function SignInPage() { const { signIn } = useSignIn(); async function onClick(e) { e.preventDefault(); // Sign the user in with email address and // password. await signIn.create({ identifier: "user@example.com", password: "********", }); // Prepare the second factor verification by // specifying the phone code strategy. An SMS // message with a one-time code will be sent // to the user's verified phone number. await signIn.prepareSecondFactor({ strategy: "phone_code", }); // Attempt to complete the second factor // verification, passing the previously // received one-time code. await signIn.attemptSecondFactor({ strategy: "phone_code", code: "123456", }); } return ( <button onClick={onClick}> Sign in with MFA </button> ); }
const { client } = window.Clerk; // Sign the user in with the required first // factor strategy. In this case it's email // and password. const signIn = await client.signIn.create({ identifier: "user@example.com", password: "**********", }); // Prepare the second factor verification by // specifying the phone code strategy. An SMS // message with a one-time code will be sent // to the user's verified phone number. await signIn.prepareSecondFactor({ strategy: "phone_code", }); // Attempt to complete the second factor // verification, passing the previously // received one-time code. await signIn.attemptSecondFactor({ strategy: "phone_code", code: "123456", });

What did you think of this content?

Clerk © 2023