7.6 KiB
7.6 KiB
Feladat Leírás
🎯 Cél
Implementálj egy teljes authentication és authorization rendszert egy blog platformhoz JWT token használatával, cookie-alapú session kezeléssel.
⚠️ MIT KELL IMPLEMENTÁLNI
1. AuthController (src/api/controllers/AuthController.js)
register(req, res) ✏️
// Input: { email, username, password }
// 1. Validálás (kötelező mezők, formátum)
// 2. Ellenőrizd: email és username unique?
// 3. Hash-eld a jelszót: bcrypt.hash(password, 10)
// 4. Hozd létre a user-t: userRepository.create()
// 5. Generálj JWT tokent: jwt.sign()
// 6. Állíts be HTTP-only cookie-t: res.cookie()
// 7. Válasz: { user (jelszó nélkül!), accessToken, refreshToken }
login(req, res) ✏️
// Input: { email vagy username, password }
// 1. Keresd meg a user-t: userRepository.findByEmail() vagy findByUsername()
// 2. Ha nincs user → 401 error
// 3. Ellenőrizd a jelszót: bcrypt.compare(password, user.password)
// 4. Ha nem egyezik → 401 error
// 5. Generálj access és refresh tokent
// 6. Állítsd be a cookie-kat
// 7. Redis session (opcionális): redis.set(`session:${userId}`, ...)
// 8. Válasz: { user, accessToken, refreshToken }
logout(req, res) ✏️
// 1. Töröld a cookie-kat: res.clearCookie('accessToken')
// 2. Redis session törlés: redis.del(`session:${userId}`)
// 3. Válasz: { success: true, message: 'Logged out' }
refreshToken(req, res) ✏️
// 1. Olvasd ki a refresh tokent: req.cookies.refreshToken
// 2. Validáld: jwt.verify(refreshToken, JWT_REFRESH_SECRET)
// 3. Generálj új access tokent
// 4. Állítsd be az új cookie-t
// 5. Válasz: { accessToken }
getCurrentUser(req, res) ✏️
// 1. req.user-ből olvasd ki a user adatokat
// 2. Válasz: { user }
2. AuthMiddleware (src/api/middlewares/authMiddleware.js)
authenticateToken(req, res, next) ✏️
// 1. Token kiolvasás:
// - Cookie-ból: req.cookies.accessToken
// - VAGY Header-ből: req.headers.authorization (Bearer token)
// 2. Ha nincs token → 401 Unauthorized
// 3. Validálás: jwt.verify(token, JWT_SECRET)
// 4. User lekérés: userRepository.findById(decoded.userId)
// 5. req.user = user
// 6. next()
requireRole(allowedRoles) ✏️
// Higher-order function - visszaad egy middleware-t
return (req, res, next) => {
// 1. Ellenőrizd: req.user létezik?
// 2. Ellenőrizd: allowedRoles.includes(req.user.role)?
// 3. Ha nem → 403 Forbidden
// 4. Ha yes → next()
}
// Használat:
// router.delete('/admin', authenticateToken, requireRole(['ADMIN']), ...)
checkOwnership(getResourceOwnerId) ✏️
// Higher-order function
return async (req, res, next) => {
// 1. Szerezd meg a resource owner ID-t:
// const ownerId = await getResourceOwnerId(req)
// 2. Ellenőrizd: req.user.id === ownerId VAGY req.user.role === 'ADMIN'
// 3. Ha nem → 403 Forbidden
// 4. Ha yes → next()
}
// Használat:
// router.put('/blogs/:id', authenticateToken,
// checkOwnership(async (req) => {
// const blog = await blogRepository.findById(req.params.id);
// return blog.authorId;
// }),
// updateController
// );
3. Route-ok védelme
src/api/routes/authRoutes.js ✏️
import { authenticateToken } from '../middlewares/authMiddleware.js';
// Publikus
router.post('/register', ...);
router.post('/login', ...);
router.post('/refresh', ...);
// Védett - add hozzá az authenticateToken middleware-t!
router.post('/logout', authenticateToken, ...);
router.get('/me', authenticateToken, ...);
src/api/routes/blogRoutes.js ✏️
import { authenticateToken, checkOwnership } from '../middlewares/authMiddleware.js';
// Publikus
router.get('/', ...);
router.get('/:id', ...);
// Védett - add hozzá a middleware-eket!
router.post('/', authenticateToken, ...);
router.put('/:id', authenticateToken, checkOwnership(...), ...);
router.delete('/:id', authenticateToken, checkOwnership(...), ...);
📋 Ellenőrző Lista
Implementációd kész, ha az alábbiak működnek:
# 1. Regisztráció
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "test@test.com",
"username": "testuser",
"password": "Test1234"
}'
# → 201 Created, user adatok, cookie beállítva
# 2. Bejelentkezés
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "test@test.com",
"password": "Test1234"
}'
# → 200 OK, user adatok, cookie beállítva
# 3. Current user
curl -X GET http://localhost:3000/api/auth/me \
-H "Authorization: Bearer <token>"
# → 200 OK, user adatok
# 4. Blog létrehozás (védett)
curl -X POST http://localhost:3000/api/blogs \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"title": "Test", "content": "Content"}'
# → 201 Created
# 5. Másik user blogja - módosítás TILOS
curl -X PUT http://localhost:3000/api/blogs/<mas_user_blog_id> \
-H "Authorization: Bearer <token>" \
-d '{"title": "Hacked"}'
# → 403 Forbidden
# 6. Saját blog - módosítás OK
curl -X PUT http://localhost:3000/api/blogs/<sajat_blog_id> \
-H "Authorization: Bearer <token>" \
-d '{"title": "Updated"}'
# → 200 OK
# 7. Kijelentkezés
curl -X POST http://localhost:3000/api/auth/logout \
-H "Authorization: Bearer <token>"
# → 200 OK, cookie törölve
🔑 Kulcs Fontosságú Részek
JWT Token Struktúra
{
userId: "uuid...",
email: "user@example.com",
role: "USER",
iat: 1234567890, // issued at
exp: 1234999999 // expires
}
Cookie Options
{
httpOnly: true, // JavaScript nem fér hozzá
secure: true, // Csak HTTPS (production)
sameSite: 'strict', // CSRF védelem
maxAge: 7 * 24 * 60 * 60 * 1000 // millisec
}
Környezeti Változók
JWT_SECRET=minimum-32-karakter-hosszu-random-string
JWT_REFRESH_SECRET=egy-masik-32-karakter-hosszu-string
JWT_EXPIRES_IN=7d
JWT_REFRESH_EXPIRES_IN=30d
COOKIE_SECRET=meg-egy-secret
⚡ Gyors Start
# 1. Telepítés
npm install
# 2. Env fájl
cp .env.example .env
# Szerkeszd a .env fájlt!
# 3. Docker indítás
npm run docker:up
# 4. Migráció
npm run prisma:migrate
npm run prisma:generate
# 5. Szerver indítás
npm run dev
# 6. Implementáld az auth részeket
# - AuthController: register, login, logout, refresh, getCurrentUser
# - authMiddleware: authenticateToken, requireRole, checkOwnership
# - Routes: add hozzá a middleware-eket
# 7. Tesztelés
# Használd a fenti curl parancsokat
🚨 Gyakori Hibák
❌ Jelszó plain text-ben van tárolva
✅ Használd: bcrypt.hash(password, 10)
❌ Token nincs validálva
✅ Használd: jwt.verify(token, secret)
❌ Cookie nem httpOnly
✅ Állítsd be: httpOnly: true a cookie options-ben
❌ Rossz paraméter sorrend bcrypt.compare()-nál
✅ Helyes: bcrypt.compare(plainPassword, hashedPassword)
❌ req.user nincs beállítva ✅ Az authenticateToken middleware-nek kell beállítania!
🎯 Mit Tanulsz
- ✅ JWT-based authentication
- ✅ Cookie management (httpOnly, secure, sameSite)
- ✅ Password hashing (bcrypt)
- ✅ Middleware pattern
- ✅ Role-based access control (RBAC)
- ✅ Resource ownership validation
- ✅ Clean architecture
- ✅ CQRS pattern
- ✅ Repository pattern
- ✅ Dependency injection
Kezdj neki és sok sikert! 💪