158 lines
4.2 KiB
JavaScript
158 lines
4.2 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
|
const { User } = require('../models');
|
|
|
|
/**
|
|
* Authentication middleware
|
|
* Verifies JWT token and attaches user to request
|
|
*/
|
|
const authenticateToken = async (req, res, next) => {
|
|
try {
|
|
const authHeader = req.headers['authorization'];
|
|
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|
|
|
if (!token) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Access token required'
|
|
});
|
|
}
|
|
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
const user = await User.findByPk(decoded.userId, {
|
|
attributes: { exclude: ['password'] }
|
|
});
|
|
|
|
if (!user || !user.isActive) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Invalid or inactive user'
|
|
});
|
|
}
|
|
|
|
req.user = user;
|
|
next();
|
|
} catch (error) {
|
|
console.error('Token verification error:', error);
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: 'Invalid token'
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Session-based authentication middleware
|
|
* For web pages using sessions
|
|
*/
|
|
const authenticateSession = async (req, res, next) => {
|
|
try {
|
|
if (!req.session.userId) {
|
|
req.flash('error', '로그인이 필요합니다.');
|
|
return res.redirect('/auth/login');
|
|
}
|
|
|
|
const user = await User.findByPk(req.session.userId, {
|
|
attributes: { exclude: ['password'] }
|
|
});
|
|
|
|
if (!user || !user.isActive) {
|
|
req.session.destroy();
|
|
req.flash('error', '유효하지 않은 사용자입니다.');
|
|
return res.redirect('/auth/login');
|
|
}
|
|
|
|
req.user = user;
|
|
res.locals.user = user;
|
|
next();
|
|
} catch (error) {
|
|
console.error('Session authentication error:', error);
|
|
req.session.destroy();
|
|
req.flash('error', '인증 오류가 발생했습니다.');
|
|
return res.redirect('/auth/login');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Admin role middleware
|
|
* Requires user to be authenticated and have admin role
|
|
*/
|
|
const requireAdmin = (req, res, next) => {
|
|
if (!req.user) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Authentication required'
|
|
});
|
|
}
|
|
|
|
if (req.user.role !== 'admin') {
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: 'Admin access required'
|
|
});
|
|
}
|
|
|
|
next();
|
|
};
|
|
|
|
/**
|
|
* Admin session middleware for web pages
|
|
*/
|
|
const requireAdminSession = (req, res, next) => {
|
|
if (!req.user) {
|
|
req.flash('error', '로그인이 필요합니다.');
|
|
return res.redirect('/auth/login');
|
|
}
|
|
|
|
if (req.user.role !== 'admin') {
|
|
req.flash('error', '관리자 권한이 필요합니다.');
|
|
return res.redirect('/');
|
|
}
|
|
|
|
next();
|
|
};
|
|
|
|
/**
|
|
* Optional authentication middleware
|
|
* Attaches user if token exists but doesn't require it
|
|
*/
|
|
const optionalAuth = async (req, res, next) => {
|
|
try {
|
|
// Check session first
|
|
if (req.session.userId) {
|
|
const user = await User.findById(req.session.userId).select('-password');
|
|
if (user && user.isActive) {
|
|
req.user = user;
|
|
res.locals.user = user;
|
|
}
|
|
}
|
|
|
|
// Check JWT token if no session
|
|
if (!req.user) {
|
|
const authHeader = req.headers['authorization'];
|
|
const token = authHeader && authHeader.split(' ')[1];
|
|
|
|
if (token) {
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
const user = await User.findById(decoded.userId).select('-password');
|
|
|
|
if (user && user.isActive) {
|
|
req.user = user;
|
|
res.locals.user = user;
|
|
}
|
|
}
|
|
}
|
|
|
|
next();
|
|
} catch (error) {
|
|
// Continue without authentication if token is invalid
|
|
next();
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
authenticateToken,
|
|
authenticateSession,
|
|
requireAdmin,
|
|
requireAdminSession,
|
|
optionalAuth
|
|
}; |