Skip to content

[EPIC] Migrate to httpOnly Cookie Authentication #205

@kevalyq

Description

@kevalyq

🎯 Vision

Migrate authentication from token-based (localStorage) to httpOnly cookie-based authentication for enhanced security against XSS attacks and improved session management.


📋 Sub-Issues & Work Plan

Frontend Implementation Phases

  • TBD Phase 1: CSRF Token Integration & API Service Updates
  • TBD Phase 2: AuthContext Migration & Token Storage Removal
  • TBD Phase 3: Integration Testing & Documentation

Backend Implementation (SecPal/api)

  • api#210 ✅ CSRF Token Endpoint & Security Hardening Complete (23.11.2025)
  • api#218 Sanctum Stateful Configuration & CORS Updates
  • api#219 Integration Testing & Documentation

Backend Epic: SecPal/api#217


🔐 Security Issue

Priority: High
Area: Authentication
Related: PR #204 (Login UI implementation)

Problem

Currently, the authentication token is stored in localStorage:

// src/services/storage.ts
localStorage.setItem('auth_token', token);

Security vulnerabilities:

  1. XSS-vulnerable: JavaScript can access token → If XSS vulnerability exists, attacker can steal token
  2. No built-in expiration: Token persists until manually cleared
  3. Accessible from any script: Browser extensions, third-party scripts can read

🎯 Success Criteria

Frontend

  • Authentication token stored in httpOnly cookie (backend-managed)
  • No token accessible via JavaScript
  • CSRF token handling implemented
  • All existing auth tests still pass
  • Documentation updated

Backend

  • CSRF Protection: /sanctum/csrf-cookie endpoint accessible
  • httpOnly Cookies: Session cookies configured securely
  • Sanctum Stateful: Frontend domain whitelisted
  • CORS Configured: supports_credentials: true
  • All Tests Pass: Backend auth tests work

🔒 Security Improvements

Current (Token-based):

  • ❌ Token stored in localStorage (XSS-vulnerable)
  • ❌ Token accessible via JavaScript
  • ❌ Manual token management required
  • ❌ No built-in expiration enforcement

New (httpOnly Cookies):

  • ✅ Token in httpOnly cookie (XSS-protected)
  • ✅ Browser handles token automatically
  • ✅ CSRF protection via Sanctum
  • ✅ Server-side expiration control
  • ✅ Secure + SameSite flags

📚 Technical Architecture

Frontend Changes

Authentication Flow:

// 1. Get CSRF Token (before login)
await fetch(`${API_URL}/sanctum/csrf-cookie`, {
  credentials: 'include'
});

// 2. Login with credentials
const response = await fetch(`${API_URL}/v1/auth/token`, {
  method: 'POST',
  credentials: 'include', // Send/receive cookies
  headers: {
    'Content-Type': 'application/json',
    'X-XSRF-TOKEN': getCsrfTokenFromCookie()
  },
  body: JSON.stringify(credentials)
});

// 3. Subsequent authenticated requests
await fetch(`${API_URL}/v1/secrets`, {
  credentials: 'include',
  headers: {
    'X-XSRF-TOKEN': getCsrfTokenFromCookie()
  }
});

Files to Modify:

  • src/services/authApi.ts - Add CSRF handling, use credentials: 'include'
  • src/contexts/AuthContext.tsx - Remove token state, rely on cookies
  • src/services/storage.ts - Remove token storage functions
  • src/utils/csrf.ts - New utility for CSRF token extraction
  • All API service files - Add credentials: 'include' to fetch calls

Backend Configuration (SecPal/api)

Sanctum Stateful:

// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS')),

CORS:

// config/cors.php
'supports_credentials' => true,
'allowed_origins' => [env('FRONTEND_URL')],

🔗 Related Issues

Frontend (this repo):

Backend (SecPal/api):

  • api#217 - Epic: httpOnly Cookie Authentication Migration
  • api#210 ✅ Complete - CSRF Token Endpoint
  • api#218 - Sanctum Stateful Configuration
  • api#219 - Integration Testing & Documentation

🔗 Dependencies

Requires:

  • Backend api#217 must be complete before frontend can fully migrate
  • api#218 (Sanctum configuration) must be deployed
  • HTTPS in production (httpOnly + Secure flags)

Blocks:

  • None (security enhancement)

📊 Implementation Timeline

Backend Phase 1 (Complete): CSRF Endpoint ✅ Done (23.11.2025)
Backend Phase 2 (Next): Sanctum Configuration - api#218 (~1-2 days)
Backend Phase 3: Integration Testing - api#219 (~1 day)
Frontend Phase 1: CSRF Integration (~1-2 days)
Frontend Phase 2: AuthContext Migration (~1-2 days)
Frontend Phase 3: Testing & Docs (~1 day)

Total Estimated Effort: ~6-8 days (cross-repo)
Current Progress: ~15% (Backend CSRF done)


📖 References


✅ Acceptance Criteria Summary

  • Authentication token stored in httpOnly cookie
  • No token accessible via JavaScript
  • CSRF protection enabled and tested
  • All existing auth tests still pass
  • credentials: 'include' on all authenticated requests
  • CSRF token sent in X-XSRF-TOKEN header
  • Login/logout flow works correctly
  • Documentation updated
  • Works in development and production

Type: Epic
Priority: High (Security Feature)
Target Milestone: v0.3.0
Frontend Status: 📅 Planned (waiting for backend api#218)
Backend Status: 🔄 In Progress (30% complete, see api#217)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    💡 Ideas

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions