mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 09:51:37 +00:00
Compare commits
2 commits
f0d5f46199
...
030e43f382
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
030e43f382 | ||
|
|
f081a7fdc1 |
1 changed files with 27 additions and 6 deletions
|
|
@ -1,10 +1,14 @@
|
||||||
const { rateLimit, RateLimitRequestHandler } = require('express-rate-limit')
|
const { rateLimit, RateLimitRequestHandler } = require('express-rate-limit')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
|
const requestIp = require('../libs/requestIp')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating authentication rate limiters
|
* Factory for creating authentication rate limiters
|
||||||
*/
|
*/
|
||||||
class RateLimiterFactory {
|
class RateLimiterFactory {
|
||||||
|
static DEFAULT_WINDOW_MS = 10 * 60 * 1000 // 10 minutes
|
||||||
|
static DEFAULT_MAX = 40 // 40 attempts
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.authRateLimiter = null
|
this.authRateLimiter = null
|
||||||
}
|
}
|
||||||
|
|
@ -18,17 +22,30 @@ class RateLimiterFactory {
|
||||||
return this.authRateLimiter
|
return this.authRateLimiter
|
||||||
}
|
}
|
||||||
|
|
||||||
let windowMs = 10 * 60 * 1000 // 10 minutes default
|
// Disable by setting max to 0
|
||||||
|
if (process.env.RATE_LIMIT_AUTH_MAX === '0') {
|
||||||
|
this.authRateLimiter = (req, res, next) => next()
|
||||||
|
Logger.info(`[RateLimiterFactory] Authentication rate limiting disabled by ENV variable`)
|
||||||
|
return this.authRateLimiter
|
||||||
|
}
|
||||||
|
|
||||||
|
let windowMs = RateLimiterFactory.DEFAULT_WINDOW_MS
|
||||||
if (parseInt(process.env.RATE_LIMIT_AUTH_WINDOW) > 0) {
|
if (parseInt(process.env.RATE_LIMIT_AUTH_WINDOW) > 0) {
|
||||||
windowMs = parseInt(process.env.RATE_LIMIT_AUTH_WINDOW)
|
windowMs = parseInt(process.env.RATE_LIMIT_AUTH_WINDOW)
|
||||||
|
if (windowMs !== RateLimiterFactory.DEFAULT_WINDOW_MS) {
|
||||||
|
Logger.info(`[RateLimiterFactory] Authentication rate limiting window set to ${windowMs}ms by ENV variable`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let max = 40 // 40 attempts default
|
let max = RateLimiterFactory.DEFAULT_MAX
|
||||||
if (parseInt(process.env.RATE_LIMIT_AUTH_MAX) > 0) {
|
if (parseInt(process.env.RATE_LIMIT_AUTH_MAX) > 0) {
|
||||||
max = parseInt(process.env.RATE_LIMIT_AUTH_MAX)
|
max = parseInt(process.env.RATE_LIMIT_AUTH_MAX)
|
||||||
|
if (max !== RateLimiterFactory.DEFAULT_MAX) {
|
||||||
|
Logger.info(`[RateLimiterFactory] Authentication rate limiting max set to ${max} by ENV variable`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = 'Too many requests, please try again later.'
|
let message = 'Too many authentication requests'
|
||||||
if (process.env.RATE_LIMIT_AUTH_MESSAGE) {
|
if (process.env.RATE_LIMIT_AUTH_MESSAGE) {
|
||||||
message = process.env.RATE_LIMIT_AUTH_MESSAGE
|
message = process.env.RATE_LIMIT_AUTH_MESSAGE
|
||||||
}
|
}
|
||||||
|
|
@ -36,18 +53,22 @@ class RateLimiterFactory {
|
||||||
this.authRateLimiter = rateLimit({
|
this.authRateLimiter = rateLimit({
|
||||||
windowMs,
|
windowMs,
|
||||||
max,
|
max,
|
||||||
message,
|
|
||||||
standardHeaders: true,
|
standardHeaders: true,
|
||||||
legacyHeaders: false,
|
legacyHeaders: false,
|
||||||
|
keyGenerator: (req) => {
|
||||||
|
// Override keyGenerator to handle proxy IPs
|
||||||
|
return requestIp.getClientIp(req) || req.ip
|
||||||
|
},
|
||||||
handler: (req, res) => {
|
handler: (req, res) => {
|
||||||
const userAgent = req.get('User-Agent') || 'Unknown'
|
const userAgent = req.get('User-Agent') || 'Unknown'
|
||||||
const endpoint = req.path
|
const endpoint = req.path
|
||||||
const method = req.method
|
const method = req.method
|
||||||
|
const ip = requestIp.getClientIp(req) || req.ip
|
||||||
|
|
||||||
Logger.warn(`[RateLimiter] Rate limit exceeded - IP: ${req.ip}, Endpoint: ${method} ${endpoint}, User-Agent: ${userAgent}`)
|
Logger.warn(`[RateLimiter] Rate limit exceeded - IP: ${ip}, Endpoint: ${method} ${endpoint}, User-Agent: ${userAgent}`)
|
||||||
|
|
||||||
res.status(429).json({
|
res.status(429).json({
|
||||||
error: 'Too many authentication attempts, please try again later.'
|
error: message
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue