From c43425f5894607f42f8c1e45ec0d19c54d29b6f6 Mon Sep 17 00:00:00 2001 From: Tereshchenko Aleksandr Date: Wed, 20 Mar 2024 09:14:51 +0200 Subject: [PATCH] backend: Allow mocking the user based on custom header --- backend/src/controllers/LoginController.js | 4 +++- backend/src/middleware/auth.js | 24 +++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/LoginController.js b/backend/src/controllers/LoginController.js index f049b4ac..0b1edf40 100644 --- a/backend/src/controllers/LoginController.js +++ b/backend/src/controllers/LoginController.js @@ -40,7 +40,9 @@ export const login = async (req, res) => { try { const { shibbolethId, studentNumber, firstname, lastname, email } = parseShibbolethInformationFromHeaders(req.headers) - await register(shibbolethId, studentNumber, firstname, lastname, email) + if (!req.isMockUser) { + await register(shibbolethId, studentNumber, firstname, lastname, email) + } const token = await generateToken(shibbolethId) res.status(200).json({ token }) } catch (err) { diff --git a/backend/src/middleware/auth.js b/backend/src/middleware/auth.js index 07733ea6..0345430f 100644 --- a/backend/src/middleware/auth.js +++ b/backend/src/middleware/auth.js @@ -6,6 +6,9 @@ const config = require('../util/config') const isShibboUser = (userId, uidHeader) => userId === uidHeader +const hasAtLeastOneRole = (userRoles, allowedRoleNames) => + userRoles.filter(item => allowedRoleNames.includes(item.role.name)).length > 0 + /** * Authentication middleware that is called before any requests. * @@ -14,11 +17,26 @@ export const checkAuth = async (req, res, next) => { const token = req.headers['x-access-token'] const { uid } = req.headers if (token) { - jwt.verify(token, config.TOKEN_SECRET, (err, decoded) => { + jwt.verify(token, config.TOKEN_SECRET, async (err, decoded) => { if (err) { res.status(403).json(err) } else if (isShibboUser(decoded.userId, uid)) { req.decodedToken = decoded + + if (req.headers['x-mock-user-id']) { + // only allow admins to mock other users + const user = await personService.getLoggedPerson(req) + const userRoles = await roleService.getUsersRoles(user) + const isAdmin = hasAtLeastOneRole(userRoles, ['admin']) + + if (isAdmin || process.env.NODE === 'development') { + req.headers.uid = req.headers['x-mock-user-id'] + req.isMockUser = true + // if x-mock-user-id is set, we need to mock userId also in the token + req.decodedToken.userId = req.headers['x-mock-user-id'] + } + } + next() } else { res.status(403).json({ error: 'User shibboleth id and token id did not match' }) @@ -55,12 +73,12 @@ export const checkCanSubmitThesis = async (req, res, next) => { await checkRoles(staffRoles, req, res, next) } -const checkRoles = async (allowedRoles, req, res, next) => { +const checkRoles = async (allowedRoleNames, req, res, next) => { console.log("Checking roles") const user = await personService.getLoggedPerson(req) const userRoles = await roleService.getUsersRoles(user) try { - if (userRoles.filter(item => allowedRoles.includes(item.role.name)).length > 0) { + if (hasAtLeastOneRole(userRoles, allowedRoleNames)) { console.log("Roles were ok") next() } else {