# 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