Adding Two‑Factor Authentication (2FA) to a Laravel API (Laragear + Sanctum)

I recently wired up Two‑Factor Authentication (2FA) for the Profresh API. There are a few ways to do 2FA in Laravel, but I chose the Laragear 2FA package because it’s simple, well‑documented, and plays nicely with Sanctum.

2 min read


We’ll add 2FA to a Laravel Sanctum API in 3 steps

  1. Enable 2FA (generate secret + QR, confirm with OTP)

  2. Return recovery codes & allow disabling

  3. Enforce 2FA at login with a secure flow


I used the Laragear 2FA package (v2 for Laravel 10) with Sanctum. Full code is in my repo: ProFresh GitHub.

Who this is for
  • You’re building a JSON API with Laravel 10 + Sanctum.

  • You’re comfortable with basic auth flows and Form Requests.

  • You want a clean, minimal 2FA setup without writing your own logic

Step 1: Enable 2FA

When a user opts-in, we generate a secret, return a QR code, and mark the setup as “in progress.”

What happens:
Step 2: Confirm & Recovery Codes

The user confirms setup with a 6-digit code from their authenticator app.






What happens:

Step 3: Regenerate Codes or Disable 2FA (optional)
  • Disable: Gives user option to disable 2FA









  • Recovery codes endpoint: - Generates a fresh set of recovery codes on demand




Step 4: Enforce 2FA at login

Here’s the secure API login flow:

  • User submits email/password.

  • If 2FA is disabled return a Sanctum token like normal.

  • If 2FA is enabled create a short‑lived, encrypted session marker and return 2fa required.

  • User submits the 6‑digit code to a dedicated endpoint.

  • If the code is valid clear the marker and issue the Sanctum token.

Controller: confirm login















What happens here:
  • If 2FA is enabled, no token is returned yet — only a two_fa_required response.

  • If 2FA is not enabled, we proceed as normal and issue the token.

  • Set session in LoginUserService class



Confirming the login:

Once the user enters their OTP, the second endpoint kicks in:
















What this does:

  • Validates the 6-digit code via the TwoFactorLoginRequest.

  • If valid, it clears the short-lived 2fa_login marker from the session.

  • Finally, it issues a first-class Sanctum token, just like a normal login.


🏁 Wrapping Up

And that’s it — you now have a full 2FA setup running in your Laravel API.
This approach keeps your login flow clean, secure, and simple enough to extend later.

If you want to take it a step further, check out Securing articles on advanced MFA authentication — they cover some great extra security layers.

You can also look at the frontend side of this feature and explore the full implementation in my open-source project ProFresh.

If you hit any issues or have questions, feel free to reach out — I’ve probably run into the same thing.
Thanks for reading — hope this helps you make your next Laravel app a bit more secure!