diff --git a/backend/src/controllers/user.controller.ts b/backend/src/controllers/user.controller.ts index ce816349..6a0490cb 100644 --- a/backend/src/controllers/user.controller.ts +++ b/backend/src/controllers/user.controller.ts @@ -241,10 +241,20 @@ export async function setUserPassword(req: Request, res: Response): Promise { + const ip = req.ip || 'unknown'; + const targetUserId = (req.params?.id ?? '').toString(); + return `${ip}|staff-pw|${targetUserId}`; + }, + handler: (req, res, _next, options) => { + onLimitReached('staff-password-set', 'HIGH')(req, res); + res.status(options.statusCode).json(options.message); + }, +}); + /** * Public-Consent-Endpoints (/api/public/consent/:hash[/grant|/pdf]) sind * unauthenticated. Der hash ist 128-bit-UUID → kein Brute-Force-Risk, diff --git a/backend/src/routes/user.routes.ts b/backend/src/routes/user.routes.ts index dbb57ffd..d394366e 100644 --- a/backend/src/routes/user.routes.ts +++ b/backend/src/routes/user.routes.ts @@ -1,6 +1,7 @@ import { Router } from 'express'; import * as userController from '../controllers/user.controller.js'; import { authenticate, requirePermission } from '../middleware/auth.js'; +import { staffPasswordReAuthLimiter } from '../middleware/rateLimit.js'; const router = Router(); @@ -10,8 +11,10 @@ router.post('/', authenticate, requirePermission('users:create'), userController router.get('/:id', authenticate, requirePermission('users:read'), userController.getUser); router.put('/:id', authenticate, requirePermission('users:update'), userController.updateUser); router.delete('/:id', authenticate, requirePermission('users:delete'), userController.deleteUser); -// Passwort-Reset durch Admin – dedizierter Endpoint (Pentest Runde 12) -router.post('/:id/password', authenticate, requirePermission('users:update'), userController.setUserPassword); +// Passwort-Reset durch Admin – dedizierter Endpoint (Pentest Runde 12). +// 47.3 verlangt Re-Auth (currentPassword), 48.3 wirft einen Rate-Limit +// davor, damit ein gestohlener JWT das Admin-Passwort nicht brute-forcen kann. +router.post('/:id/password', staffPasswordReAuthLimiter, authenticate, requirePermission('users:update'), userController.setUserPassword); // Roles router.get('/roles/list', authenticate, requirePermission('users:read'), userController.getRoles);