Advanced

Security Features

CSRF protection and two-factor authentication (2FA) implementation

Learn about security features in Nuxt Umbu, including CSRF protection and two-factor authentication (2FA) implementation.

Overview

Nuxt Umbu provides built-in security features to protect your authentication system:

  • CSRF Protection: Cross-Site Request Forgery protection for Sanctum
  • Two-Factor Authentication: Optional 2FA support for enhanced security
  • Secure Cookie Configuration: Production-ready cookie security settings

CSRF Protection

What is CSRF?

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated.

Sanctum CSRF

Nuxt Umbu integrates with Laravel Sanctum's CSRF protection:

// nuxt.config.ts
export default defineNuxtConfig({
  auth: {
    provider: 'sanctum',
    csrf: '/sanctum/csrf-cookie'  // CSRF cookie endpoint
  }
})

How CSRF Works

  1. Initial Request: Client requests CSRF cookie
  2. Cookie Set: Server sets CSRF cookie
  3. Subsequent Requests: Client includes CSRF token in headers
  4. Validation: Server validates token before processing

Using CSRF Protection

Automatic CSRF Handling

Nuxt Umbu automatically handles CSRF for Sanctum:

import { ensureCsrf } from '#auth-utils'

// Ensure CSRF token is present before authenticated requests
await ensureCsrf()

// Now make authenticated requests
const response = await $fetch('/api/protected', {
  method: 'POST',
  body: { data: 'value' }
})

Manual CSRF Token

If you need the CSRF token manually:

import { useAuthStore } from '#auth-utils'

const authStore = useAuthStore()
const csrfToken = authStore.csrfToken

// Use in custom requests
await $fetch('/api/protected', {
  headers: {
    'X-XSRF-TOKEN': csrfToken
  }
})

CSRF Configuration

Custom CSRF Endpoint

auth: {
  provider: 'sanctum',
  csrf: '/api/csrf-token'  // Custom endpoint
}

CSRF in Development

CSRF is automatically handled in development with relaxed security:

if (isDev) {
  options.cookie.prefix = 'auth.'
  options.cookie.options.secure = false
}

Passport CSRF (Optional)

Passport provider can optionally use CSRF:

auth: {
  provider: 'passport',
  csrf: '/api/csrf-token'  // Optional CSRF endpoint
}

Two-Factor Authentication (2FA)

What is 2FA?

Two-Factor Authentication adds an extra layer of security by requiring a second form of verification in addition to your password.

Enabling 2FA

2FA is automatically enabled when you configure a twoFactor endpoint:

strategies: {
  password: {
    endpoints: {
      login: { url: '/oauth/token', method: 'post' },
      user: { url: '/api/user', method: 'get' },
      twoFactor: {
        url: '/api/2fa/verify',
        method: 'post',
        property: 'access_token',
        expires: 'expires_in',
        headerName: 'X-2FA-Token'
      }
    },
    redirect: {
      login: '/login',
      logout: '/',
      twoFactor: '/2fa'
    }
  }
}

2FA Configuration Options

TwoFactorFetchOption

type TwoFactorFetchOption = {
  url: string              // 2FA verification endpoint
  method: string           // HTTP method
  property?: string       // Where token comes from (default: access_token)
  expires?: string        // Where expiration comes from (default: expires_in)
  headerName?: string     // Header name for token (default: '2fa')
}

Configuration Example

twoFactor: {
  url: '/api/2fa/verify',
  method: 'post',
  property: 'token',           // Response property containing token
  expires: 'expires',          // Response property containing expiration
  headerName: 'Authorization' // Custom header name
}

Using 2FA

Middleware Protection

When 2FA is enabled, the middleware automatically protects routes:

// nuxt.config.ts
export default defineNuxtConfig({
  auth: {
    // 2FA endpoint configured
    strategies: {
      password: {
        endpoints: {
          twoFactor: { url: '/api/2fa/verify', method: 'post' }
        }
      }
    }
  }
})

// Middleware is automatically registered
// Routes with twoFactor middleware will require 2FA verification

Manual 2FA Verification

const { $auth } = useNuxtApp()

// Verify 2FA code
const result = await $auth.twoFactor('password', '123456')

if (result.success) {
  // 2FA verified, user authenticated
  navigateTo('/dashboard')
} else {
  // Invalid code
  showError('Invalid 2FA code')
}

2FA in Components

<script setup lang="ts">
const { $auth } = useNuxtApp()
const code = ref('')

const verify2FA = async () => {
  const result = await $auth.twoFactor('password', code.value)
  
  if (result.success) {
    await navigateTo('/dashboard')
  } else {
    alert('Invalid code')
  }
}
</script>

