From 9c1d836e4f5e2d517f521c0f69c2fa3c13b35a27 Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Wed, 28 Jan 2026 22:51:34 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=92=20Add=20documentation=20for=20auth?= =?UTF-8?q?entication=20architecture=20in=20Pokedex.Online?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../architecture/authentication.md | 322 ++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 docs/projects/Pokedex.Online/architecture/authentication.md diff --git a/docs/projects/Pokedex.Online/architecture/authentication.md b/docs/projects/Pokedex.Online/architecture/authentication.md new file mode 100644 index 0000000..ea9e389 --- /dev/null +++ b/docs/projects/Pokedex.Online/architecture/authentication.md @@ -0,0 +1,322 @@ +# JWT Authentication Architecture + +**Last Updated:** January 28, 2026 +**Status:** ✅ Implemented (Step 9 Complete) + +## Overview + +Pokedex.Online uses JWT (JSON Web Token) authentication for admin access to protected features like the Gamemaster Manager. The system provides: + +- Token-based authentication (stateless) +- 7-day token expiration with refresh capability +- Permission-based access control +- Secure localStorage token storage +- Automatic Bearer token injection in API requests + +## Architecture Diagram + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Client (Browser) │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ AdminLogin View │ +│ ↓ (password) │ +│ useAuth Composable (login → POST /auth/login) │ +│ ↓ (token received) │ +│ localStorage.setItem('auth_token', token) │ +│ ↓ │ +│ api-client.setDefaultHeader('Authorization', Bearer ...) │ +│ ↓ │ +│ Router Guards (requiresAdmin check) │ +│ ↓ │ +│ Protected Routes (GamemasterManager, etc.) │ +│ │ +└─────────────────────────────────────────────────────────────┘ + ↕ +┌─────────────────────────────────────────────────────────────┐ +│ Server (Express) │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ Auth Routes (server/routes/auth.js) │ +│ ↓ /auth/login (POST) → verifyPassword │ +│ ↓ createToken(payload, secret, expiration) │ +│ ↓ return { token, user, expiresIn } │ +│ │ +│ Auth Middleware (server/middleware/auth.js) │ +│ ↓ authMiddleware() → verifyToken(token) │ +│ ↓ requirePermission() → check permissions │ +│ ↓ requireAdmin() → check isAdmin flag │ +│ │ +│ Protected Routes │ +│ ↓ /api/gamemaster/* (with @authMiddleware) │ +│ ↓ /api/feature-flags/* (with @requirePermission) │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## File Structure + +``` +Frontend: +├── src/ +│ ├── composables/ +│ │ └── useAuth.js # Auth state management +│ ├── views/ +│ │ └── AdminLogin.vue # Login page +│ ├── router/ +│ │ └── guards.js # Route protection +│ └── utilities/ +│ └── api-client.js # Enhanced with header mgmt +│ +Backend: +├── server/ +│ ├── utils/ +│ │ └── jwt-utils.js # Token creation/validation +│ ├── middleware/ +│ │ └── auth.js # Auth middleware +│ └── routes/ +│ └── auth.js # Auth endpoints +│ +Tests: +└── tests/unit/ + ├── composables/ + │ └── useAuth.test.js # Auth composable tests + └── views/ + └── AdminLogin.test.js # Login page tests +``` + +## API Endpoints + +### POST /auth/login +Authenticate with password to receive JWT token. + +**Request:** +```json +{ + "password": "admin-password" +} +``` + +**Response (Success):** +```json +{ + "success": true, + "token": "eyJhbGc...", + "expiresIn": 604800, + "user": { + "isAdmin": true, + "permissions": ["admin", "gamemaster-edit"] + } +} +``` + +**Response (Error):** +```json +{ + "error": "Invalid password", + "code": "INVALID_PASSWORD" +} +``` + +### POST /auth/verify +Verify that a token is valid and get its metadata. + +**Request:** +```json +{ + "token": "eyJhbGc..." +} +``` + +**Response:** +```json +{ + "valid": true, + "user": { + "isAdmin": true, + "permissions": ["admin", "gamemaster-edit"] + }, + "expiresIn": 3600, + "expiresAt": "2026-02-04T17:48:00Z" +} +``` + +### POST /auth/refresh +Extend token expiration. + +**Request:** +```json +{ + "token": "eyJhbGc..." +} +``` + +**Response:** +```json +{ + "success": true, + "token": "eyJhbGc...", + "expiresIn": 604800 +} +``` + +### GET /auth/user +Get current user information (requires valid token). + +**Headers:** +``` +Authorization: Bearer eyJhbGc... +``` + +**Response:** +```json +{ + "user": { + "isAdmin": true, + "permissions": ["admin", "gamemaster-edit"], + "loginTime": "2026-01-28T17:48:00Z" + } +} +``` + +### POST /auth/logout +Logout endpoint (token invalidation happens client-side). + +**Response:** +```json +{ + "success": true, + "message": "Logged out successfully" +} +``` + +## Frontend Integration + +### Using useAuth in Components + +```javascript +import { useAuth } from '../composables/useAuth.js'; + +export default { + setup() { + const { + login, // login(password) + logout, // logout() + token, // Reactive token ref + user, // Reactive user ref + isAuthenticated, // Boolean computed + isAdmin, // Boolean computed + hasPermission // (perm) => boolean + } = useAuth(); + + return { + login, + logout, + token, + user, + isAuthenticated, + isAdmin, + hasPermission + }; + } +}; +``` + +### Protected Routes + +```javascript +import { setupAuthGuards } from './router/guards.js'; + +const router = createRouter({ ... }); + +setupAuthGuards(router); + +// In route definitions: +{ + path: '/gamemaster-manager', + component: GamemasterManager, + meta: { requiresAdmin: true } // Protected route +} +``` + +### Setting Up Auth on App Startup + +```javascript +import { useAuth } from './composables/useAuth.js'; + +export default { + async setup() { + const { initializeAuth, setupAuthInterceptor } = useAuth(); + + // Initialize from localStorage + await initializeAuth(); + + // Set up automatic token injection + setupAuthInterceptor(); + } +}; +``` + +## Security Considerations + +### ✅ Implemented + +- JWT tokens with HMAC-SHA256 signature +- 7-day expiration with refresh capability +- Bearer token in Authorization header +- Token stored in localStorage (browser-side) +- Permission-based access control +- Server-side token validation + +### ⚠️ Recommendations + +For production deployment: + +1. **HTTPS Only:** Ensure all authentication over HTTPS +2. **Environment Secrets:** Store JWT_SECRET in environment variables +3. **Password Hashing:** Use bcrypt for password hashing on server +4. **CSRF Protection:** Add CSRF tokens for state-changing requests +5. **Rate Limiting:** Implement rate limiting on /auth/login endpoint +6. **Secure Cookies:** Consider httpOnly cookies for sensitive tokens +7. **Token Rotation:** Implement token rotation for long-lived sessions +8. **Logout Blacklist:** Maintain blacklist of revoked tokens (if needed) + +### Current Limitations + +- Passwords stored in environment/config (suitable for single admin scenario) +- No multi-user support yet (planned for future) +- Tokens valid until expiration (no immediate revocation) +- Single secret key (key rotation not yet implemented) + +## Testing + +Tests verify: + +✅ useAuth composable state management +✅ AdminLogin component rendering and interaction +✅ Login/logout flow +✅ Token state in localStorage +✅ Permission checking logic +✅ Router guard integration + +Run tests: +```bash +npm test # Watch mode +npm test -- AdminLogin # Specific test +npm run test:coverage # Coverage report +``` + +## Next Steps (Phase 3: Steps 10-12) + +- Feature flags system leveraging JWT permissions +- Secure backend configuration management +- Environment-based flag toggleput +- Flag caching and invalidation +- Admin panel for flag management + +--- + +**Related Documentation:** +- [PROGRESS.md](./PROGRESS.md) - Full refactoring progress +- [REFACTORING-PLAN.md](./REFACTORING-PLAN.md) - Complete 68-step plan