Introduction

APIs that use opaque bearer tokens (non-JWT) must validate each token by calling the OAuth2 server's introspection endpoint (RFC 7662). When the OAuth2 server is unreachable -- due to network issues, server downtime, or DNS failures -- the API cannot validate any tokens and must either reject all requests or implement a fallback strategy.

Symptoms

  • All API requests return 401 Unauthorized regardless of token validity
  • API logs show introspection endpoint unreachable or connection timeout
  • OAuth2 server health check fails
  • Requests work with JWT tokens (which can be validated locally) but fail with opaque tokens
  • Error message: Failed to introspect token: connection timed out to https://auth.example.com/oauth/introspect

Common Causes

  • OAuth2 server crashed or was taken offline for maintenance
  • Network connectivity issue between the API and the OAuth2 server
  • DNS resolution failure for the OAuth2 server hostname
  • OAuth2 server firewall rules blocking access from API servers
  • OAuth2 server overloaded and not responding within the API's timeout

Step-by-Step Fix

  1. 1.Verify the OAuth2 server is reachable: Test connectivity.
  2. 2.```bash
  3. 3.# Check DNS resolution
  4. 4.dig auth.example.com +short
  5. 5.# Test HTTPS connectivity
  6. 6.curl -v https://auth.example.com/oauth/introspect
  7. 7.# Check OAuth2 server health endpoint
  8. 8.curl -s https://auth.example.com/.well-known/openid-configuration
  9. 9.`
  10. 10.Restart or recover the OAuth2 server: Restore the introspection endpoint.
  11. 11.```bash
  12. 12.# Check OAuth2 server status
  13. 13.systemctl status keycloak # or your OAuth2 server
  14. 14.# Restart if needed
  15. 15.systemctl restart keycloak
  16. 16.# Verify the introspection endpoint works
  17. 17.curl -X POST https://auth.example.com/oauth/introspect \
  18. 18.-d "token=test-token" \
  19. 19.-u "client:secret"
  20. 20.`
  21. 21.Implement token caching to tolerate OAuth2 outages: Cache introspection results.
  22. 22.```java
  23. 23.// Cache introspection results for the token's remaining lifetime
  24. 24.@Cacheable(value = "tokenIntrospection", key = "#token")
  25. 25.public TokenIntrospection introspect(String token) {
  26. 26.return oauth2Client.introspect(token);
  27. 27.}
  28. 28.// Set cache TTL based on the token's 'exp' claim from the introspection response
  29. 29.`
  30. 30.Implement a circuit breaker for the introspection call: Fail fast during outages.
  31. 31.```java
  32. 32.@CircuitBreaker(name = "oauth2", fallbackMethod = "introspectFallback")
  33. 33.public TokenIntrospection introspect(String token) {
  34. 34.return oauth2Client.introspect(token);
  35. 35.}

public TokenIntrospection introspectFallback(String token, Exception e) { // Return cached result or reject with clear error return TokenIntrospection.unavailable("OAuth2 server temporarily unavailable"); } ```

  1. 1.Verify API authentication works after recovery: Test with a valid token.
  2. 2.```bash
  3. 3.curl -H "Authorization: Bearer $VALID_TOKEN" https://api.example.com/resource
  4. 4.# Should return 200 OK
  5. 5.`

Prevention

  • Deploy OAuth2 servers in a highly available configuration (multi-node cluster)
  • Implement introspection result caching with TTL based on token expiration
  • Use JWT tokens instead of opaque tokens to enable local validation
  • Configure circuit breakers with fallback strategies for OAuth2 unavailability
  • Monitor OAuth2 server health and introspection endpoint latency
  • Implement API-level token caching to reduce introspection call frequency