<template>
  <form @submit.prevent="verify2FA">
    <input v-model="code" type="text" placeholder="Enter 2FA code" />
    <button type="submit">Verify</button>
  </form>
</template>

2FA Redirects

Configure where users are redirected during 2FA flow:

redirect: {
  login: '/login',
  logout: '/',
  twoFactor: '/2fa',  // Redirect to 2FA page when needed
  home: '/dashboard'
}

2FA Middleware

The 2FA middleware is automatically registered when you configure a twoFactor endpoint:

// Automatically registered
addRouteMiddleware({
  name: 'umbu:two-factor',
  path: resolve('./runtime/' + provider + '/middleware/twoFactor')
})

Using 2FA Middleware

<script setup>
// Protect route with 2FA middleware
definePageMeta({
  middleware: ['umbu:two-factor']
})
</script>

Security Best Practices

CSRF Protection

  1. Always enable CSRF in production
    auth: {
      csrf: '/sanctum/csrf-cookie'
    }
    
  2. Use HTTPS in production
    cookie: {
      options: {
        secure: true
      }
    }
    
  3. Validate CSRF on server
    • Ensure your backend validates CSRF tokens
    • Use Sanctum's built-in CSRF protection

2FA Implementation

  1. Use secure 2FA methods
    • TOTP (Time-based One-Time Password)
    • SMS codes (with rate limiting)
    • Hardware tokens
  2. Implement rate limiting
    • Limit 2FA attempts
    • Lock accounts after failed attempts
  3. Backup codes
    • Provide backup recovery codes
    • Allow secure code regeneration
  4. Session management
    • Remember 2FA for trusted devices
    • Require re-verification for sensitive actions
  1. Use secure cookie settings in production
    cookie: {
      prefix: '__Secure-',
      options: {
        httpOnly: true,
        secure: true,
        sameSite: 'Strict'
      }
    }
    
  2. Set appropriate expiration
    options: {
      maxAge: 60 * 60 * 24 * 7  // 7 days
    }
    
  3. Use proper prefixes
    • __Secure- for production
    • __Host- for strict security

Common Security Issues

CSRF Token Missing

Problem: CSRF token not included in requests

Solution:

import { ensureCsrf } from '#auth-utils'

// Ensure CSRF token before requests
await ensureCsrf()

2FA Not Working

Problem: 2FA verification fails

Solution:

  1. Verify endpoint configuration
  2. Check response property names
  3. Ensure header name matches backend expectations
  4. Verify code format (6 digits, etc.)

Problem: Cookies not secure in production

Solution:

cookie: {
  prefix: '__Secure-',
  options: {
    secure: true,
    httpOnly: true,
    sameSite: 'Strict'
  }
}

Testing Security Features

Testing CSRF

// test/csrf.test.ts
import { describe, it, expect } from 'vitest'
import { ensureCsrf } from '#auth-utils'

describe('CSRF Protection', () => {
  it('should fetch CSRF token', async () => {
    await ensureCsrf()
    // Verify token is present
  })
})

Testing 2FA

// test/2fa.test.ts
import { describe, it, expect } from 'vitest'

describe('2FA', () => {
  it('should verify 2FA code', async () => {
    const { $auth } = useNuxtApp()
    const result = await $auth.twoFactor('password', '123456')
    expect(result.success).toBe(true)
  })
})

Security Checklist

Before Production

  • CSRF protection enabled
  • HTTPS configured
  • Secure cookie settings
  • 2FA implemented for sensitive actions
  • Rate limiting configured
  • Session management configured
  • Error handling doesn't leak information
  • Logging configured for security events

Regular Security Audits

  • Review dependency updates
  • Check for security advisories
  • Audit authentication flows
  • Test for common vulnerabilities
  • Review access logs
  • Update security configurations

Troubleshooting

CSRF Issues

CSRF cookie not being set

  1. Verify CSRF endpoint is correct
  2. Check browser console for errors
  3. Ensure cookies are enabled
  4. Verify backend CSRF configuration

CSRF token validation failing

  1. Check token format
  2. Verify header name
  3. Ensure token is included in requests
  4. Check backend validation logic

2FA Issues

2FA middleware not triggering

  1. Verify twoFactor endpoint is configured
  2. Check that middleware is registered
  3. Ensure route has middleware applied
  4. Check redirect configuration

2FA verification failing

  1. Verify endpoint URL and method
  2. Check response property names
  3. Ensure code format is correct
  4. Verify header name matches backend

Additional Security Resources