✅ Implemented: - Password hashing with bcrypt (salt rounds = 10) - JWT token generation (access 15m, refresh 7d) - Updated login endpoint to return access + refresh tokens - Added refresh and logout endpoints - Updated seed script with hashed passwords - Added test users for all roles (OWNER, MANAGER, GROWER, STAFF) 📝 Files Added/Modified: - backend/src/utils/password.ts (NEW) - backend/src/utils/jwt.ts (NEW) - backend/src/controllers/auth.controller.ts (UPDATED) - backend/src/routes/auth.routes.ts (UPDATED) - backend/prisma/seed.js (UPDATED - now hashes passwords) - CREDENTIALS.md (UPDATED - all test users documented) 🔐 Test Users: - admin@runfoo.run (OWNER) - manager@runfoo.run (MANAGER) - grower@runfoo.run (GROWER) - staff@runfoo.run (STAFF) All passwords: password123 ⏭️ Next: Auth middleware + RBAC
5.6 KiB
5.6 KiB
Sprint 2: Authentication & RBAC
Date: 2025-12-09
Status: 🟡 In Progress
Duration: 8-10 hours
Priority: 🔴 Critical
🎯 Objective
Implement secure authentication and role-based access control (RBAC) to protect all API endpoints and enforce permissions based on user roles.
📋 Current State
What Works
- ✅ Basic login endpoint exists (
/api/auth/login) - ✅ JWT plugin registered in Fastify
- ✅ User model with Role enum (OWNER, MANAGER, GROWER, STAFF)
- ✅ Frontend AuthContext exists
What's Missing
- ❌ Password hashing (currently plaintext)
- ❌ JWT token generation and validation
- ❌ Auth middleware to protect routes
- ❌ RBAC middleware for role-based permissions
- ❌ Refresh token logic
- ❌ Proper error handling for auth failures
🏗️ Implementation Plan
Phase 1: Backend Auth Core (3-4 hours)
Task 2.1: Password Hashing
- Install bcrypt:
npm install bcrypt @types/bcrypt - Create password utility functions (hash, compare)
- Update seed script to hash passwords
- Update login controller to compare hashed passwords
Task 2.2: JWT Token Generation
- Create JWT utility functions (generate access token, generate refresh token)
- Update login endpoint to return JWT tokens
- Add token expiry configuration (15min access, 7d refresh)
- Store refresh tokens in Redis
Task 2.3: Auth Middleware
- Create
authenticatemiddleware (verify JWT) - Add user info to request object
- Handle expired tokens
- Handle invalid tokens
Task 2.4: RBAC Middleware
- Create
authorize(...roles)middleware - Check user role against allowed roles
- Return 403 Forbidden if unauthorized
Phase 2: Protected Routes (2-3 hours)
Task 2.5: Apply Auth to Routes
- Protect
/api/rooms(all roles) - Protect
/api/batches(all roles) - Protect
/api/timeclock(all roles) - Add role restrictions where needed
Task 2.6: Refresh Token Endpoint
- Create
/api/auth/refreshendpoint - Validate refresh token
- Generate new access token
- Return new tokens
Task 2.7: Logout Endpoint
- Create
/api/auth/logoutendpoint - Invalidate refresh token in Redis
- Clear tokens from client
Phase 3: Frontend Integration (2-3 hours)
Task 2.8: Update AuthContext
- Store tokens in localStorage
- Add token refresh logic
- Add automatic logout on 401
- Add token to all API requests
Task 2.9: Update API Client
- Create axios instance with interceptors
- Add Authorization header to requests
- Handle 401 (refresh token or logout)
- Handle 403 (show permission error)
Task 2.10: Update Login Flow
- Store tokens on successful login
- Redirect to dashboard
- Handle login errors
- Add loading states
Phase 4: Testing & Polish (1-2 hours)
Task 2.11: Manual Testing
- Test login with correct credentials
- Test login with wrong credentials
- Test protected routes without token
- Test protected routes with valid token
- Test token expiry and refresh
- Test logout
Task 2.12: Add More Test Users
- Create users for each role (MANAGER, GROWER, STAFF)
- Update seed script
- Document test credentials
🔐 Security Considerations
Password Security
- Use bcrypt with salt rounds = 10
- Never log passwords
- Never return password hashes in API responses
Token Security
- Access tokens: Short-lived (15 minutes)
- Refresh tokens: Longer-lived (7 days)
- Store refresh tokens in httpOnly cookies (future enhancement)
- Invalidate refresh tokens on logout
RBAC Rules
- OWNER: Full access to everything
- MANAGER: Full access except user management
- GROWER: Read/write batches, rooms, tasks
- STAFF: Read-only + timeclock
📊 Success Criteria
- All API endpoints require authentication
- Passwords are hashed with bcrypt
- JWT tokens working (access + refresh)
- Role-based permissions enforced
- Frontend stores and uses tokens correctly
- Token refresh works automatically
- Logout invalidates tokens
- Multiple test users available (one per role)
- No security vulnerabilities (no plaintext passwords, no exposed secrets)
🧪 Testing Checklist
Backend Tests
- Login with valid credentials returns tokens
- Login with invalid credentials returns 401
- Protected route without token returns 401
- Protected route with valid token returns data
- Protected route with expired token returns 401
- Refresh token endpoint works
- Logout invalidates refresh token
- RBAC blocks unauthorized roles
Frontend Tests
- Login form submits correctly
- Tokens stored in localStorage
- API requests include Authorization header
- 401 triggers token refresh
- Logout clears tokens and redirects
📝 Files to Modify
Backend
backend/package.json- Add bcrypt dependencybackend/src/utils/password.ts- New file (hash, compare)backend/src/utils/jwt.ts- New file (generate, verify)backend/src/middleware/auth.ts- New file (authenticate, authorize)backend/src/controllers/auth.controller.ts- Update login, add refresh, logoutbackend/src/routes/*.routes.ts- Add auth middlewarebackend/prisma/seed.js- Hash passwords
Frontend
frontend/src/context/AuthContext.tsx- Update token handlingfrontend/src/lib/api.ts- New file (axios instance with interceptors)frontend/src/pages/LoginPage.tsx- Update login flow
🚀 Let's Begin
Starting with Task 2.1: Password Hashing...