Sanctum

Sanctum 2FA Flow

Complete 2FA flow with optional middleware in Nuxt Umbu

In Nuxt Umbu, Two-Factor Authentication (2FA) is completely optional.

It is only enabled when the 2fa endpoint is configured within the selected strategy.
If this endpoint is not defined — or is removed — 2FA support is automatically disabled automatically, without affecting the standard authentication flow.

This provides full flexibility, allowing you to use standard Sanctum authentication or enable 2FA only when needed.


How 2FA Works with Sanctum

Below is the complete and correct 2FA flow for the Sanctum provider in Nuxt Umbu, including optional middleware usage and SSR behavior.

Unlike the Passport strategy, Sanctum does NOT require a custom 2FA header, because authentication is session-based and Laravel already knows the authenticated user through the session cookie.

This means:
  • No Authorization: Bearer header
  • No custom X-2FA header
  • Laravel session handles user state
  • CSRF protection is handled automatically

Official Laravel documentation:Laravel Sanctum


1. User Logs In Normally

Authentication works through Laravel session cookies (Sanctum).

The user logs in using: POST /login

2. Frontend Sends the 2FA Code

Example:

const { $auth } = useNuxtApp()

const handleVerify = async () => {
    try {
        await $auth._2fa('admin', code)
        // success
    } catch (err) {
        // error
    }
}

3. Backend validates the code

Your Laravel backend must validate the code using the current session user.

If valid, it MUST return:

    {
    "access_token": "temporary-2fa-token",
    "expires_in": 3600
    }

If the response does not contain both:

access_token

expires_in

Nuxt Umbu will throw:

    throw new Error('Invalid 2FA response');

Without this structure, 2FA will not work.

4. Nuxt Umbu stores the token

On success:

  • If SSR is being used:
  • Middleware also validates on the server
  • A cookie named token_2fa is checked
  • Currently the cookie name is fixed
  • Future versions will allow configuring the cookie name

2FA Middleware (Optional)

To protect pages with 2FA:

definePageMeta({
  layout: false,
  middleware: ['auth', '_2fa']
})

Important:

  • auth middleware validates login
  • _2fa middleware validates 2FA completion
  • Using _2fa is NOT mandatory
  • Only required if you want to enforce 2FA protection
  • If you do not use _2fa, 2FA will not block access.

Enabling / Disabling 2FA

2FA is enabled only if the endpoint is defined:

nuxt.config.ts
export default defineNuxtConfig({
    auth: {
        csrf: '/sanctum/csrf-cookie',
        provider: 'sanctum',
        strategies: {
            client: {
                redirect: {
                    login: '/auth',
                    logout: '/auth'
                },
                user: {
                    property: 'profile'
                },
                endpoints: {
                    login:  { url: '/login', method: 'post' },
                    user:   { url: '/api/profile', method: 'get' },
                    '2fa':  { url: '/api/token-2fa', method: 'post' }, // If present → 2FA enabled
                    logout: { url: '/api/logout', method: 'post' }
                }
            }
        }
    },
})

If you remove:

Then:

  • _2fa() method should not be used
  • _2fa middleware should not be applied
  • System works as standard Sanctum authentication

Server-Side Validation (SSR)

When using SSR:

  • Middleware runs on server
  • Reads cookie token_2fa
  • Validates active strategy
  • Validates session state
  • Forces logout if invalid
  • This ensures protection in:
  • CSR
  • SSR
  • Page refresh
  • Direct URL access