Skip to content

Phase 2: Sanctum Stateful Configuration & CORS Updates #218

@kevalyq

Description

@kevalyq

📦 Sub-Issue of Epic #217

Part of: #217 (httpOnly Cookie Authentication Migration)
Priority: High
Area: Backend, Configuration, Security
Repository: api

Goal

Configure Laravel Sanctum for stateful SPA authentication with httpOnly cookies, including SANCTUM_STATEFUL_DOMAINS whitelist and CORS configuration to support credentials.

Acceptance Criteria

Sanctum Configuration

  • SANCTUM_STATEFUL_DOMAINS configured in .env and .env.example
  • Frontend domains whitelisted (localhost:5173, production domain)
  • config/sanctum.php properly configured for stateful mode
  • Sanctum middleware enabled for API routes

CORS Configuration

  • supports_credentials set to true in config/cors.php
  • allowed_origins includes frontend URL from .env
  • allowed_headers includes X-XSRF-TOKEN
  • exposed_headers configured if needed

Session Configuration

Environment Variables

  • .env.example updated with new variables:
    SANCTUM_STATEFUL_DOMAINS=localhost,localhost:5173,127.0.0.1:5173
    FRONTEND_URL=http://localhost:5173
    SESSION_DOMAIN=localhost

Testing

  • Feature test: Stateful authentication flow works
  • Feature test: CORS credentials accepted
  • Feature test: Frontend domain in whitelist
  • Feature test: Non-whitelisted domains rejected
  • PHPStan passes
  • Pint passes
  • All existing auth tests pass

Documentation

  • docs/guides/sanctum-spa-auth.md created
  • .env.example has clear comments
  • CHANGELOG.md updated

Implementation Details

Files to Modify

Configuration:

// config/sanctum.php
'stateful' => explode(',', env(
    'SANCTUM_STATEFUL_DOMAINS',
    'localhost,localhost:5173,127.0.0.1,127.0.0.1:5173,::1'
)),

'middleware' => [
    'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
    'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],

CORS:

// config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:5173')],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true, // CRITICAL!

Environment:

# .env.example
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:5173,127.0.0.1:5173
FRONTEND_URL=http://localhost:5173
SESSION_DOMAIN=localhost
SESSION_SECURE_COOKIE=false  # true in production

Testing Strategy

# Test CSRF cookie works
curl -X GET http://api.secpal.test/sanctum/csrf-cookie -i

# Test login with credentials
curl -X POST http://api.secpal.test/v1/auth/token \
  -H "Content-Type: application/json" \
  -H "X-XSRF-TOKEN: <token>" \
  -d '{"email":"test@example.com","password":"password"}' \
  --cookie-jar cookies.txt

# Test authenticated request
curl -X GET http://api.secpal.test/v1/user \
  -H "X-XSRF-TOKEN: <token>" \
  --cookie cookies.txt

Dependencies

Security Considerations

  • ⚠️ Never disable CSRF protection in production
  • ⚠️ Use HTTPS in production (SESSION_SECURE_COOKIE=true)
  • ⚠️ Restrict SANCTUM_STATEFUL_DOMAINS to known domains only
  • ⚠️ Never use allowed_origins = ['*'] with supports_credentials = true

Breaking Changes

⚠️ BREAKING CHANGE:

  • Token-based authentication endpoints remain functional
  • New cookie-based authentication flow added alongside
  • Frontend needs to migrate to new flow

Migration Path:

  1. Backend deployed with both auth methods working
  2. Frontend migrates to cookie-based auth
  3. (Future) Deprecate token-based auth

References


Type: Sub-Issue
Priority: High
Estimated Effort: 1-2 days
Sprint: Current

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions