Yaltopia-Ticket-Email/src/lib/ipAuth.ts

70 lines
2.0 KiB
TypeScript

import type { Request, Response, NextFunction } from 'express'
import { config } from './config'
import { logger } from './logger'
/**
* Simple IP-based authentication middleware
* Restricts access to only allowed IP addresses
*/
export const ipWhitelistAuth = (req: Request, res: Response, next: NextFunction) => {
// Skip if no IP restrictions configured
if (config.security.allowedIPs.length === 0) {
logger.warn('No IP whitelist configured - allowing all IPs')
return next()
}
const clientIP = req.ip || req.socket.remoteAddress || 'unknown'
logger.info('IP authentication check', {
clientIP: logger['maskIp'](clientIP),
allowedIPs: config.security.allowedIPs.length
})
// Check if IP is in whitelist
const isAllowed = config.security.allowedIPs.some(allowedIP => {
// Exact match
if (clientIP === allowedIP) return true
// Handle localhost variations
if (allowedIP === '127.0.0.1' && (clientIP === '::1' || clientIP === '::ffff:127.0.0.1')) return true
if (allowedIP === '::1' && (clientIP === '127.0.0.1' || clientIP === '::ffff:127.0.0.1')) return true
// Handle IPv6 mapped IPv4
if (clientIP.startsWith('::ffff:') && allowedIP === clientIP.substring(7)) return true
return false
})
if (!isAllowed) {
logger.warn('IP access denied', {
clientIP: logger['maskIp'](clientIP),
allowedIPs: config.security.allowedIPs.map(ip => logger['maskIp'](ip))
})
return res.status(403).json({
success: false,
error: 'Access denied: IP address not authorized',
code: 'IP_NOT_ALLOWED'
})
}
logger.info('IP authentication successful', {
clientIP: logger['maskIp'](clientIP)
})
next()
}
/**
* Get client IP address with proper handling of proxies
*/
export const getClientIP = (req: Request): string => {
return (
req.headers['x-forwarded-for'] as string ||
req.headers['x-real-ip'] as string ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.ip ||
'unknown'
).split(',')[0].trim()
}