feat: rate limit authentication endpoints#115
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds application-level rate limiting using @nestjs/throttler, with a global default throttle and tighter limits on high-risk authentication endpoints to mitigate brute force and abuse.
Changes:
- Add
@nestjs/throttlerdependency. - Register
ThrottlerModuleglobally and applyThrottlerGuardas a globalAPP_GUARD. - Add per-route
@Throttle()overrides for/auth/login,/auth/register, and/auth/forgot-password, and document env vars in.env.example.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks @nestjs/throttler dependency resolution. |
| backend/package.json | Adds @nestjs/throttler dependency. |
| backend/src/app.module.ts | Configures global throttler defaults and installs ThrottlerGuard globally. |
| backend/src/modules/auth/auth.controller.ts | Adds stricter per-endpoint throttling for sensitive auth routes. |
| backend/.env.example | Documents new rate-limit env variables and defaults. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Register ThrottlerModule globally with configurable default limits (100 req/60s). Apply stricter per-endpoint limits on auth routes via @Throttle decorator: - POST /auth/login: 10 req/60s (AUTH_LOGIN_THROTTLE_LIMIT/TTL) - POST /auth/register: 5 req/60s (AUTH_REGISTER_THROTTLE_LIMIT/TTL) - POST /auth/forgot-password: 5 req/60s (AUTH_FORGOT_THROTTLE_LIMIT/TTL) All limits are env-configurable. ThrottlerGuard applied as global APP_GUARD. 429 responses include Retry-After header via ThrottlerGuard defaults. Closes #95
1db55b8 to
4602f86
Compare
Review item fixes: - Replace parseInt() in @Throttle decorators with Number() + isFinite validation via toThrottleInt() helper; invalid env vars fall back to safe defaults rather than silently producing NaN - Rename *_THROTTLE_TTL env vars to *_THROTTLE_TTL_MS for unambiguous unit signalling; update .env.example and all references - Apply same Number/isFinite validation to THROTTLE_TTL_MS/THROTTLE_LIMIT in ThrottlerModule.forRootAsync factory in app.module.ts - Add CustomThrottlerGuard (src/common/guards/throttler.guard.ts) that reads X-Forwarded-For header for proxy-aware client identification; register as APP_GUARD in AppModule instead of plain ThrottlerGuard - Add auth-rate-limit.e2e-spec.ts: exceeds login rate limit and asserts 429 Conflict resolutions: - .env.example: kept rate-limiting block + added ALLOWED_ORIGIN from main - auth.controller.ts: kept @Throttle + @httpcode on forgot-password route - pnpm-lock.yaml: regenerated
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- getTracker(): use req.ips[0] (Express proxy-aware) instead of reading X-Forwarded-For directly; avoids spoofing when trust proxy is not set - main.ts: move dotenv/config to first import so process.env is populated before any module-level code evaluates it (fixes per-route throttle constants not reading .env values during local development) - e2e test: add Retry-After header assertions (defined, integer, > 0)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Replace \`Number(env) || 10\` with \`toThrottleInt()\` to mirror the exact same parsing/flooring/fallback logic used in auth.controller.ts; prevents a misconfigured env value (e.g. 'Infinity') from hanging the for loop - Read \`AUTH_LOGIN_THROTTLE_TTL_MS\` via the same helper to derive the expected TTL window in seconds - Add upper-bound assertion: \`Retry-After\` must be <= \`ceil(TTL_MS / 1000)\`; a larger value would indicate a unit mismatch or misconfiguration in the throttler setup
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Resolved conflicts: - backend/.env.example: kept main's sectioned format and FRONTEND_URL; added Rate Limiting section under its own header; dropped duplicate Application block from HEAD - backend/src/modules/auth/auth.controller.ts: kept both Throttle import (PR-115) and ConfigService import (main/PR-118)
Summary
Test plan
Closes #95