# ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management - **Status**: `DECIDED_HYBRID_DUAL_TOKEN` - **Date**: 2026-08-06 - **Context**: Audit finding `ARCH-001` and security findings `SEC-001`, `SEC-002`, `SEC-003` evaluated authentication architecture. User finalized product decision: Storefront is built with Next.js (SSR/SEO), while the Admin Panel is an isolated, standalone React SPA focused on maximum security and performance. --- ## 1. Context and Problem Statement The Admin Panel application requires an enterprise-grade authentication token management strategy satisfying three key pillars: 1. **Maximum Security**: Complete defense against Cross-Site Scripting (XSS) token exfiltration and Cross-Site Request Forgery (CSRF) on administrative endpoints. 2. **Session Resilience**: Seamless session renewal via dual tokens (`JWT_ACCESS_SECRET` and `JWT_REFRESH_SECRET`) without persisting long-lived access tokens in vulnerable browser storage (`localStorage`). 3. **API Client & Authorization Interception**: Strict authorization boundary enforcement (`@Roles('Admin')`) via Axios request interceptors and HttpOnly cookies. --- ## 2. Evaluation of Options ### Option A: Storefront Next.js & Admin SPA Shared Storage (`localStorage`) - **Assessment**: **REJECTED**. Exposes Admin access tokens to XSS exfiltration. ### Option B: Pure In-Memory Token Storage - **Assessment**: **REJECTED**. Causes immediate logout on page refresh (`F5`), causing unacceptable UX degradation for admin workflows. ### Option C: Dual-Token Hybrid Architecture (In-Memory Access Token + HttpOnly Refresh Cookie) - **Description**: - `POST /api/auth/verify-otp` / admin login validates credentials and issues a short-lived `accessToken` (signed with `JWT_ACCESS_SECRET`) in-memory, while setting an `HttpOnly`, `Secure`, `SameSite=Strict` cookie containing a `refreshToken` (signed with `JWT_REFRESH_SECRET`). - Access tokens are held exclusively in-memory inside Zustand / Axios client closures. - Background silent refresh via `POST /api/auth/refresh` exchanges the HttpOnly cookie for a new access token on page reload or 401 expiration. - **Security Assessment**: **EXCELLENT**. Immune to XSS exfiltration of refresh tokens. `JWT_ACCESS_SECRET` and `JWT_REFRESH_SECRET` environment variables enforced at NestJS bootstrap. - **Verdict**: **FINALIZED ARCHITECTURE FOR ADMIN PANEL**. --- ## 3. Decision Outcome **Chosen Architecture**: **Option C — Dual-Token Hybrid Architecture for Standalone Admin Panel**. ### Implementation Specifications for `TASK-AUTH-001` & Backend: 1. **Backend Configuration (`TASK-SEC-001`)**: - Enforce mandatory startup validation in NestJS `main.ts` for TWO secrets: `JWT_ACCESS_SECRET` and `JWT_REFRESH_SECRET` (each >= 32 characters/bytes). Fail bootstrap immediately (`process.exit(1)`) if either secret is missing or insecure. 2. **Admin Panel Client (`src/` / Admin SPA)**: - Configure Axios client with `withCredentials: true`. - Store `accessToken` strictly in-memory (Zustand state / closure). - Automatically attach `Authorization: Bearer ` via request interceptor. - Response interceptor catches HTTP 401 Unauthorized to trigger silent token renewal via `/api/auth/refresh`.