Opaque bearer tokens require a trusted introspection response per validation path, making network failure and cache staleness part of API availability.
Spring opaque-token introspection: budget the authorization-server dependency
The token is only a handle
An opaque token tells the receipt service nothing until an authorization server confirms that it is active and returns its attributes. Spring Resource Server can call an introspection endpoint through an OpaqueTokenIntrospector. This can make revocation visible sooner than a self-contained JWT, but it adds a remote dependency to authentication. JWT validation instead checks a signed token locally, subject to key and expiry rules.
Bound calls and caching
Configure the endpoint, client credentials and HTTP timeouts from protected settings. Never print bearer tokens or introspection credentials in logs. If a local cache is introduced, bind it to token identity, expire entries no later than the returned token expiry and choose an explicit revocation delay. A cache that stores active results indefinitely defeats the operational reason for introspection. Downstream capacity thinking applies here too: a login provider outage can saturate request workers if every call waits at once.
Fail closed and observe
Test active, inactive, malformed and expired tokens, plus a timeout and a server error. Unavailable introspection must not turn into anonymous permission to issue receipts. Distinguish authentication failure from dependency failure in internal metrics without exposing token values. Measure p95 introspection latency and concurrent in-flight calls, then set a request budget that leaves room for the actual receipt work.
Implementation contract
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=${INTROSPECTION_URI}
spring.security.oauth2.resourceserver.opaquetoken.client-id=${INTROSPECTION_CLIENT_ID}
spring.security.oauth2.resourceserver.opaquetoken.client-secret=${INTROSPECTION_CLIENT_SECRET}Cost and verification
Without caching, authorization calls grow O(requests) and add network latency per request. A bounded cache reduces calls but extends the window before revocation is observed.
Common Mistakes
- Do not cache a positive introspection result without an expiry policy.
- Do not interpret an introspection outage as a valid token.
- Do not log bearer values or introspection client secrets.
Read next
Spring Security JWT resource server: validate trust before checking scope, Spring OAuth2 client credentials: acquire and reuse a service token, Spring Security 401 versus 403: authentication and access are separate failures, Spring Resource Server JWT key rotation: overlap keys across token lifetime, Spring Boot metrics: bound tag values instead of tracking each receipt.
