Files
GKNB_MSTM071/Backend/harmadik gyakorlat/FELADAT.md
T
2026-02-25 20:16:03 +01:00

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
}
{
  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! 💪