# OAuthLib: Bearer token can be retrieved as long as client knows a valid client ID for device workflow

OAuthLib's DeviceCodeGrant.validate_token_request never validates device_code, so knowing a public client ID yields a bearer token without any valid device code.

- Payout: Research
- Severity: high
- Program: OAuthLib
- Found by: hekhuisk
- Disclosed: 2026-10-27
- CVE: CVE-2026-49272
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-3jp2-3mrg-2vxc
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-3jp2-3mrg-2vxc
- Tags: area:web domain:web impact:ato kind:research platform:ghsa sev:high tech:oauth technique:source-review vuln:access-control vuln:auth-bypass

**Target:** OAuth 2.0 token endpoint (RFC 8628 device authorization grant)
**Root cause:** DeviceCodeGrant.validate_token_request omits any check that device_code is present and valid, unlike AuthorizationCodeGrant which validates its code; no validate_device_code hook exists on RequestValidator.
**Steps:**
1. Implement RequestValidator.authenticate_client to return True for clients whose client_type is "public".
2. Register a public client with grant_type `urn:ietf:params:oauth:grant-type:device_code`.
3. POST to the token endpoint with body `{"client_id": <public client id>, "grant_type": "urn:ietf:params:oauth:grant-type:device_code", "device_code": <anything>}`.
4. Receive a bearer token for the client despite the bogus device_code.
**How found:** Compared DeviceCodeGrant.validate_token_request against AuthorizationCodeGrant.validate_token_request, which performs presence and validity checks on its code, and noticed the device_code equivalent was missing; RFC 8628 section 3.4 requires device_code as a mandatory parameter.
**Exploitation:** Attacker who knows a valid public client ID enabled for the device workflow calls the token endpoint with an arbitrary device_code value and receives a bearer token, bypassing the device authorization step entirely.
**Insight:** When auditing OAuth grant implementations, diff each grant type's validate_token_request against the authorization_code grant: any grant that skips validating its core credential (device_code, refresh_token, code) is an authentication bypass, especially for public clients where client auth is trivially satisfied.

## Proof of concept (copied exactly from the original report)

**Token request with bogus device_code**

```
{
  "client_id": <ID of the public client you made>,
  "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
  "device_code": <anything you want since it's not validated>
}
```

