105 lines
2.7 KiB
JavaScript

const jwt = require('jsonwebtoken');
const {getUserById} = require('./db');
const JWT_SECRET = 'THISISTOTALLYSECRETDONTLOOK';
const JWT_EXPIRATION = '24h';
/**
* Generate a JWT token for a user
* @param {Object}- User object from database
* @returns {string} - signed JWT token
*/
function generateToken(user) {
const payload = {
id: user.id,
email: user.email,
username: user.username,
display_name: user.display_name,
auth_provider: user.auth_provider,
role: user.role
};
const token = jwt.sign(payload, JWT_SECRET, {expiresIn: JWT_EXPIRATION});
return token;
}
/**
* Verify and decode a JWT token
* @param {string} token - JWT token to verify
* @returns {Object} - Decoded token payload
* @throws {Error} - If token is invalid or expired
*/
function verifyToken(token) {
try {
const decoded = jwt.verify(token, JWT_SECRET);
return decoded;
} catch (error) {
throw new Error('Invalid or expired token');
}
}
/**
* Express middleware to authenticate requests using JWT
* Extracts token from Authorization header, verfies it, and attaches user to req.user
*/
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({error: 'Access token required'});
}
try {
const decoded = verifyToken(token);
const user = getUserById(decoded.id);
if (!user) {
return res.status(403).json({error: 'User not found'});
}
req.user = {
id: user.id,
email: user.email,
username: user.username,
display_name: user.display_name,
auth_provider: user.auth_provider,
role: user.role
};
next();
} catch (error) {
return res.status(403).json({error: 'Invalid or expired token', details: error.message});
}
}
/**
* Middleware to check if user has required role
* @param {Array} allowedRoles - Array of roles that can acces the route
*/
function authorizeRoles(...allowedRoles) {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({error: 'Authentication requried'});
}
if (!allowedRoles.includes(req.user.role)) {
return res.status(403).json({
error: 'Insufficient permissions',
required: allowedRoles,
current: req.user.role
});
}
next();
};
}
module.exports = {
generateToken,
verifyToken,
authenticateToken,
authorizeRoles,
JWT_SECRET
};