301 lines
7.6 KiB
Markdown
301 lines
7.6 KiB
Markdown
# 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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)` ✏️
|
|
```javascript
|
|
// 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` ✏️
|
|
```javascript
|
|
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` ✏️
|
|
```javascript
|
|
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:
|
|
|
|
```bash
|
|
# 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
|
|
```javascript
|
|
{
|
|
userId: "uuid...",
|
|
email: "user@example.com",
|
|
role: "USER",
|
|
iat: 1234567890, // issued at
|
|
exp: 1234999999 // expires
|
|
}
|
|
```
|
|
|
|
### Cookie Options
|
|
```javascript
|
|
{
|
|
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
|
|
```env
|
|
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
|
|
|
|
```bash
|
|
# 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! 💪**
|