const rateLimit = require('express-rate-limit') const log = require('../utils/logger')('ratelimit') function makeLimiter({ windowMs, max, label, message }) { return rateLimit({ windowMs, max, standardHeaders: true, legacyHeaders: false, message: { message }, handler: (req, res, next, options) => { log.warn(`${label} rate limit exceeded`, { ip: req.ip, path: req.originalUrl }) res.status(options.statusCode).json(options.message) }, }) } // Brute-force protection on login. const loginLimiter = makeLimiter({ windowMs: 15 * 60 * 1000, max: 10, label: 'login', message: 'Too many login attempts. Please try again later.', }) // Throttle the public contact form. const contactLimiter = makeLimiter({ windowMs: 60 * 60 * 1000, max: 5, label: 'contact', message: 'Too many messages sent. Please try again later.', }) // Cap mobile refresh-token exchanges per IP. Legitimate apps refresh at most a // handful of times per window; a flood is either a bug or an attempt to brute // the refresh endpoint. const mobileRefreshLimiter = makeLimiter({ windowMs: 15 * 60 * 1000, max: 30, label: 'mobile-refresh', message: 'Too many refresh attempts. Please try again later.', }) // Throttle SSO redirect starts per IP — cheap to trigger, and a flood is either a // bug or an attempt to spin the OAuth flow. Generous enough for real users. const ssoStartLimiter = makeLimiter({ windowMs: 15 * 60 * 1000, max: 30, label: 'sso-start', message: 'Too many sign-in attempts. Please try again later.', }) module.exports = { loginLimiter, contactLimiter, mobileRefreshLimiter, ssoStartLimiter }