151 lines
3.5 KiB
JavaScript
151 lines
3.5 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
|
const { validateApiKey } = require('../database/auth-queries');
|
|
|
|
// JWT 시크릿 키 (실제 환경에서는 환경변수로 관리)
|
|
const JWT_SECRET = 'your-super-secret-jwt-key-change-this-in-production';
|
|
|
|
// JWT 토큰 생성
|
|
function generateToken(user) {
|
|
return jwt.sign(
|
|
{
|
|
id: user.id,
|
|
username: user.username,
|
|
email: user.email,
|
|
role: user.role
|
|
},
|
|
JWT_SECRET,
|
|
{ expiresIn: '24h' }
|
|
);
|
|
}
|
|
|
|
// JWT 토큰 검증 미들웨어
|
|
function verifyToken(req, res, next) {
|
|
const token = req.headers.authorization?.replace('Bearer ', '');
|
|
|
|
if (!token) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: '인증 토큰이 필요합니다'
|
|
});
|
|
}
|
|
|
|
try {
|
|
const decoded = jwt.verify(token, JWT_SECRET);
|
|
req.user = decoded;
|
|
next();
|
|
} catch (error) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: '유효하지 않은 토큰입니다'
|
|
});
|
|
}
|
|
}
|
|
|
|
// API 키 검증 미들웨어
|
|
async function verifyApiKey(req, res, next) {
|
|
const apiKey = req.headers['x-api-key'] || req.query.api_key;
|
|
|
|
if (!apiKey) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'API 키가 필요합니다. X-API-Key 헤더 또는 api_key 쿼리 파라미터를 사용하세요.'
|
|
});
|
|
}
|
|
|
|
try {
|
|
const keyData = await validateApiKey(apiKey);
|
|
|
|
if (!keyData) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: '유효하지 않은 API 키입니다'
|
|
});
|
|
}
|
|
|
|
req.apiKey = keyData;
|
|
req.user = keyData.user;
|
|
next();
|
|
} catch (error) {
|
|
console.error('API 키 검증 오류:', error);
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: 'API 키 검증 중 오류가 발생했습니다'
|
|
});
|
|
}
|
|
}
|
|
|
|
// 관리자 권한 확인 미들웨어
|
|
function requireAdmin(req, res, next) {
|
|
if (!req.user || req.user.role !== 'admin') {
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: '관리자 권한이 필요합니다'
|
|
});
|
|
}
|
|
next();
|
|
}
|
|
|
|
// 권한 확인 미들웨어 (API 키 기반)
|
|
function requirePermission(permission) {
|
|
return (req, res, next) => {
|
|
if (!req.apiKey) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'API 키 인증이 필요합니다'
|
|
});
|
|
}
|
|
|
|
// 관리자는 모든 권한 보유
|
|
if (req.user.role === 'admin') {
|
|
return next();
|
|
}
|
|
|
|
// 권한 확인
|
|
if (!req.apiKey.permissions.includes(permission)) {
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: `${permission} 권한이 필요합니다`
|
|
});
|
|
}
|
|
|
|
next();
|
|
};
|
|
}
|
|
|
|
// 선택적 인증 미들웨어 (API 키 또는 JWT)
|
|
async function optionalAuth(req, res, next) {
|
|
const apiKey = req.headers['x-api-key'] || req.query.api_key;
|
|
const token = req.headers.authorization?.replace('Bearer ', '');
|
|
|
|
if (apiKey) {
|
|
try {
|
|
const keyData = await validateApiKey(apiKey);
|
|
if (keyData) {
|
|
req.apiKey = keyData;
|
|
req.user = keyData.user;
|
|
}
|
|
} catch (error) {
|
|
console.error('API 키 검증 오류:', error);
|
|
}
|
|
} else if (token) {
|
|
try {
|
|
const decoded = jwt.verify(token, JWT_SECRET);
|
|
req.user = decoded;
|
|
} catch (error) {
|
|
// 토큰이 유효하지 않아도 계속 진행
|
|
}
|
|
}
|
|
|
|
next();
|
|
}
|
|
|
|
module.exports = {
|
|
generateToken,
|
|
verifyToken,
|
|
verifyApiKey,
|
|
requireAdmin,
|
|
requirePermission,
|
|
optionalAuth,
|
|
JWT_SECRET
|
|
};
|