Skip to content

6.0.0.beta2

Pre-release
Pre-release

Choose a tag to compare

@nbulaj nbulaj released this 10 Aug 14:32
· 16 commits to main since this release
ce535d9

Please make sure you read the Upgrade guides
and changelog below before the update since this version includes breaking changes.

  • [#1865] Revoke the token issued for an authorization code when the code is exchanged more than once, per RFC 6749 §4.1.2 / §10.5. Active when the oauth_access_grants.access_token_id column exists: new installs get it from the generated migration, existing apps can add it with rails generate doorkeeper:grant_reuse_revocation. Closes [#1713].
  • [#1871] [BREAKING] redirect_uri is now compared to the registered redirect URIs with the simple string comparison required by RFC 6749 §3.1.2.3 (the RFC 8252 §7.3 loopback port exception is kept). Clients relying on the previous lenient matching must send the exact registered URI, closes [#1718].
  • [#1874] Fix force_pkce requiring a code_challenge from response types that never issue an authorization code (e.g. token, or an OIDC extension's id_token / id_token token). PKCE (RFC 7636) protects the authorization code exchange, so for code-less response types there is no token-endpoint step where a code_verifier could ever be checked — such requests were rejected over a parameter that cannot be validated. force_pkce now only enforces the challenge for response types that issue a code (code and code-carrying hybrid types such as code id_token).
  • [#1876] Fix: reject a non-string scope parameter (e.g. scope[a]=b, which Rack parses into a Hash) with invalid_request (RFC 6749 §3.3) instead of an unhandled 500. Scopes.from_string now raises Errors::InvalidScopeParameter for a non-string argument — turned into invalid_request by the token endpoint's rescue_from, so every grant type is covered — and the authorization endpoint rejects it up front in pre-authorization validation. The crash was reachable unauthenticated, before client authentication.
  • [#1877] Fix: let the none client authentication strategy match a request whose Authorization header carries a Bearer token. A bearer credential authorizes access to the endpoint itself (e.g. a bearer-protected introspection endpoint per RFC 7662 §2.1, or a revocation request) rather than authenticating the client, so it must not suppress the public-client none strategy when the client identifies itself with a body client_id. Any other non-blank Authorization value — Basic, or a Bearer with no token — is still treated as header-based client authentication and continues to bypass none. The 6.0.0.beta1 workaround of dropping the Authorization header from such a request is no longer needed.
  • [#1878] Fix: the loopback redirect URI exception (RFC 8252 §7.3) now varies by port only, not by userinfo. The port was cleared with URI#port=, which on Ruby >= 4.0 also drops the userinfo, so http://attacker@127.0.0.1/cb matched a registered http://127.0.0.1/cb. The match is now made component-by-component. The destination host is always the loopback interface, so this was not a cross-origin open redirect, and non-loopback hosts were never affected.
  • [#1879] Fix: with reuse_access_token enabled, replaying an authorization code no longer revokes an access token that another grant still shares. The single-use revocation added in [#1865] followed the grant's access_token_id, which a reused token shares across grants, so a replay could collaterally revoke a token another valid session still held. The revocation now skips a token referenced by another grant and only reaches one unique to the replayed code; a token unique to the code is still revoked as before.
  • [#1881] Fix: Doorkeeper::ApplicationsController no longer 500s on create/update/destroy in api_only mode, where ActionController::API provides no flash. Confining flash to the HTML path is not sufficient on its own, because a client that does not name JSON explicitly still negotiates its way into that path — an absent Accept header and a browser-like list such as application/json, text/plain, */* both resolve to text/html, and a bare */* resolves to the first registered format — so api_only mode now pins the response format to JSON.
  • [#1883] Internal: merge CHANGELOG.md with git's union driver, so two pull requests that each add an entry no longer conflict on the line above "Please add here".
  • [#1884] Fix: /oauth/introspect and /oauth/revoke extend the token lookup across both token types when the lookup by token_type_hint finds nothing (RFC 7662 §2.1 / RFC 7009 §2.1), so a wrong hint no longer hides a token the server knows about ([#1882])
  • [#1885] Index oauth_access_grants.access_token_id in the migration templates: since [#1879] the code-replay revocation filters access grants by that column, the "never used to filter queries" premise behind index: false no longer holds.
  • [#1886] Add support for Resource Indicators for OAuth 2.0 (RFC 8707). Clients can include a resource parameter in authorization and token requests to indicate the target protected resource(s). The authorization server validates resource URIs, enforces audience restriction on tokens, and includes aud in introspection responses. Enable by configuring resource_indicator_validator with a callable. Requires new resource columns on access grants and tokens — run rails generate doorkeeper:resource_indicators to add the migration.
  • [#1887] [test] Pin that a requested non-default scope reaches the authorization grant and the exchanged token, and that the authorization strategy shares the controller's pre-authorization — the mismatch reported in [#1576] does not reproduce. Test-only change, closes [#1576].
  • [#1888] Document custom grant flow registration (Doorkeeper::GrantFlow.register) in the README with a SAML 2.0 bearer assertion (RFC 7522) walkthrough, and pin URN-shaped custom grant types with an end-to-end request spec. Docs/test-only change, closes [#764].
  • [#1890] [test] Pin that the authorization endpoint answers invalid_redirect_uri for a client registered without a redirect URI (allow_blank_redirect_uri), whether or not the request supplies one — the behavior required by RFC 6749 §3.1.2.3. Test-only change, closes [#1682].
  • [#1898] Fix: with reuse_access_token enabled, the client_credentials grant no longer reuses a token whose resource differs from the one requested (RFC 8707), so the audience restriction the client asked for is always applied. Follow-up to [#1886].
  • [#1899] Document the client authentication methods registry (Doorkeeper::ClientAuthentication.register) in the README with a walkthrough for registering a custom method, and pin it with an end-to-end request spec. Docs/test-only change, closes [#1894].
  • [#1891] Fix: an authorization request carrying a redirect_uri for a client registered without one (redirect_uri is nil under allow_blank_redirect_uri) now answers invalid_redirect_uri instead of crashing with an unhandled 500.
  • [#1896] Add an opt-in private_key_jwt client authentication method (RFC 7523 / OIDC Core §9, requires the jwt gem >= 2.7) that verifies assertions against the client's published public keys — jwks / jwks_uri attributes you define on your Application model, the latter fetched with an SSRF-hardened HTTP client. The jti replay guard and the fetched-JWKS cache are process-local by default and can be replaced with shared stores via the private_key_jwt_replay_guard / private_key_jwt_jwks_cache config options. Part of [#1875].
  • [#1901] [test] Pin the answered behaviors behind [#984], [#1554], [#1600], [#1663], [#1759] and [#1787] with regression specs — the built-in client authentication methods, the unmodified echo of long state values, DB persistence with custom token generators, refresh token rotation/expiry semantics and the introspection asymmetry. Test-only change, closes those issues along with [#1291], [#1756] and [#1764].
  • [#1902] Fix: requests that omit scope now compute the same default scopes at the authorization and token endpoints (Scopes#common, symmetric). With dynamic scopes enabled, a scope pattern in either default_scopes or the application's scopes grants the matching concrete scope at both endpoints, closes [#1889].
  • [#1903] Fix: revoke_previous_client_credentials_token no longer revokes a client's live access token issued for a different resource ([#1886]), so a client can keep one audience-restricted token per resource server.
  • [#1905] [test] Cover private_key_jwt client authentication on the client_credentials grant, the one flow where an assertion is the client's only credential end to end. Test-only change.