
Cloud Vulnerability DB
A community-led vulnerabilities database
Doorkeeper accepts an access token through three transmission methods — the Authorization: Bearer header, a form-encoded body parameter, and a URI query parameter (access_token / bearer_token) — as configured by access_token_methods. RFC 6750 §2 requires that a client "MUST NOT use more than one method to transmit the token in each request", and §3.1 requires a resource server to answer such a request with invalid_request.
Doorkeeper instead authorized the request with the first configured method that yielded a token and silently discarded every other token presented in the same request. Which token authorizes the request was therefore decided by the server's configured method order, not by what the caller sent, and the form-encoded body and the URI query were never told apart at all, because both Rails and Rack merge them into a single parameter hash before Doorkeeper reads it (Rails lets the query win, Rack lets the body win).
This affects every resource protected with doorkeeper_authorize! (Rails and Grape, and controllers built on Doorkeeper's own base classes), GET /oauth/token/info, and the bearer-token authorization path of POST /oauth/introspect.
Two consequences:
Authorization: Bearer while forwarding a caller-controlled access_token parameter runs the request under the gateway's identity; the caller's token is discarded without any error or log entry. Attribution, rate limiting and resource_owner_id resolution are then wrong.Measured on v5.9.6 with two access tokens for two different applications and two different resource owners, default access_token_methods:
| Request | Result |
|---|---|
Authorization: Bearer <A> + ?access_token=<B> | 200 — served under A, B discarded |
?access_token=<A>&bearer_token=<B> | 200 — served under A, B discarded |
Authorization: Bearer <revoked B> + ?access_token=<valid A> | 401 — the valid token is discarded |
same request as row 1 with access_token_methods order reversed | 403 — now the parameter wins |
POST with access_token=<A> in the body and ?access_token=<B> in the query | 200 — served under B on Rails, under A on Grape |
The fix counts how many transmission methods carry a token and refuses the request when there is more than one. Only the built-in extraction methods take part in the check; a custom callable configured in access_token_methods keeps the historical first-wins behaviour, mirroring the exemption client authentication gives its legacy callable extractors.
invalid_request (HTTP 400) response RFC 6750 §3.1 prescribes, at every affected surface. The body and the query count as two methods, and the same token repeated across two methods is refused as well. Doorkeeper.authenticate and the doorkeeper_token helpers keep their token-or-nil contract; under handle_auth_errors :raise the request raises Doorkeeper::Errors::InvalidRequest (a sibling of Doorkeeper::Errors::InvalidToken, not a subclass). A new doorkeeper_bad_request_render_options controller hook customizes the 400 body. See the 6.0.0 CHANGELOG and upgrade guide.invalid_token (HTTP 401), with no change to any public method's contract. The stricter invalid_request answer is 6.0-only.If you cannot upgrade, reduce access_token_methods to a single method (for example access_token_methods :from_bearer_authorization) so that only one transmission method is read, and make any gateway, WAF or middleware in front of Doorkeeper read the same one. Note that this does not detect the body/query collision for the parameter methods; only upgrading does.
invalid_request)Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."