fixed login payload and token structure for auth

This commit is contained in:
Pau 2025-04-02 19:07:16 +02:00
parent a3ecace384
commit 4ebc73031e
2 changed files with 56 additions and 37 deletions

View File

@ -1,9 +1,10 @@
import { sendResponseAccessDenied } from '../utils/responses.js'; import { sendResponseAccessDenied } from '../utils/responses.js';
import { checkPermission, getDataFromToken, generateAccessToken} from '../services/authService.js'; import { checkPermission, getDataFromToken, generateAccessToken} from '../services/authService.js';
import { getRolesHasPermissionsModel } from '../models/authorization/roles_has_permissionsModel.js'; import { getRolesHasPermissionsModel } from '../models/authorization/roles_has_permissionsModel.js';
import mysql from '../adapters/mysql.js';
import { error404, errorHandler } from '../utils/errors.js'; import { error404, errorHandler } from '../utils/errors.js';
import { noResults } from '../validators/result-validators.js'; import { noResults } from '../validators/result-validators.js';
import mysql from '../adapters/mysql.js';
import { sendResponseNotFound } from '../utils/responses.js';
const obtainToken = (req, res) => { const obtainToken = (req, res) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -11,18 +12,15 @@ const obtainToken = (req, res) => {
if (token) { if (token) {
resolve(token); resolve(token);
} else { } else {
sendResponseAccessDenied(res, { message: 'No authorization provided. Access token required' }); return sendResponseAccessDenied(res, { message: 'No authorization provided. Access token required' })
reject(new Error('No authorization provided'));
} }
}); });
}; };
const setToken = (result, req, res, next, config) => { const setToken = (result, req, res, next, config) => {
const { user, role } = result._data const { uuid, role } = result._data
const token = generateAccessToken({ const payload = {role, user: uuid}
payload: { user, role }, const token = generateAccessToken(payload)
config
})
next({ user: { ...result, token } }) next({ user: { ...result, token } })
} }
@ -34,8 +32,7 @@ const authenticateToken = (req, res, next) => {
next(); next();
}) })
.catch((error) => { .catch((error) => {
console.error('Error in authentication middleware:', error); return sendResponseAccessDenied(res, error);
sendResponseAccessDenied(res, { message: 'Access denied. Invalid token.' });
}); });
}; };
@ -44,31 +41,27 @@ const authorizePermission = (endpoint) => {
obtainToken(req, res) obtainToken(req, res)
.then((token) => getDataFromToken(token)) //extract user data from the token .then((token) => getDataFromToken(token)) //extract user data from the token
.then((decoded) => { .then((decoded) => {
const roleName = decoded.payload.role const roleName = decoded.role
_getRolePermissionsByName(roleName, config) _getRolePermissionsByName(roleName, config)
.then((rolePermissions) => { .then((rolePermissions) => {
const action = req.method const action = req.method
//check if the user has the necessary permissions //check if the user has the necessary permissions
return checkPermission(action, endpoint, rolePermissions) return checkPermission(action, endpoint, rolePermissions, config)
.then(({ hasPermission }) => { .then(({ hasPermission }) => {
if (!hasPermission) { if (!hasPermission) {
sendResponseAccessDenied(res, { return sendResponseAccessDenied(res, {
message: `You don't have permission to ${action} on ${endpoint}` message: `Access denied. User does not have permission`
}); });
throw new Error(`Permission denied for ${action} on ${endpoint}`);
} }
req.auth.user = decoded.user
//attach user and role to the request object req.auth.role = roleName;
//req.auth.user = user;
//req.auth.role = role;
next(); next();
}) })
}) })
}) })
.catch((error) => { .catch((error) => {
console.error('Error in authorization middleware:', error); return sendResponseAccessDenied(res, error);
sendResponseAccessDenied(res, { message: 'Authorization error', error: error.message });
}); });
}; };
}; };
@ -82,15 +75,13 @@ const _getRolePermissionsByName = (roleName, config) => {
const error = errorHandler(err, config.environment) const error = errorHandler(err, config.environment)
return sendResponseNotFound(res, error) return sendResponseNotFound(res, error)
} }
console.log(response)
return response.map(({ permission_action, permission_endpoint }) => ({ return response.map(({ permission_action, permission_endpoint }) => ({
permission_action, permission_action,
permission_endpoint permission_endpoint
})) }))
}) })
.catch((err) => { .catch((err) => {
const error = errorHandler(err, config.environment) errorHandler(err, config.environment)
res.status(error.code).json(error)
}) })
.finally(() => { .finally(() => {
mysql.end(conn) mysql.end(conn)

View File

@ -1,5 +1,10 @@
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
import dotenv from 'dotenv'; 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(); dotenv.config();
@ -25,7 +30,6 @@ const getDataFromToken = (token) => {
const generateAccessToken = (payload) => { const generateAccessToken = (payload) => {
const JWT_SECRET = process.env.JWT_SECRET; const JWT_SECRET = process.env.JWT_SECRET;
const JWT_TIME = parseInt(process.env.JWT_TIME, 10); const JWT_TIME = parseInt(process.env.JWT_TIME, 10);
return jwt.sign(payload, JWT_SECRET, JWT_TIME ? { expiresIn: JWT_TIME } : {}); 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. * @param {Array} userPermissions - The list of permissions assigned to the user.
* @returns {Promise<Object>} - Resolves with an object containing permission details. * @returns {Promise<Object>} - Resolves with an object containing permission details.
*/ */
const checkPermission = (action, endpoint, userPermissions) => { const checkPermission = (action, endpoint, userPermissions, config) => {
return new Promise((resolve, reject) => { return _getEndpointByRoute(endpoint, config)
.then((endpointInfo) => {
const hasPermission = userPermissions.some( const hasPermission = userPermissions.some(
(permission) => (permission) =>
permission.permission_action === action && permission.permission_endpoint === endpoint permission.permission_action === action &&
permission.permission_endpoint === endpointInfo.id // Comparar con el ID del endpoint
); );
if (hasPermission) { if (hasPermission) {
resolve({ hasPermission: true }); return { hasPermission: true };
} else {
reject(new Error(`Permission denied for ${action} on ${endpoint}`));
} }
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 { export {
getDataFromToken, getDataFromToken,
generateAccessToken, generateAccessToken,