Files
ridebus-admin/backend/src/middleware/auth.js
2026-04-28 22:51:54 +03:00

116 lines
2.9 KiB
JavaScript

const pool = require('../config/database');
const logger = require('../config/logger');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
function verifyJwtToken(token) {
try {
return jwt.verify(token, JWT_SECRET);
} catch (error) {
return null;
}
}
async function getApiKeyInfo(apiKey, touchLastUsed = false) {
if (!apiKey) {
return null;
}
const query = touchLastUsed
? `UPDATE api_keys
SET last_used_at = CURRENT_TIMESTAMP
WHERE key = $1 AND is_active = true
RETURNING id, app_name, rate_limit`
: `SELECT id, app_name, rate_limit
FROM api_keys
WHERE key = $1 AND is_active = true`;
const result = await pool.query(query, [apiKey]);
return result.rows[0] || null;
}
// Verify JWT token
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) {
return res.status(401).json({ error: 'Access token required' });
}
const user = verifyJwtToken(token);
if (!user) {
return res.status(403).json({ error: 'Invalid or expired token' });
}
req.user = user;
next();
}
// Check if user is admin
function requireAdmin(req, res, next) {
if (!req.user || req.user.role !== 'admin') {
return res.status(403).json({ error: 'Admin access required' });
}
next();
}
async function authenticateApiKey(req, res, next) {
// Check for JWT token first
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (token) {
// If JWT token is present, verify it
try {
const user = verifyJwtToken(token);
if (!user) {
throw new Error('Invalid JWT token');
}
req.user = user;
return next();
} catch (error) {
// JWT token is invalid, continue to API key check
logger.warn('Invalid JWT token in request');
}
}
// Fall back to API key authentication
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
return res.status(401).json({
error: 'Authentication required',
message: 'Please provide either Authorization header with JWT token or X-API-Key header'
});
}
try {
const apiKeyInfo = await getApiKeyInfo(apiKey, true);
if (!apiKeyInfo) {
logger.warn(`Invalid API key attempt: ${apiKey.substring(0, 8)}...`);
return res.status(403).json({
error: 'Invalid API key',
message: 'The provided API key is invalid or inactive'
});
}
req.apiKeyInfo = apiKeyInfo;
next();
} catch (error) {
logger.error('Authentication error:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
module.exports = {
authenticateToken,
requireAdmin,
authenticateApiKey,
verifyJwtToken,
getApiKeyInfo
};