Preflight checklist
Ory Network Project
No response
Describe the bug
OAuth2 Bearer Token authentication (issued by Hydra) does not work correctly in Oathkeeper v25.4.0.
Both the bearer_token and oauth2_introspection authenticators have issues that prevent the API client flow from functioning.
Reproducing the bug
Affected Flow
API Client → Oathkeeper(:4455) → app-user(:8082) / app-admin(:8081)
↓
Bearer Token validation fails
Environment
- Oathkeeper:
oryd/oathkeeper:v25.4.0
- Hydra:
oryd/hydra:v25.4.0
- Platform: macOS (Darwin) ARM64 (Apple Silicon)
- Docker: Docker Desktop for Mac (ARM64)
bearer_token authenticator — Incompatible with Hydra Introspect
Symptom
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:4455/user/me
# → {"error":{"code":401,"status":"Unauthorized","message":"Access credentials are invalid"}}
Root Cause
The bearer_token authenticator forwards the token to check_session_url as an Authorization header.
However, Hydra's introspect endpoint (RFC 7662) expects the token in the POST body as token=<value>.
Verification (executed from within the container)
# What bearer_token does (forwards via Authorization header)
POST http://hydra:4445/admin/oauth2/introspect
Authorization: Bearer <token>
# → 400 Bad Request ❌
# Correct introspect call (token in POST body)
POST http://hydra:4445/admin/oauth2/introspect
Content-Type: application/x-www-form-urlencoded
Body: token=<token>
# → {"active": true, ...} ✅
Configuration (does not work)
# oathkeeper.yml
authenticators:
bearer_token:
enabled: true
config:
check_session_url: http://hydra:4445/admin/oauth2/introspect
preserve_path: true
token_from:
header: Authorization
force_method: POST
extra_from: "@this"
subject_from: "sub"
Conclusion
The bearer_token authenticator is fundamentally incompatible with Hydra's introspect endpoint.
This handler is designed for session stores that accept Authorization headers, such as Kratos' sessions/whoami.
Relevant log output
Relevant configuration
Version
v25.4.0
On which operating system are you observing this issue?
None
In which environment are you deploying?
None
Additional Context
oauth2_introspection authenticator — OOM Crash on ARM64
Symptom
Enabling oauth2_introspection causes Oathkeeper to crash immediately after startup, entering a restart loop.
oathkeeper | fatal error: runtime: out of memory
The stack trace points to the github.com/dgraph-io/ristretto cache library.
Root Cause
The ristretto cache library (v1.0.0) used internally by oauth2_introspection fails to allocate memory on ARM64, causing an OOM crash.
The following mitigations were attempted, all without success:
- Explicitly setting
cache.enabled: false → OOM occurs during ristretto initialization itself
- Setting Docker
mem_limit: 512m → Same crash
- Setting
GOMAXPROCS: 2 → Same crash
Configuration (crashes)
# oathkeeper.yml
authenticators:
oauth2_introspection:
enabled: true
config:
introspection_url: http://hydra:4445/admin/oauth2/introspect
Note: Schema Validation Errors
Including subject_from or token_from in the config results in schema validation rejection.
additionalProperties "subject_from" not allowed
Even with a minimal config (introspection_url only), the cache library OOM crash occurs.
Conclusion
oauth2_introspection is unusable on v25.4.0 ARM64.
This is presumed to be an ARM64 compatibility issue in the ristretto library.
Workaround: jwt authenticator + Hydra JWT Access Token Strategy
Approach
Configure Hydra to issue access tokens in JWT format, and use Oathkeeper's jwt authenticator to verify the signature locally via JWKS.
This bypasses the introspect endpoint entirely, avoiding both issues above.
Verified Working
Changes Required
1. hydra.full.yml — Enable JWT access token strategy
strategies:
access_token: jwt
2. oathkeeper.yml — Add jwt authenticator
authenticators:
bearer_token:
enabled: false
jwt:
enabled: true
config:
jwks_urls:
- http://hydra:4444/.well-known/jwks.json
scope_strategy: wildcard
trusted_issuers:
- http://hydra:4444 # Must match the issuer configuration
3. rules.yml — Update protected route authenticators
# admin-api, user-api authenticators
authenticators:
- handler: cookie_session
- handler: jwt # Changed from bearer_token to jwt
Verification Steps
# 1. Obtain a JWT token
TOKEN=$(curl -s -X POST http://127.0.0.1:4455/oauth2/token \
-u "<client_id>:<client_secret>" \
-d "grant_type=client_credentials&scope=openid" | jq -r .access_token)
# 2. Confirm the token is in JWT format (starts with ey...)
echo $TOKEN
# 3. Access the API
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:4455/user/me
# → 200 OK ✅
Preflight checklist
Ory Network Project
No response
Describe the bug
OAuth2 Bearer Token authentication (issued by Hydra) does not work correctly in Oathkeeper v25.4.0.
Both the
bearer_tokenandoauth2_introspectionauthenticators have issues that prevent the API client flow from functioning.Reproducing the bug
Affected Flow
Environment
oryd/oathkeeper:v25.4.0oryd/hydra:v25.4.0bearer_tokenauthenticator — Incompatible with Hydra IntrospectSymptom
Root Cause
The
bearer_tokenauthenticator forwards the token tocheck_session_urlas an Authorization header.However, Hydra's introspect endpoint (RFC 7662) expects the token in the POST body as
token=<value>.Verification (executed from within the container)
Configuration (does not work)
Conclusion
The
bearer_tokenauthenticator is fundamentally incompatible with Hydra's introspect endpoint.This handler is designed for session stores that accept Authorization headers, such as Kratos'
sessions/whoami.Relevant log output
Relevant configuration
Version
v25.4.0
On which operating system are you observing this issue?
None
In which environment are you deploying?
None
Additional Context
oauth2_introspectionauthenticator — OOM Crash on ARM64Symptom
Enabling
oauth2_introspectioncauses Oathkeeper to crash immediately after startup, entering a restart loop.The stack trace points to the
github.com/dgraph-io/ristrettocache library.Root Cause
The ristretto cache library (v1.0.0) used internally by
oauth2_introspectionfails to allocate memory on ARM64, causing an OOM crash.The following mitigations were attempted, all without success:
cache.enabled: false→ OOM occurs during ristretto initialization itselfmem_limit: 512m→ Same crashGOMAXPROCS: 2→ Same crashConfiguration (crashes)
Note: Schema Validation Errors
Including
subject_fromortoken_fromin the config results in schema validation rejection.Even with a minimal config (
introspection_urlonly), the cache library OOM crash occurs.Conclusion
oauth2_introspectionis unusable on v25.4.0 ARM64.This is presumed to be an ARM64 compatibility issue in the ristretto library.
Workaround:
jwtauthenticator + Hydra JWT Access Token StrategyApproach
Configure Hydra to issue access tokens in JWT format, and use Oathkeeper's
jwtauthenticator to verify the signature locally via JWKS.This bypasses the introspect endpoint entirely, avoiding both issues above.
Verified Working
Changes Required
1. hydra.full.yml — Enable JWT access token strategy
2. oathkeeper.yml — Add jwt authenticator
3. rules.yml — Update protected route authenticators
Verification Steps