✅ 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
220 lines
5.6 KiB
Markdown
220 lines
5.6 KiB
Markdown
# 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 `authenticate` middleware (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/refresh` endpoint
|
|
- [ ] Validate refresh token
|
|
- [ ] Generate new access token
|
|
- [ ] Return new tokens
|
|
|
|
#### Task 2.7: Logout Endpoint
|
|
|
|
- [ ] Create `/api/auth/logout` endpoint
|
|
- [ ] 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 dependency
|
|
- `backend/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, logout
|
|
- `backend/src/routes/*.routes.ts` - Add auth middleware
|
|
- `backend/prisma/seed.js` - Hash passwords
|
|
|
|
### Frontend
|
|
|
|
- `frontend/src/context/AuthContext.tsx` - Update token handling
|
|
- `frontend/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**...
|