Skip to content

Fix allow_token_introspection default returning false with custom application_class (#1833)#1834

Open
55728 wants to merge 1 commit into
doorkeeper-gem:mainfrom
55728:fix/1833-allow-token-introspection-custom-application-class
Open

Fix allow_token_introspection default returning false with custom application_class (#1833)#1834
55728 wants to merge 1 commit into
doorkeeper-gem:mainfrom
55728:fix/1833-allow-token-introspection-custom-application-class

Conversation

@55728

@55728 55728 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #1833.

The default allow_token_introspection proc compared application objects with ==:

authorized_token.application == token&.application   # authorized_token branch
authorized_client == token.application               # authorized_client branch

ActiveRecord == requires both the same class and the same id. That assumption breaks once a custom application_class is configured:

  • token.application is resolved through the belongs_to :application association, whose class_name is captured at mixin load time (defaults to Doorkeeper::Application).
  • authorized_client is resolved at request time via Doorkeeper.config.application_model, i.e. the configured (sub)class.

So the two sides reference the same record but are instantiated as different classes, making == return false. 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:

if authorized_token
  authorized_token.application_id == token&.application_id
elsif token&.application
  authorized_client.id == token.application_id
else
  true
end

Only the comparison method changes — no other behavior is affected. token_introspection.rb is untouched; this is a config-level fix.

Test

Adds a regression spec under POST #introspect in spec/controllers/tokens_controller_spec.rb that configures application_model to a Doorkeeper::Application subclass, 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.
  • RuboCop reports no new offenses on the changed files.
  • Added a CHANGELOG.md entry under ## main.

…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 houndci-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_introspection proc 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.md entry 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.

Comment thread CHANGELOG.md

## 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

allow_token_introspection default silently returns false when using a custom application_class

3 participants