Module: StandardId::Provider::Extensions::IntrospectionsControllerExt
- Defined in:
- lib/standard_id/provider/extensions/introspections_controller_ext.rb
Overview
Teaches core's RFC 7662 endpoint (POST /oauth/introspect,
StandardId::Api::Oauth::IntrospectionsController) about this engine's
access-token denylist.
Why this replaced a second introspection endpoint
This gem used to ship its own POST /api/provider/introspect. Since
standard_id 0.33.0 core has one too, and core's is strictly more
RFC-conformant:
* RFC 7662 §2.2 — every failure mode renders `{"active": false}` and
NOTHING else. The provider's raised InvalidClientError on bad client
credentials, answering 401 with an error body: a caller could tell
"your credentials are wrong" from "that token is not valid".
* The provider's rate limiter answered 429, which turns the throttle
into a token-validity oracle — probe until throttled, then read the
status code rather than the body. Core's renders the ordinary
inactive response instead, deliberately.
* Core's is 404-gated behind `config.oauth.introspection_enabled`, so
an endpoint that answers questions about other people's tokens is
not exposed by accident. The provider's was always on — and its own
`config.provider.introspection_enabled` flag was never read.
Only one thing was worth keeping: core cannot see StandardId::Provider::RevokedToken. Core says so itself — access tokens are stateless, "this engine cannot invalidate a stateless JWT before its exp". This engine's revocation endpoint maintains exactly the jti denylist that makes that possible. So rather than run two endpoints with different answers, the denylist is contributed INTO core's.
Coupling
#decode_token is a private method of a non-public controller. That is
the same bargain the rest of this gem already makes (see
StandardId::Provider::Engine), and the reason the gemspec pins
standard_id to ~> 0.33 with a compat CI job watching it.
Returning nil is the whole mechanism: core already treats a nil decode
as inactive and renders the bare {"active": false}, so a denylisted
token is indistinguishable from a forged one — which is what RFC 7662
§2.2 wants.