If you use Doorkeeper to handle OAuth 2 authentication in your Ruby on Rails or Grape APIs, you need to know about a major vulnerability discovered last year, officially tracked as CVE-2023-34246. This quiet bug could let attackers impersonate users without their consent, particularly when dealing with so-called “public clients.” Here, I’ll break it all down simply—code, risk, and what you should do.
What is Doorkeeper and Who is at Risk?
Doorkeeper is the go-to OAuth 2 provider gem for many Rails and Grape projects. It allows third-party apps to request access to your users’ data, powering everything from single sign-on to mobile app authentication. OAuth 2 distinguishes between *confidential* clients (like secure backend apps) and *public* clients (like single-page JavaScript apps or mobile apps that can’t securely hold secrets).
Public clients are riskier because there’s no way to guarantee their identity—they can’t safely store credentials. That’s why OAuth 2 implementations usually take special care to always require user consent for these apps.
The Flaw: Consent Bypassing for Public Clients
Before version 5.6.6, Doorkeeper would automatically allow OAuth authorization requests from public clients if the user had previously approved that client. This means users wouldn’t see the consent screen again.
That sounds convenient, but here’s the catch: anyone can impersonate a public client simply by copying its client ID. Once the link between the user and a client is established, and the consent was given once, anyone pretending to be that client could get access tokens—no new prompt, no user awareness.
The logic that skips consent typically happens in controllers like AuthorizationsController
# Pseudocode - Simplified for clarity
if client_is_public && user_has_previous_approval
# BAD: silently grant authorization without re-prompting the user
auto_approve!
else
ask_user_for_consent!
end
This means an attacker only needs to register a public client once and can later spam the endpoint for new tokens—acting on that user's behalf as soon as they're authenticated with the Rails app.
User logs in once, grants consent.
3. Attacker then crafts requests pretending to be that client (using its public client ID, which isn’t secret).
User gets no further consent prompts, while attacker is handed access tokens.
This is unfixable at a user or client level because, by definition, public clients are not secured.
Why Is This a Problem?
- No identity assurance: Anyone can act as the “public client” by knowing its client ID (which is easy to discover or guess).
No consent renewal: Victims get no notification or chance to reject new authorizations.
- Shadowy impersonation: Access tokens flow to unauthorized parties, possibly exposing sensitive user data.
How It Was Fixed
Doorkeeper 5.6.6 updated the consent logic. Public clients always require user consent, regardless of previous authorizations. Here’s a safe pattern (post-fix):
if client_is_public
# Always ask for user consent for public clients
ask_user_for_consent!
elsif user_has_previous_approval
auto_approve!
else
ask_user_for_consent!
end
Now, no public client can silently get new tokens—the user has to explicitly okay every authorization attempt.
Upgrade immediately: Move to at least Doorkeeper 5.6.6.
Official References and Further Reading
- CVE-2023-34246 Advisory
- Doorkeeper 5.6.6 Release Notes
- Upgrading Doorkeeper Guidance
- Original Commit Fix
The Bottom Line
If you use Doorkeeper in your Rails or Grape app, especially with public OAuth clients, update now. Prevent attackers from silently acting on behalf of your users. As OAuth 2 grows more popular, subtle bugs like CVE-2023-34246 remind us of the importance of vigilance—even in trusted libraries.
*Stay secure!*
Did this help? Want more breakdowns of Ruby and Rails security? Let me know below or subscribe for alerts!
Timeline
Published on: 06/12/2023 17:15:00 UTC
Last modified on: 07/12/2023 15:15:00 UTC