Refactor auth routes to use controller functions#1374
Conversation
Co-authored-by: alexanmtz <88840+alexanmtz@users.noreply.github.com>
| res.redirect(`${process.env.FRONTEND_HOST}/#/signin/invalid`) | ||
| } | ||
| }) | ||
| router.get('/connect/github', secure, controllers.connectGithub) |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
To fix the problem, introduce a rate-limiting middleware in this router and apply it to the sensitive authorization/connection routes, including /connect/github (the one using secure). The most straightforward approach in an Express-based codebase is to use the widely adopted express-rate-limit package. This avoids changing the business logic or existing behavior beyond rejecting or slowing excessive requests.
Concretely, in src/app/routes/auth/providers.ts:
- Add an import for
express-rate-limit. - Define a
rateLimiterinstance with sensible defaults (e.g., a window and max number of requests) near the router initialization. - Apply
rateLimiteras middleware to the routes that perform authorization: at minimum the/connect/githubroute wheresecureis used, and optionally other/authorize/*and/callback/*routes if you want broader coverage. To minimally satisfy the CodeQL finding, we will wrap only/connect/githubwith the limiter while leaving existing logic intact:router.get('/connect/github', rateLimiter, secure, controllers.connectGithub).
No existing imports are modified or removed; we only add a new import and a small configuration block plus the extra middleware parameter on the specific route definition.
| @@ -3,9 +3,15 @@ | ||
| import * as authenticationHelpers from '../../../modules/authenticationHelpers' | ||
| import * as controllers from '../../controllers/auth' | ||
| import secure from '../secure' | ||
| import rateLimit from 'express-rate-limit' | ||
|
|
||
| const router = express.Router() | ||
|
|
||
| const rateLimiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, | ||
| max: 100 | ||
| }) | ||
|
|
||
| router.get('/authenticated', authenticationHelpers.isAuth) | ||
|
|
||
| router.get('/authorize/google', passport.authenticate('google', { scope: ['email'] })) | ||
| @@ -36,7 +39,7 @@ | ||
|
|
||
| router.get('/callback/github/private', controllers.createPrivateTask) | ||
|
|
||
| router.get('/connect/github', secure, controllers.connectGithub) | ||
| router.get('/connect/github', rateLimiter, secure, controllers.connectGithub) | ||
|
|
||
| router.get('/authorize/github/private', controllers.authorizeGithubPrivateIssue) | ||
| router.get('/authorize/github/disconnect', secure, controllers.disconnectGithub) |
| @@ -128,7 +128,8 @@ | ||
| "url": "^0.11.0", | ||
| "url-search-params": "^1.0.2", | ||
| "x-frame-options": "^1.0.0", | ||
| "zone.js": "^0.8.4" | ||
| "zone.js": "^0.8.4", | ||
| "express-rate-limit": "^8.2.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@playwright/test": "^1.53.0", |
| Package | Version | Security advisories |
| express-rate-limit (npm) | 8.2.1 | None |
| res.redirect(`${process.env.FRONTEND_HOST}/#/signin/invalid`) | ||
| } | ||
| }) | ||
| router.get('/connect/github', secure, controllers.connectGithub) |
Check failure
Code scanning / CodeQL
Missing rate limiting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, this should be fixed by applying rate limiting middleware to routes that perform authentication or authorization, especially those that can trigger expensive work (external API calls, DB writes, etc.). In an Express app, this is typically done by importing a rate limiting library such as express-rate-limit, configuring a limiter instance, and applying it to the specific routes that need protection (instead of globally if we want minimal behavioral change).
For this file, the minimal-change fix is to: (1) import express-rate-limit; (2) define a limiter configured for auth-related routes (e.g., a modest number of requests per IP per time window); and (3) apply that limiter to the /connect/github route (and potentially other similar authorization routes, but CodeQL’s complaint is specifically about controllers.connectGithub). We will add the import at the top of src/app/routes/auth/providers.ts, define the limiter just below the router initialization, and then include the limiter as middleware in the route definition before secure and controllers.connectGithub so that rate limiting occurs before other logic executes. This preserves existing behavior for requests that are under the limit and only changes behavior when a client exceeds the configured rate.
Concretely:
- Add
import rateLimit from 'express-rate-limit'at the top. - After
const router = express.Router(), add a constant such asconst authRateLimiter = rateLimit({ windowMs: ..., max: ... }). - Change line 39 from
router.get('/connect/github', secure, controllers.connectGithub)torouter.get('/connect/github', authRateLimiter, secure, controllers.connectGithub).
| @@ -3,9 +3,15 @@ | ||
| import * as authenticationHelpers from '../../../modules/authenticationHelpers' | ||
| import * as controllers from '../../controllers/auth' | ||
| import secure from '../secure' | ||
| import rateLimit from 'express-rate-limit' | ||
|
|
||
| const router = express.Router() | ||
|
|
||
| const authRateLimiter = rateLimit({ | ||
| windowMs: 15 * 60 * 1000, // 15 minutes | ||
| max: 100 // limit each IP to 100 auth requests per windowMs | ||
| }) | ||
|
|
||
| router.get('/authenticated', authenticationHelpers.isAuth) | ||
|
|
||
| router.get('/authorize/google', passport.authenticate('google', { scope: ['email'] })) | ||
| @@ -36,7 +39,7 @@ | ||
|
|
||
| router.get('/callback/github/private', controllers.createPrivateTask) | ||
|
|
||
| router.get('/connect/github', secure, controllers.connectGithub) | ||
| router.get('/connect/github', authRateLimiter, secure, controllers.connectGithub) | ||
|
|
||
| router.get('/authorize/github/private', controllers.authorizeGithubPrivateIssue) | ||
| router.get('/authorize/github/disconnect', secure, controllers.disconnectGithub) |
| @@ -128,7 +128,8 @@ | ||
| "url": "^0.11.0", | ||
| "url-search-params": "^1.0.2", | ||
| "x-frame-options": "^1.0.0", | ||
| "zone.js": "^0.8.4" | ||
| "zone.js": "^0.8.4", | ||
| "express-rate-limit": "^8.2.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@playwright/test": "^1.53.0", |
| Package | Version | Security advisories |
| express-rate-limit (npm) | 8.2.1 | None |
Co-authored-by: alexanmtz <88840+alexanmtz@users.noreply.github.com>
Description
Inline route handlers in
providers.tsviolated the established pattern of delegating logic to controllers. Four routes (/callback/github,/connect/github,/callback/bitbucket,/authorize/local) implemented business logic directly in route definitions.Changes:
src/app/controllers/auth.ts:callbackGithub- handles GitHub OAuth callback with login strategy routingconnectGithub- initiates GitHub authentication for account linkingcallbackBitbucket- handles Bitbucket OAuth callbackauthorizeLocal- handles local auth with header injectionreq.userandreq.user.tokento prevent silent failuresBefore:
After:
Routes now follow the same pattern as
/callback/github/privateand/authorize/github/disconnect.Thank you for your contribution!
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.