From 961af7752c371ed374613b9e74acf9d87424d469 Mon Sep 17 00:00:00 2001 From: shaunn Date: Wed, 26 Nov 2025 08:39:55 -0800 Subject: [PATCH 1/6] docs: oauth2 stateless jwt access tokens --- docs/self-hosted/oel/oauth2/stateless-jwt.mdx | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 docs/self-hosted/oel/oauth2/stateless-jwt.mdx diff --git a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx new file mode 100644 index 000000000..73a5a8d5a --- /dev/null +++ b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx @@ -0,0 +1,175 @@ +--- +id: stateless-jwt +title: Stateless JWT access tokens +sidebar_label: Stateless JWT tokens +--- + +# Stateless JWT access tokens + +This document explains how to configure stateless JWT access tokens in Ory Hydra. When enabled, JWT access tokens are issued as +self-contained tokens without persisting them to the database, significantly improving performance for high-throughput workloads. + +Stateless JWT access tokens are available only to customers on an Ory Enterprise plan (Ory Enterprise License / Ory Network +Enterprise). If you are interested in this feature, please [contact us](https://www.ory.sh/contact). + +## Overview + +By default, Ory Hydra persists all access tokens to the database, regardless of the token strategy (opaque or JWT). This +persistence enables features like token introspection, revocation, and userinfo endpoint support. However, for workloads using JWT +access tokens that do not require these stateful operations, database writes introduce unnecessary overhead. + +The stateless JWT feature optimizes performance by skipping database persistence for JWT access tokens. When enabled, access +tokens are issued as self-contained JWTs with a configurable boolean claim that identifies them as stateless. Operations that +require token state (introspection, revocation, and userinfo) will return an error for these tokens. + +This feature applies when either the OAuth2 client is configured to use the JWT access token strategy or the global access token +strategy is set to JWT (instead of opaque). + +## How it works + +When stateless JWT tokens are enabled: + +1. **Token Generation**: JWT access tokens are issued with an additional boolean claim (default: `sl`) set to `true`. This claim + identifies the token as stateless. + +2. **No Database Writes**: Access token sessions are not written to the database, eliminating write operations and improving + performance. + +3. **Stateful Operations Unavailable**: Operations that require token state return HTTP 501 (Not Implemented) with error + `unsupported_token_type`: + + - **Token Introspection** (`/oauth2/introspect`): Returns 501 for stateless JWT tokens + - **Token Revocation** (`/oauth2/revoke`): Returns 501 for stateless JWT tokens + - **Userinfo Endpoint** (`/userinfo`): Returns 501 for stateless JWT tokens + +4. **Standard JWT Validation**: Token validation continues to work through standard JWT signature verification and claims + validation. + +## Configuration + +Configure stateless JWT access tokens using the `strategies.jwt.stateless` configuration namespace. + +### Configuration keys + +Two configuration keys control stateless JWT behavior: + +- `strategies.jwt.stateless.enabled`: Boolean flag to enable or disable stateless JWT tokens. Default: `false` +- `strategies.jwt.stateless.claim_name`: String value specifying the claim name used to identify stateless tokens. Default: `sl` + +### Example configuration + +```yaml +strategies: + jwt: + stateless: + enabled: true + claim_name: sl +``` + +In this configuration: + +- Stateless JWT tokens are enabled +- JWT access tokens will include a top-level claim `"sl": true` +- Database writes for JWT access token sessions are skipped + +### Custom claim name + +You can customize the claim name used to identify stateless tokens: + +```yaml +strategies: + jwt: + stateless: + enabled: true + claim_name: stateless +``` + +With this configuration, JWT access tokens will contain `"stateless": true` instead of the default `"sl": true`. + +## Token format + +When stateless JWT tokens are enabled, the generated JWT access token includes the configured stateless claim as a top-level +boolean claim. + +### Example JWT payload + +```json +{ + "iss": "https://your-hydra-instance.com", + "sub": "user-id", + "aud": ["api-resource"], + "exp": 1735689600, + "iat": 1735686000, + "scope": "openid profile email", + "sl": true +} +``` + +The `sl` claim (or your custom claim name) with a boolean value of `true` identifies this token as stateless. + +## Functional limitations + +Enabling stateless JWT tokens disables certain OAuth2 and OpenID Connect features that require access to persisted token state. + +### Token introspection + +**Endpoint**: `/oauth2/introspect` + +When introspecting a stateless JWT access token, the endpoint returns: + +- **HTTP Status**: 501 Not Implemented +- **Error**: `unsupported_token_type` + +Standard opaque and JWT access tokens (with stateless disabled) continue to support introspection normally. + +### Token revocation + +**Endpoint**: `/oauth2/revoke` + +Attempting to revoke a stateless JWT access token returns: + +- **HTTP Status**: 501 Not Implemented +- **Error**: `unsupported_token_type` + +Since stateless tokens are not persisted in the database, they cannot be revoked. Token expiration is enforced through the JWT +`exp` claim during validation. + +### Userinfo endpoint + +**Endpoint**: `/userinfo` + +Requesting user information with a stateless JWT access token returns: + +- **HTTP Status**: 501 Not Implemented +- **Error**: `unsupported_token_type` + +The userinfo endpoint requires database lookups to retrieve the consent session data associated with the access token, which is +not available for stateless tokens. + +## When to use stateless JWT tokens + +Stateless JWT access tokens are suitable for scenarios where: + +- **High throughput is required**: Applications with high token issuance rates benefit from eliminating database writes +- **Token revocation is not needed**: Workloads that rely solely on JWT expiration for token lifecycle management +- **Introspection is not used**: Resource servers validate tokens using JWT signature verification rather than introspection +- **Userinfo endpoint is not required**: Client applications do not call the userinfo endpoint for user information +- **JWT access tokens are used**: The feature only applies when clients or the global strategy is configured for JWT tokens (not + opaque tokens) + +## When not to use stateless JWT tokens + +Do not enable stateless JWT tokens if your application requires: + +- **Token revocation**: Immediate invalidation of access tokens before expiration +- **Token introspection**: Validating tokens through the introspection endpoint +- **Userinfo endpoint support**: Retrieving user information associated with access tokens +- **Audit trail of active tokens**: Database records of issued tokens for compliance or auditing purposes + +## Performance considerations + +Enabling stateless JWT tokens provides performance benefits by: + +- Eliminating database write operations for access token sessions +- Reducing database connection pool usage during token issuance +- Decreasing storage requirements by not persisting JWT access tokens From 6f689e2a3ff1d82522dcc689ced12697483c3b1d Mon Sep 17 00:00:00 2001 From: shaunn Date: Wed, 26 Nov 2025 11:58:51 -0800 Subject: [PATCH 2/6] docs: oauth2 stateless jwt access tokens - with pr feedback fix --- docs/self-hosted/oel/oauth2/stateless-jwt.mdx | 72 ++++++------------- 1 file changed, 22 insertions(+), 50 deletions(-) diff --git a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx index 73a5a8d5a..8f264c5f3 100644 --- a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx +++ b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx @@ -4,13 +4,14 @@ title: Stateless JWT access tokens sidebar_label: Stateless JWT tokens --- -# Stateless JWT access tokens - This document explains how to configure stateless JWT access tokens in Ory Hydra. When enabled, JWT access tokens are issued as self-contained tokens without persisting them to the database, significantly improving performance for high-throughput workloads. -Stateless JWT access tokens are available only to customers on an Ory Enterprise plan (Ory Enterprise License / Ory Network -Enterprise). If you are interested in this feature, please [contact us](https://www.ory.sh/contact). +```mdx-code-block +import Help from '@site/docs/_common/need-help.mdx' + + +``` ## Overview @@ -23,27 +24,26 @@ tokens are issued as self-contained JWTs with a configurable boolean claim that require token state (introspection, revocation, and userinfo) will return an error for these tokens. This feature applies when either the OAuth2 client is configured to use the JWT access token strategy or the global access token -strategy is set to JWT (instead of opaque). +strategy is set to JWT instead of opaque. ## How it works When stateless JWT tokens are enabled: -1. **Token Generation**: JWT access tokens are issued with an additional boolean claim (default: `sl`) set to `true`. This claim +1. Token Generation: JWT access tokens are issued with an additional boolean claim (default: `sl`) set to `true`. This claim identifies the token as stateless. -2. **No Database Writes**: Access token sessions are not written to the database, eliminating write operations and improving +2. No Database Writes: Access token sessions are not written to the database, eliminating write operations and improving performance. -3. **Stateful Operations Unavailable**: Operations that require token state return HTTP 501 (Not Implemented) with error +3. Stateful Operations Unavailable: Operations that require token state return HTTP 501 (Not Implemented) with error `unsupported_token_type`: - - **Token Introspection** (`/oauth2/introspect`): Returns 501 for stateless JWT tokens - - **Token Revocation** (`/oauth2/revoke`): Returns 501 for stateless JWT tokens - - **Userinfo Endpoint** (`/userinfo`): Returns 501 for stateless JWT tokens + - Token Introspection (`/oauth2/introspect`): Returns 501 for stateless JWT tokens + - Token Revocation (`/oauth2/revoke`): Returns 501 for stateless JWT tokens + - Userinfo Endpoint (`/userinfo`): Returns 501 for stateless JWT tokens -4. **Standard JWT Validation**: Token validation continues to work through standard JWT signature verification and claims - validation. +4. Standard JWT Validation: Token validation continues to work through standard JWT signature verification and claims validation. ## Configuration @@ -113,63 +113,35 @@ Enabling stateless JWT tokens disables certain OAuth2 and OpenID Connect feature ### Token introspection -**Endpoint**: `/oauth2/introspect` +Endpoint: `/oauth2/introspect` When introspecting a stateless JWT access token, the endpoint returns: -- **HTTP Status**: 501 Not Implemented -- **Error**: `unsupported_token_type` +- HTTP Status: 501 Not Implemented +- Error: `unsupported_token_type` Standard opaque and JWT access tokens (with stateless disabled) continue to support introspection normally. ### Token revocation -**Endpoint**: `/oauth2/revoke` +Endpoint: `/oauth2/revoke` Attempting to revoke a stateless JWT access token returns: -- **HTTP Status**: 501 Not Implemented -- **Error**: `unsupported_token_type` +- HTTP Status: 501 Not Implemented +- Error: `unsupported_token_type` Since stateless tokens are not persisted in the database, they cannot be revoked. Token expiration is enforced through the JWT `exp` claim during validation. ### Userinfo endpoint -**Endpoint**: `/userinfo` +Endpoint: `/userinfo` Requesting user information with a stateless JWT access token returns: -- **HTTP Status**: 501 Not Implemented -- **Error**: `unsupported_token_type` +- HTTP Status: 501 Not Implemented +- Error: `unsupported_token_type` The userinfo endpoint requires database lookups to retrieve the consent session data associated with the access token, which is not available for stateless tokens. - -## When to use stateless JWT tokens - -Stateless JWT access tokens are suitable for scenarios where: - -- **High throughput is required**: Applications with high token issuance rates benefit from eliminating database writes -- **Token revocation is not needed**: Workloads that rely solely on JWT expiration for token lifecycle management -- **Introspection is not used**: Resource servers validate tokens using JWT signature verification rather than introspection -- **Userinfo endpoint is not required**: Client applications do not call the userinfo endpoint for user information -- **JWT access tokens are used**: The feature only applies when clients or the global strategy is configured for JWT tokens (not - opaque tokens) - -## When not to use stateless JWT tokens - -Do not enable stateless JWT tokens if your application requires: - -- **Token revocation**: Immediate invalidation of access tokens before expiration -- **Token introspection**: Validating tokens through the introspection endpoint -- **Userinfo endpoint support**: Retrieving user information associated with access tokens -- **Audit trail of active tokens**: Database records of issued tokens for compliance or auditing purposes - -## Performance considerations - -Enabling stateless JWT tokens provides performance benefits by: - -- Eliminating database write operations for access token sessions -- Reducing database connection pool usage during token issuance -- Decreasing storage requirements by not persisting JWT access tokens From 900952ee56c12911884d2ce54140759a287f4e12 Mon Sep 17 00:00:00 2001 From: shaunn Date: Wed, 26 Nov 2025 12:53:27 -0800 Subject: [PATCH 3/6] docs: oauth2 stateless jwt access tokens - with sidebar entry --- src/sidebar.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sidebar.ts b/src/sidebar.ts index 8dd49c751..c5d8afba0 100644 --- a/src/sidebar.ts +++ b/src/sidebar.ts @@ -1236,6 +1236,7 @@ const oel: SidebarItemsConfig = [ "self-hosted/oel/oauth2/upgrade", "self-hosted/oel/oauth2/changelog", "self-hosted/oel/oauth2/token-prefix", + "self-hosted/oel/oauth2/stateless-jwt", "self-hosted/oel/oauth2/migrate-postgresql-ttl", "self-hosted/oel/oauth2/revert-database-migrations", "self-hosted/oel/oauth2/configuration", From abf00e89dd7e31d983ed7be0a44aa239455f135b Mon Sep 17 00:00:00 2001 From: shaunn Date: Wed, 26 Nov 2025 14:41:20 -0800 Subject: [PATCH 4/6] docs: oauth2 stateless jwt access tokens - with more pr feedback fixes --- docs/self-hosted/oel/oauth2/stateless-jwt.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx index 8f264c5f3..21e753c06 100644 --- a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx +++ b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx @@ -109,7 +109,7 @@ The `sl` claim (or your custom claim name) with a boolean value of `true` identi ## Functional limitations -Enabling stateless JWT tokens disables certain OAuth2 and OpenID Connect features that require access to persisted token state. +Enabling stateless JWT tokens disables certain OAuth2 and OpenID Connect features that require access to a persisted token state. ### Token introspection @@ -143,5 +143,4 @@ Requesting user information with a stateless JWT access token returns: - HTTP Status: 501 Not Implemented - Error: `unsupported_token_type` -The userinfo endpoint requires database lookups to retrieve the consent session data associated with the access token, which is -not available for stateless tokens. +The `/userinfo` endpoint requires database lookups to retrieve the consent session data associated with the access token. From e8d867bda6e03e0add02d270af9f83cbcc32608a Mon Sep 17 00:00:00 2001 From: shaunn Date: Mon, 1 Dec 2025 09:16:19 -0800 Subject: [PATCH 5/6] docs: oauth2 stateless jwt access tokens - with 'when to use' points --- docs/self-hosted/oel/oauth2/stateless-jwt.mdx | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx index 21e753c06..82b868c26 100644 --- a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx +++ b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx @@ -144,3 +144,29 @@ Requesting user information with a stateless JWT access token returns: - Error: `unsupported_token_type` The `/userinfo` endpoint requires database lookups to retrieve the consent session data associated with the access token. + +## When to use stateless JWT tokens + +Stateless JWT access tokens are suitable for scenarios where: + +- High throughput is required: Applications with high token issuance rates benefit from eliminating database writes +- Token revocation is not needed: Workloads that rely solely on JWT expiration for token lifecycle management +- Introspection is not used: Resource servers validate tokens using JWT signature verification rather than introspection +- Userinfo endpoint is not required: Client applications do not call the userinfo endpoint for user information +- JWT access tokens are used: The feature only applies when clients or the global strategy is configured for JWT tokens + +## When not to use stateless JWT tokens + +Do not enable stateless JWT tokens if your application requires: + +- Token revocation: Immediate invalidation of access tokens before expiration +- Token introspection: Validating tokens through the introspection endpoint +- Userinfo endpoint support: Retrieving user information associated with access tokens +- Audit trail of active tokens: Database records of issued tokens for compliance or auditing purposes + +## Performance considerations + +Enabling stateless JWT tokens provides performance benefits by: + +- Eliminating database write operations for access token sessions +- Decreasing storage requirements by not persisting JWT access tokens From 375c0425a79c60a3761d1d52cd1db5ab63e10a23 Mon Sep 17 00:00:00 2001 From: Patrik Date: Tue, 2 Dec 2025 09:28:43 +0100 Subject: [PATCH 6/6] Update docs/self-hosted/oel/oauth2/stateless-jwt.mdx --- docs/self-hosted/oel/oauth2/stateless-jwt.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx index 82b868c26..edf681e39 100644 --- a/docs/self-hosted/oel/oauth2/stateless-jwt.mdx +++ b/docs/self-hosted/oel/oauth2/stateless-jwt.mdx @@ -150,7 +150,7 @@ The `/userinfo` endpoint requires database lookups to retrieve the consent sessi Stateless JWT access tokens are suitable for scenarios where: - High throughput is required: Applications with high token issuance rates benefit from eliminating database writes -- Token revocation is not needed: Workloads that rely solely on JWT expiration for token lifecycle management +- Token revocation is not needed: Workloads that rely solely on JWT expiration for token lifecycle management, or have a dedicated mechanism for revoking tokens - Introspection is not used: Resource servers validate tokens using JWT signature verification rather than introspection - Userinfo endpoint is not required: Client applications do not call the userinfo endpoint for user information - JWT access tokens are used: The feature only applies when clients or the global strategy is configured for JWT tokens