Part of #3848 Β· severity: critical
Where
modules/auth/controllers/auth.controller.js:637-674 (the req.body?.strategy === false branch) and modules/auth/routes/auth.routes.js:93-94.
Problem
POST /api/auth/:strategy/callback has a "strategy managed on client side" branch that builds a user object from client-supplied email / value (set as providerData[key]), looks the account up by that value (checkOAuthUserProfile), and mints a TOKEN JWT cookie β with no server-side verification of any provider ID/access token. The route registers neither authLimiter nor passport (every other auth route does).
Exploit
An unauthenticated attacker who knows a victim's (public) email sends:
POST /api/auth/google/callback
{ "strategy": false, "key": "email", "value": "victim@example.com" }
checkOAuthUserProfile matches the victim's OAuth account and the handler returns a valid victim-scoped TOKEN cookie β full session, no password, no provider token. Works with key:"sub" for any OAuth user and via the linked-account branch for local accounts. The unthrottled route also enables enumeration.
Fix
Never trust a client-asserted OAuth identity. Default: remove the strategy === false branch so the callback always runs passport.authenticate(strategy, β¦). If a native/mobile flow is reintroduced, the client must submit the provider ID/access token and the server must verify it (e.g. google-auth-library verifyIdToken against the configured clientID; Apple identity-token JWKS) before resolving the account by the verified sub/email. Also add authLimiter to both /api/auth/:strategy/callback routes.
Created via /dev:issue
Part of #3848 Β· severity: critical
Where
modules/auth/controllers/auth.controller.js:637-674(thereq.body?.strategy === falsebranch) andmodules/auth/routes/auth.routes.js:93-94.Problem
POST /api/auth/:strategy/callbackhas a "strategy managed on client side" branch that builds a user object from client-suppliedemail/value(set asproviderData[key]), looks the account up by that value (checkOAuthUserProfile), and mints aTOKENJWT cookie β with no server-side verification of any provider ID/access token. The route registers neitherauthLimiternorpassport(every other auth route does).Exploit
An unauthenticated attacker who knows a victim's (public) email sends:
checkOAuthUserProfilematches the victim's OAuth account and the handler returns a valid victim-scopedTOKENcookie β full session, no password, no provider token. Works withkey:"sub"for any OAuth user and via the linked-account branch for local accounts. The unthrottled route also enables enumeration.Fix
Never trust a client-asserted OAuth identity. Default: remove the
strategy === falsebranch so the callback always runspassport.authenticate(strategy, β¦). If a native/mobile flow is reintroduced, the client must submit the provider ID/access token and the server must verify it (e.g.google-auth-libraryverifyIdTokenagainst the configured clientID; Apple identity-token JWKS) before resolving the account by the verifiedsub/email. Also addauthLimiterto both/api/auth/:strategy/callbackroutes.Created via /dev:issue