From 42ee56ecd4c80f4776eb89465b71a42d7ef6be37 Mon Sep 17 00:00:00 2001 From: Miguel Serrano Date: Wed, 5 Mar 2025 11:10:08 +0100 Subject: [PATCH] Merge pull request #23810 from overleaf/msm-ldap-login-rate-limiter [SP] LDAP login rate limiter GitOrigin-RevId: dedab17da85c0f91b280d002cdad796e95b9fd4f --- server-ce/hotfix/5.3.2/Dockerfile | 1 + .../Security/RateLimiterMiddleware.js | 46 ++++++++++--------- services/web/app/src/router.mjs | 4 +- 3 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 server-ce/hotfix/5.3.2/Dockerfile diff --git a/server-ce/hotfix/5.3.2/Dockerfile b/server-ce/hotfix/5.3.2/Dockerfile new file mode 100644 index 0000000000..3a43371e6f --- /dev/null +++ b/server-ce/hotfix/5.3.2/Dockerfile @@ -0,0 +1 @@ +FROM sharelatex/sharelatex:5.3.1 diff --git a/services/web/app/src/Features/Security/RateLimiterMiddleware.js b/services/web/app/src/Features/Security/RateLimiterMiddleware.js index 6398916f60..571eb8a307 100644 --- a/services/web/app/src/Features/Security/RateLimiterMiddleware.js +++ b/services/web/app/src/Features/Security/RateLimiterMiddleware.js @@ -56,29 +56,31 @@ function rateLimit(rateLimiter, opts = {}) { } } -function loginRateLimitEmail(req, res, next) { - const { email } = req.body - if (!email) { - return next() +function loginRateLimitEmail(emailField = 'email') { + return function (req, res, next) { + const email = req.body[emailField] + if (!email) { + return next() + } + LoginRateLimiter.processLoginRequest(email, (err, isAllowed) => { + if (err) { + return next(err) + } + if (isAllowed) { + next() + } else { + logger.warn({ email }, 'rate limit exceeded') + res.status(429) // Too many requests + res.json({ + message: { + type: 'error', + text: req.i18n.translate('to_many_login_requests_2_mins'), + key: 'to-many-login-requests-2-mins', + }, + }) + } + }) } - LoginRateLimiter.processLoginRequest(email, (err, isAllowed) => { - if (err) { - return next(err) - } - if (isAllowed) { - next() - } else { - logger.warn({ email }, 'rate limit exceeded') - res.status(429) // Too many requests - res.json({ - message: { - type: 'error', - text: req.i18n.translate('to_many_login_requests_2_mins'), - key: 'to-many-login-requests-2-mins', - }, - }) - } - }) } const RateLimiterMiddleware = { diff --git a/services/web/app/src/router.mjs b/services/web/app/src/router.mjs index b200bd5206..c213689435 100644 --- a/services/web/app/src/router.mjs +++ b/services/web/app/src/router.mjs @@ -218,7 +218,7 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) { webRouter.post( '/login', RateLimiterMiddleware.rateLimit(overleafLoginRateLimiter), // rate limit IP (20 / 60s) - RateLimiterMiddleware.loginRateLimitEmail, // rate limit email (10 / 120s) + RateLimiterMiddleware.loginRateLimitEmail(), // rate limit email (10 / 120s) CaptchaMiddleware.validateCaptcha('login'), AuthenticationController.passportLogin ) @@ -243,7 +243,7 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) { webRouter.post( '/login/legacy', RateLimiterMiddleware.rateLimit(overleafLoginRateLimiter), // rate limit IP (20 / 60s) - RateLimiterMiddleware.loginRateLimitEmail, // rate limit email (10 / 120s) + RateLimiterMiddleware.loginRateLimitEmail(), // rate limit email (10 / 120s) CaptchaMiddleware.validateCaptcha('login'), AuthenticationController.passportLogin )