# OAuth client_id and scope trust

Authorization decided from request-supplied client_id, unverified registration, or unenforced token audience

_Area: Web authentication and account takeover. Seen in 2 disclosed reports; latest 2026-10-30. Updated 2026-11-02._

## How it works
OAuth separates *who is asking* (the authenticated client) from *what the request claims* (client_id, scope, audience). The weakness is when an authorization decision — grant type, scope, audience, or which app gets a token — is made from a client-supplied value instead of the authenticated principal or a verified registration. The assumption that breaks: that the identifier in the request describes the same party the server authenticated. When it doesn't, a low-privilege or attacker-controlled client is judged by a value it chose.

## Where it shows up
- Grant handlers that call scope/grant-type validation before normalizing `client_id` from the authenticated client [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md)
- Fallback patterns like `x = x or authenticated.x`, which preserve a body-supplied value [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md)
- JWT verification that checks issuer but not audience, so a token minted for a narrow resource carries broader group claims [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md)
- Unauthenticated dynamic client registration with arbitrary redirect URIs, or consent-less auto-approval [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md)
- Shared OAuth clients / reusable public identifiers accepted with an arbitrary secret across tenants [E1](https://bugbountylibrary.com/r/blog%3Aseblu-de-2021-12-iap-bypass-html.md)

## How to review
Trace the order of operations in the token/authorization endpoint. The invariant: every authorization check (grant type, scope, audience, redirect URI) must read the *authenticated* client object and a *verified* registration, never a request-parsed identifier. Confirm `request.client_id` is set from `request.client.client_id` before any validation runs, and that no `or` fallback lets a body value survive [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md). For tokens, verify the API layer enforces audience, not just issuer, and that claims don't exceed the requested resource [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md). For registration, require authentication and exact redirect-URI matching, and require consent [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md). For shared clients, test whether your own instance accepts the victim's public client ID with a bogus secret [E1](https://bugbountylibrary.com/r/blog%3Aseblu-de-2021-12-iap-bypass-html.md).

## How finders spotted it
- Code reading showed validate_grant_type/validate_scopes running before client_id normalization, with an `or` fallback preserving body input — a split identity state [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md)
- Noticed a "sharing OAuth clients" convenience feature, tried configuring an attacker app with the victim's client ID, and found the secret wasn't validated [E1](https://bugbountylibrary.com/r/blog%3Aseblu-de-2021-12-iap-bypass-html.md)
- Advisory analysis (not the finder's trail) noted unauthenticated DCR, consent-less auto-approval, and issuer-only JWT validation combined [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md)

## Variants seen
- Authenticated client vs body client_id divergence at the token endpoint [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md)
- Shared public client identifier accepted with arbitrary secret across orgs [E1](https://bugbountylibrary.com/r/blog%3Aseblu-de-2021-12-iap-bypass-html.md)
- Issuer-only JWT validation with audience confusion widening scope [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md)

## Impact and severity
Low-privilege client obtaining admin-scoped tokens [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md); victim's full API authorization stolen, exceeding the requested MCP server scope [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md). Impact rises when the flaw chains with routing interception and hostname-mismatch cookie issuance into full IAP bypass and session-cookie minting [E1](https://bugbountylibrary.com/r/blog%3Aseblu-de-2021-12-iap-bypass-html.md) — that chain is adjacent, not core client_id trust.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aseblu-de-2021-12-iap-bypass-html.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-7984-qgvg-3j9c.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-xwmw-prc4-v3cr.md
