From 4ebc73031e6acad67d75e501ed12ec589b49a8d0 Mon Sep 17 00:00:00 2001 From: Pau Date: Wed, 2 Apr 2025 19:07:16 +0200 Subject: [PATCH] fixed login payload and token structure for auth --- src/middlewares/auth.js | 39 +++++++++++---------------- src/services/authService.js | 54 ++++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/src/middlewares/auth.js b/src/middlewares/auth.js index 14cfc47..d1dba4e 100644 --- a/src/middlewares/auth.js +++ b/src/middlewares/auth.js @@ -1,9 +1,10 @@ import { sendResponseAccessDenied } from '../utils/responses.js'; import { checkPermission, getDataFromToken, generateAccessToken} from '../services/authService.js'; import { getRolesHasPermissionsModel } from '../models/authorization/roles_has_permissionsModel.js'; -import mysql from '../adapters/mysql.js'; import { error404, errorHandler } from '../utils/errors.js'; import { noResults } from '../validators/result-validators.js'; +import mysql from '../adapters/mysql.js'; +import { sendResponseNotFound } from '../utils/responses.js'; const obtainToken = (req, res) => { return new Promise((resolve, reject) => { @@ -11,18 +12,15 @@ const obtainToken = (req, res) => { if (token) { resolve(token); } else { - sendResponseAccessDenied(res, { message: 'No authorization provided. Access token required' }); - reject(new Error('No authorization provided')); + return sendResponseAccessDenied(res, { message: 'No authorization provided. Access token required' }) } }); }; const setToken = (result, req, res, next, config) => { - const { user, role } = result._data - const token = generateAccessToken({ - payload: { user, role }, - config - }) + const { uuid, role } = result._data + const payload = {role, user: uuid} + const token = generateAccessToken(payload) next({ user: { ...result, token } }) } @@ -34,8 +32,7 @@ const authenticateToken = (req, res, next) => { next(); }) .catch((error) => { - console.error('Error in authentication middleware:', error); - sendResponseAccessDenied(res, { message: 'Access denied. Invalid token.' }); + return sendResponseAccessDenied(res, error); }); }; @@ -44,31 +41,27 @@ const authorizePermission = (endpoint) => { obtainToken(req, res) .then((token) => getDataFromToken(token)) //extract user data from the token .then((decoded) => { - const roleName = decoded.payload.role + const roleName = decoded.role _getRolePermissionsByName(roleName, config) .then((rolePermissions) => { const action = req.method //check if the user has the necessary permissions - return checkPermission(action, endpoint, rolePermissions) + return checkPermission(action, endpoint, rolePermissions, config) .then(({ hasPermission }) => { if (!hasPermission) { - sendResponseAccessDenied(res, { - message: `You don't have permission to ${action} on ${endpoint}` + return sendResponseAccessDenied(res, { + message: `Access denied. User does not have permission` }); - throw new Error(`Permission denied for ${action} on ${endpoint}`); } - - //attach user and role to the request object - //req.auth.user = user; - //req.auth.role = role; + req.auth.user = decoded.user + req.auth.role = roleName; next(); }) }) }) .catch((error) => { - console.error('Error in authorization middleware:', error); - sendResponseAccessDenied(res, { message: 'Authorization error', error: error.message }); + return sendResponseAccessDenied(res, error); }); }; }; @@ -82,15 +75,13 @@ const _getRolePermissionsByName = (roleName, config) => { const error = errorHandler(err, config.environment) return sendResponseNotFound(res, error) } - console.log(response) return response.map(({ permission_action, permission_endpoint }) => ({ permission_action, permission_endpoint })) }) .catch((err) => { - const error = errorHandler(err, config.environment) - res.status(error.code).json(error) + errorHandler(err, config.environment) }) .finally(() => { mysql.end(conn) diff --git a/src/services/authService.js b/src/services/authService.js index 5497b5b..aeed91b 100644 --- a/src/services/authService.js +++ b/src/services/authService.js @@ -1,5 +1,10 @@ import jwt from 'jsonwebtoken'; import dotenv from 'dotenv'; +import mysql from '../adapters/mysql.js'; +import { errorHandler } from '../utils/errors.js'; +import { getEndpointsModel } from '../models/authorization/endpointsModel.js'; +import { noResults } from '../validators/result-validators.js'; +import { error404, error403 } from '../utils/errors.js'; dotenv.config(); @@ -25,7 +30,6 @@ const getDataFromToken = (token) => { const generateAccessToken = (payload) => { const JWT_SECRET = process.env.JWT_SECRET; const JWT_TIME = parseInt(process.env.JWT_TIME, 10); - return jwt.sign(payload, JWT_SECRET, JWT_TIME ? { expiresIn: JWT_TIME } : {}); }; @@ -37,21 +41,45 @@ const generateAccessToken = (payload) => { * @param {Array} userPermissions - The list of permissions assigned to the user. * @returns {Promise} - Resolves with an object containing permission details. */ -const checkPermission = (action, endpoint, userPermissions) => { - return new Promise((resolve, reject) => { - const hasPermission = userPermissions.some( - (permission) => - permission.permission_action === action && permission.permission_endpoint === endpoint - ); +const checkPermission = (action, endpoint, userPermissions, config) => { + return _getEndpointByRoute(endpoint, config) + .then((endpointInfo) => { + const hasPermission = userPermissions.some( + (permission) => + permission.permission_action === action && + permission.permission_endpoint === endpointInfo.id // Comparar con el ID del endpoint + ); - if (hasPermission) { - resolve({ hasPermission: true }); - } else { - reject(new Error(`Permission denied for ${action} on ${endpoint}`)); - } - }); + if (hasPermission) { + return { hasPermission: true }; + } + return { hasPermission: false }; + }) + .catch((error) => { + const err = error403() + return errorHandler(err, config.environment,`Authorization failed: ${error.message}`); + }); }; +const _getEndpointByRoute = (route, config) => { + const conn = mysql.start(config) + return getEndpointsModel({ route, conn }) + .then((endpointInformation) => { + if (noResults(endpointInformation)) { + const err = error404() + errorHandler(err, config.environment) + } + + return endpointInformation[0] + }) + .catch((err) => { + errorHandler(err, config.environment) + }) + .finally(() => { + mysql.end(conn) + }) +} + export { getDataFromToken, generateAccessToken,