Fix allow_token_introspection default returning false with custom application_class (#1833)#1834
Open
55728 wants to merge 1 commit into
Conversation
…oorkeeper-gem#1833) The default `allow_token_introspection` proc compared application objects with `==`. ActiveRecord equality requires the same class and id, so when a custom `application_class` is configured the comparison fails: the authorized client is resolved as the configured `application_model` while the introspected token's `application` association is bound to the class name captured at mixin load time. Same record, different class -> `==` returns false -> introspection always reported `{ "active": false }` for Client Credentials auth. Compare application ids instead, which is class-agnostic and matches the intent of the check. No other behavior is changed.
houndci-bot
reviewed
Jun 11, 2026
houndci-bot
left a comment
There was a problem hiding this comment.
Some files could not be reviewed due to errors:
Error: unrecognized cop RSpec/AnyInstance found in .rubocop.yml, unrecognized...
Error: unrecognized cop RSpec/AnyInstance found in .rubocop.yml, unrecognized cop RSpec/ExpectInHook found in .rubocop.yml, unrecognized cop RSpec/IndexedLet found in .rubocop.yml, unrecognized cop RSpec/InstanceVariable found in .rubocop.yml, unrecognized cop RSpec/LeakyConstantDeclaration found in .rubocop.yml, unrecognized cop RSpec/MessageChain found in .rubocop.yml, unrecognized cop RSpec/MessageSpies found in .rubocop.yml, unrecognized cop RSpec/RepeatedExampleGroupDescription found in .rubocop.yml, unrecognized cop RSpec/SubjectStub found in .rubocop.yml, unrecognized cop RSpec/VerifiedDoubles found in .rubocop.yml, unrecognized cop plugins found in .rubocop.yml, unrecognized cop Rails/DynamicFindBy found in .rubocop.yml, unrecognized cop Rails/HttpPositionalArguments found in .rubocop.yml, unrecognized cop Rails/HttpStatus found in .rubocop.yml, unrecognized cop Rails/RakeEnvironment found in .rubocop.yml, unrecognized cop Rails/ReflectionClassName found in .rubocop.yml, unrecognized cop Rails/SkipsModelValidations found in .rubocop.yml, unrecognized cop RSpec/BeforeAfterAll found in .rubocop.yml, unrecognized cop RSpec/ContextWording found in .rubocop.yml, unrecognized cop RSpec/DescribeClass found in .rubocop.yml, unrecognized cop RSpec/ExampleLength found in .rubocop.yml, unrecognized cop RSpec/ExpectChange found in .rubocop.yml, unrecognized cop RSpec/MultipleMemoizedHelpers found in .rubocop.yml, unrecognized cop RSpec/SpecFilePathFormat found in .rubocop.yml, unrecognized cop RSpec/MultipleExpectations found in .rubocop.yml, unrecognized cop RSpec/NestedGroups found in .rubocop.yml, unrecognized cop RSpec/NoExpectationExample found in .rubocop.yml
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a regression in the default allow_token_introspection rule when application_class / application_model is customized: introspection authorization was incorrectly failing due to ActiveRecord == comparing both class and id, causing { "active": false } for valid tokens in Client Credentials flows.
Changes:
- Update the default
allow_token_introspectionproc to compare application ids rather than application objects. - Add a regression spec ensuring introspection remains active when the authorized client and token application are instantiated as different classes for the same DB row.
- Add a
CHANGELOG.mdentry describing the fix (note: one reference appears to use the wrong issue/PR number).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
lib/doorkeeper/config.rb |
Fixes default introspection authorization by switching from object equality to application_id / id comparisons. |
spec/controllers/tokens_controller_spec.rb |
Adds a regression test covering custom application_model subclass behavior under POST #introspect. |
CHANGELOG.md |
Documents the behavioral fix under ## main (needs reference number correction). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ## main | ||
|
|
||
| - [#1834] Fix default `allow_token_introspection` returning `false` when a custom `application_class` is configured. The default proc compared application objects with `==`, which fails when the authorized client and the introspected token's application are resolved as different classes (e.g. a base `Doorkeeper::Application` vs. a configured subclass) even though they reference the same record. It now compares application ids instead. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1833.
The default
allow_token_introspectionproc compared application objects with==:ActiveRecord
==requires both the same class and the same id. That assumption breaks once a customapplication_classis configured:token.applicationis resolved through thebelongs_to :applicationassociation, whoseclass_nameis captured at mixin load time (defaults toDoorkeeper::Application).authorized_clientis resolved at request time viaDoorkeeper.config.application_model, i.e. the configured (sub)class.So the two sides reference the same record but are instantiated as different classes, making
==returnfalse. As a result, token introspection authorized via Client Credentials always responded with{ "active": false }, even for the client the token was issued to.Fix
Compare application ids instead of objects. This is class-agnostic and preserves the original intent of the check:
Only the comparison method changes — no other behavior is affected.
token_introspection.rbis untouched; this is a config-level fix.Test
Adds a regression spec under
POST #introspectinspec/controllers/tokens_controller_spec.rbthat configuresapplication_modelto aDoorkeeper::Applicationsubclass, so the authorized client and the introspected token's application resolve as different classes for the same record. It asserts that introspection via Client Credentials responds with"active" => true.The new spec fails against the previous implementation (
"active" => false) and passes with the fix.Verification
bundle exec rspec spec/controllers/tokens_controller_spec.rb spec/lib/config_spec.rb→ all green.CHANGELOG.mdentry under## main.