const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const passport = require('passport'); const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt'); const { Strategy: LocalStrategy } = require('passport-local'); /** * Authentication and Authorization Module * Handles user authentication, session management, and role-based access control * Using Passport.js with JWT tokens */ // JWT Secret - In production, use environment variable const JWT_SECRET = process.env.JWT_SECRET || 'nodecast-tv-secret-key-change-in-production'; const JWT_EXPIRY = '24h'; /** * Hash password using bcrypt */ async function hashPassword(password) { const salt = await bcrypt.genSalt(10); return bcrypt.hash(password, salt); } /** * Verify password against hash */ async function verifyPassword(password, hash) { return bcrypt.compare(password, hash); } /** * Generate JWT token */ function generateToken(user) { return jwt.sign( { id: user.id, username: user.username, role: user.role }, JWT_SECRET, { expiresIn: JWT_EXPIRY } ); } /** * Verify JWT token */ function verifyToken(token) { try { return jwt.verify(token, JWT_SECRET); } catch (err) { return null; } } /** * Configure Passport Local Strategy for username/password authentication */ function configureLocalStrategy(getUserByUsername, verifyUserPassword) { passport.use(new LocalStrategy( async (username, password, done) => { try { const user = await getUserByUsername(username); if (!user) { return done(null, false, { message: 'Invalid credentials' }); } const isValid = await verifyUserPassword(password, user.passwordHash); if (!isValid) { return done(null, false, { message: 'Invalid credentials' }); } return done(null, user); } catch (err) { return done(err); } } )); } /** * Configure Passport JWT Strategy for token-based authentication */ function configureJwtStrategy(getUserById) { const options = { jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: JWT_SECRET }; passport.use(new JwtStrategy(options, async (payload, done) => { try { const user = await getUserById(payload.id); if (!user) { return done(null, false); } return done(null, { id: user.id, username: user.username, role: user.role }); } catch (err) { return done(err, false); } })); } /** * Middleware: Require authentication using Passport JWT */ const requireAuth = passport.authenticate('jwt', { session: false }); /** * Middleware: Require admin role */ function requireAdmin(req, res, next) { if (!req.user || req.user.role !== 'admin') { return res.status(403).json({ error: 'Forbidden - Admin access required' }); } next(); } /** * Middleware: Check for specific role */ function requireRole(role) { return (req, res, next) => { if (!req.user || req.user.role !== role) { return res.status(403).json({ error: `Forbidden - ${role} access required` }); } next(); }; } module.exports = { passport, hashPassword, verifyPassword, generateToken, verifyToken, configureLocalStrategy, configureJwtStrategy, requireAuth, requireAdmin, requireRole };