Skip to content

πŸ”’ OAuth callback trusts client-asserted identity β†’ account takeoverΒ #3849

Description

@PierreBrisorgueil

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions