summary refs log tree commit diff
path: root/src/api/middlewares
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2025-06-02 10:12:34 +0200
committerRory& <root@rory.gay>2025-06-02 10:12:34 +0200
commitc4fd9c93a63bce7c322aec1fc304b4dc5ac5a9cd (patch)
tree4cea31f08115376fefc2cdfed5befbc5610150f8 /src/api/middlewares
parentAdd shortcut for generating http file, part of API documentation (diff)
downloadnodejs-final-assignment-c4fd9c93a63bce7c322aec1fc304b4dc5ac5a9cd.tar.xz
Split authentication and authorization
Diffstat (limited to 'src/api/middlewares')
-rw-r--r--src/api/middlewares/authMiddleware.js79
1 files changed, 67 insertions, 12 deletions
diff --git a/src/api/middlewares/authMiddleware.js b/src/api/middlewares/authMiddleware.js

index 3a71e45..13d0d27 100644 --- a/src/api/middlewares/authMiddleware.js +++ b/src/api/middlewares/authMiddleware.js
@@ -1,17 +1,68 @@ import { validateJwtToken } from '#util/jwtUtils.js'; import { DbUser, UserType } from '#db/schemas/index.js'; +import { SafeNSoundError } from '#util/error.js'; + +const shouldLogAuth = !!process.env['LOG_AUTH']; +function logAuth(...params) { + if (shouldLogAuth) { + console.log('[AUTH]', ...params); + } +} + +function getTokenFromHeader(authHeader) { + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return null; + } + const parts = authHeader.split(' '); + return { + scheme: parts[0], + token: parts[1] + }; +} + +export async function useAuthentication(req, res, next) { + if (!req.headers.authorization) { + logAuth('Request to', req.path, 'without auth'); + next(); + return; + } + + const auth = (req.auth = await validateJwtToken( + getTokenFromHeader(req.headers.authorization).token + )); + logAuth('Token data:', auth); + + // req.user = auth; + next(); +} + +export async function requireAuth(req, res, next) { + if (!req.auth) { + logAuth('Unauthorized request to', req.path); + res.status(401).send( + new SafeNSoundError({ + errCode: 'UNAUTHORIZED', + message: 'Unauthorized' + }) + ); + return; + } + + next(); +} /** * @param options {AuthValidationOptions} * @returns {(function(*, *, *): void)|*} */ -export function validateAuth(options) { +export function requireRole(options) { return async function (req, res, next) { - const auth = (req.auth = validateJwtToken(req.headers.authorization)); - if (!auth) { - res.status(401).send('Unauthorized'); - return; - } + res.status(401).send( + new SafeNSoundError({ + errCode: 'UNAUTHORIZED', + message: 'Unauthorized' + }) + ); const user = (req.user = await DbUser.findById(auth.id).exec()); @@ -22,7 +73,12 @@ export function validateAuth(options) { } if (options.roles && !options.roles.includes(user.type)) { - res.status(401).send('Unauthorized'); + res.status(401).send( + new SafeNSoundError({ + errCode: 'UNAUTHORIZED', + message: 'Unauthorized' + }) + ); return; } @@ -30,11 +86,10 @@ export function validateAuth(options) { }; } -export const requireAuth = validateAuth({}); -export const requireAdmin = validateAuth({ roles: [UserType.ADMIN] }); -export const requireMonitor = validateAuth({ roles: [UserType.MONITOR] }); -export const requireUser = validateAuth({ roles: [UserType.USER] }); -export const requireUserOrMonitor = validateAuth({ +export const requireAdmin = requireRole({ roles: [UserType.ADMIN] }); +export const requireMonitor = requireRole({ roles: [UserType.MONITOR] }); +export const requireUser = requireRole({ roles: [UserType.USER] }); +export const requireUserOrMonitor = requireRole({ roles: [UserType.USER, UserType.MONITOR] });