48 lines
3.2 KiB
Markdown
48 lines
3.2 KiB
Markdown
# 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 <accessToken>` via request interceptor.
|
|
- Response interceptor catches HTTP 401 Unauthorized to trigger silent token renewal via `/api/auth/refresh`.
|