cloudflare / cloudflare/workers-oauth-provider
fix: enforce client's registered `grant_types` at /token
- Dominant language
- TypeScript
- Stars
- 1.9k
- Forks
- 134
- PR merge metrics
- No merged PRs in 30d
Description
## Problem
The token endpoint dispatches on `body.grant_type` (`src/oauth-provider.ts` ~L1979) without checking the client's registered `grant_types` array. A client that DCR-registered with `[\"authorization_code\"]` can still successfully exchange a refresh token or, with EMA configured, a `urn:ietf:params:oauth:grant-type:jwt-bearer` assertion.
Per RFC 7591 §2 and RFC 6749 §10.6, the AS SHOULD reject grant types not in the client's registered set. RFC 8414 also requires `grant_types_supported` to be the AS-wide list — the client-specific allowed set is per-client.
## Repro
1. Register a client with `grant_types: [\"authorization_code\"]` only.
2. With EMA enabled on the AS, POST `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer` to `/token` with a valid ID-JAG.
3. Observed: 200 OK with access token.
4. Expected: `400 unauthorized_client` (grant type not permitted for this client).
## Suggested fix
In the dispatch in `handleTokenRequest`, after resolving the client, check that `clientInfo.grantTypes` (which is already stored at registration) includes the requested grant type. Reject with `unauthorized_client` if not.
The default for clients registered without specifying `grant_types` is `[\"authorization_code\"]` per RFC 7591, so this enforcement also closes the implicit-acceptance gap for refresh-token and jwt-bearer.
## Reporter
Surfaced during EMA integration testing by an external partner.
Contributor guide
Research direction
Start in src/oauth-provider.ts around handleTokenRequest and the dispatch near line 1979. Trace how the resolved client’s clientInfo.grantTypes and the registration default are represented, then verify that a disallowed refresh-token or JWT-bearer request returns unauthorized_client rather than an access token.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, authentication, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100