Skip to content

Commit 4549329

Browse files
authored
[7.2] Add non-persistent AT docs (#6099)
1 parent f704d11 commit 4549329

1 file changed

Lines changed: 223 additions & 1 deletion

File tree

en/identity-server/7.2.0/docs/deploy/token-persistence.md

Lines changed: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ same application.
4646

4747
The above scenario is unlikely because in practice, an application is usually designed to handle this situation using scopes, or in the case of a multithreaded client, there is usually a separate thread to acquire access tokens so that other threads can retrieve from it.
4848

49-
### Synchronous token persistence
49+
### Synchronous token persistence recovery
5050

5151
The flow of the synchronous token persistence when receiving two identical access token requests is as follows:
5252

@@ -62,3 +62,225 @@ The process flow now moves on to the recovery flow described above to handle the
6262
- Since the same thread is being used, the OAuth2 component in the second node checks the database again for an ACTIVE access token.
6363
- Since there is now an ACTIVE token that was persisted by the first node, the second node now returns the access token persisted by the first node to the client.
6464
- Both access token requests receive the same access token.
65+
66+
## Optimizing JWT access token persistence
67+
68+
By default, JWT access token generation or validation triggers interactions with the database. JWT access token persistence differs from opaque token persistence, where an existing active token is retrieved during a token request. The issuer always issues a new JWT access token. The following sections explain how to optimize the default JWT persistence in Identity Server using **non-persistent access tokens**.
69+
70+
### Why optimize JWT access token persistence?
71+
72+
In large-scale WSO2 Identity Server deployments, especially with millions of users and high concurrency, the number of tokens stored in the database can grow quickly, making it harder to scale. This can lead to reduced performance and lower Transactions Per Second (TPS) for token generation. To address this, token persistence optimization helps by not storing access tokens. This approach avoids storing access tokens during generation while still supporting essential features like token revocation and refresh grants, improving scalability and performance.
73+
74+
- **Reduce database queries during token request**: When a token is issued, both the **access token** and **refresh token** will no longer be stored in the `IDN_OAUTH2_ACCESS_TOKEN` table (if both access token persistence and refresh token persistence are disabled). As a result, authorization grants like **Client Credentials**, which do not issue a refresh token, will experience improved throughput due to the reduction in database query overhead.
75+
- **Efficient database storage**: When tokens are stored in the persistent access token mode, new entries are added to the database with each token request, even if the same refresh token is used. However, with the **non-persistent access token** feature enabled, only the **refresh token** is stored (if refresh token persistence is enabled). If the current refresh token is still valid for the grant, no additional database rows will be added during token requests, leading to more efficient database storage.
76+
- **Improved token validation**: With the **non-persistent access token** feature enabled, revoked tokens can be stored in the database. However, deployments have the option to opt out of storing revoked tokens and can instead listen for revoked token events, providing greater flexibility in token management. This approach is particularly beneficial when the Identity Server acts as a **Key Manager** for **WSO2 API Manager**, as the Gateway can self-validate JWTs without additional hops to the Key Manager, improving performance and reducing latency.
77+
78+
### Things to consider when using JWT access token persistence optimization
79+
80+
- This mode is particularly suitable for the following scenarios:
81+
- When most token requests are based on authorization grants such as **Client Credentials**, which do not issue a refresh token.
82+
- When **Refresh Token Grants** are configured **without refresh token rotation**, reducing the need for persistent token tracking.
83+
- The **token persistence optimization** feature works only with **JWT access tokens**, as they can be self-validated.
84+
- When enabling this feature in an existing setup:
85+
- **Opaque token generation** will continue to work as expected for applications configured to use opaque tokens.
86+
- Applications configured for **JWT access token type** will be switched to **non-persistent access token mode**, meaning JWT access tokens will no longer be stored in the database.
87+
- In the case of persistent token storage, if an active access token already exists during the token generation flow, the existing token will be marked as inactive. However, in the non-persistent mode, multiple active tokens can exist, as the authorization server does not store the access tokens.
88+
- **Token binding**, **Retrieving authorized apps for user**,**Rich Authorization Details**, and **OIDC Request Object** features are currently not supported in **non-persistent access token mode**.
89+
- Actions like revoking issued access tokens when re-submitting an authorization code and revoking all issued access tokens when revoking refresh tokens are also not supported, because the Identity Server does not store access tokens in this mode.
90+
- In non-persistent mode, the cleanup deletes the selected entries; they are not moved to an audit table as in the persistent case.
91+
92+
- Following are the additional claims that will be added to the JWT access token for internal references.
93+
94+
<table>
95+
<thead>
96+
<tr class="header">
97+
<th>Claims</th>
98+
<th>Description</th>
99+
</tr>
100+
</thead>
101+
<tbody>
102+
<tr class="odd">
103+
<td><code>entity_id</code></td>
104+
<td>
105+
<p>Unique identifier for the subject within the system.</p>
106+
<p> - For application: Client Id.</p>
107+
<p> - For Users from unique Id user store: User Unique Id.</p>
108+
<p> - For Users from non-unique Id user store: Username with userstore domain and tenant domain.</p>
109+
<p> - For non-JIT provisioned federated Users: Session Id.</p>
110+
</td>
111+
</tr>
112+
<tr class="even">
113+
<td><code>entityType</code></td>
114+
<td>
115+
<p>Type of entity id.</p>
116+
<p> - For application: CLIENT_ID.</p>
117+
<p> - For Users from unique Id user store: USER_ID.</p>
118+
<p> - For Users from non-unique Id user store: USER_NAME.</p>
119+
</td>
120+
</tr>
121+
<tr class="odd">
122+
<td><code>is_federated</code></td>
123+
<td>
124+
<p>Flag to show whether the user is federated or not.</p>
125+
</td>
126+
</tr>
127+
<tr class="even">
128+
<td><code>token_id</code></td>
129+
<td>
130+
<p>Token ID for internal reference.</p>
131+
</td>
132+
</tr>
133+
<tr class="odd">
134+
<td><code>is_consented</code></td>
135+
<td>
136+
<p>Flag to show whether the user has consented to share claims.</p>
137+
</td>
138+
</tr>
139+
<tr class="odd">
140+
<td><code>grantType</code></td>
141+
<td>
142+
<p>Grant type.</p>
143+
</td>
144+
</tr>
145+
<tr class="even">
146+
<td><code>accessing_organization</code></td>
147+
<td>
148+
<p>Organization ID of the application (SaaS scenarios).</p>
149+
</td>
150+
</tr>
151+
</tbody>
152+
</table>
153+
154+
### Enable JWT access token persistence optimization
155+
156+
!!! note "Custom JWT Token Issuer"
157+
If you already use a custom JWT token issuer that extends
158+
[`JWTTokenIssuer`](https://github.com/wso2-extensions/identity-inbound-auth-oauth/blob/master/components/org.wso2.carbon.identity.oauth/src/main/java/org/wso2/carbon/identity/oauth2/token/JWTTokenIssuer.java),
159+
add the **setClaimsForNonPersistence** call **inside `createJWTClaimSet(...)` just before you return the JWT claim set**.
160+
This injects the non-persistence–related claims.
161+
162+
```java
163+
@Override
164+
protected JWTClaimsSet createJWTClaimSet(
165+
OAuthAuthzReqMessageContext authAuthzReqMessageContext,
166+
OAuthTokenReqMessageContext tokenReqMessageContext,
167+
String consumerKey) throws IdentityOAuth2Exception {
168+
169+
// ... set your standard logic here ...
170+
171+
// Add non-persistence claims BEFORE returning:
172+
setClaimsForNonPersistence(jwtClaimsSetBuilder, authAuthzReqMessageContext,
173+
tokenReqMessageContext, authenticatedUser, oAuthAppDO);
174+
175+
return jwtClaimsSetBuilder.build();
176+
}
177+
178+
```
179+
180+
Add the following configuration to the `deployment.toml` file to enable the feature in WSO2 Identity Server.
181+
182+
```toml
183+
[oauth.token_persistence]
184+
persist_access_token = false
185+
retain_revoked_token = true
186+
persist_refresh_token = false
187+
```
188+
189+
!!! Tip
190+
If you have a long-living refresh token with refresh token rotation, it is recommended to store the refresh token. The following configuration can be used to enable refresh token persistence while keeping the access token as non-persistent.
191+
```toml
192+
[oauth.token_persistence]
193+
persist_access_token = false
194+
persist_refresh_token = true
195+
```
196+
197+
!!! Tip
198+
If you don't want the Identity Server to store revoked tokens and details related to revoked subjects, you can disable this by updating the following configuration.
199+
```toml
200+
[oauth.token_persistence]
201+
retain_revoked_token = false
202+
```
203+
204+
### Removing unused refresh tokens and revoke entries from the database
205+
206+
!!! note
207+
This section applies to database cleanup when the non-persistent access token feature is enabled. For persistent mode, refer to [Clean unused tokens from database](../../setup/removing-unused-tokens-from-the-database).
208+
209+
As you continue to use **WSO2 Identity Server (WSO2 IS)**, the number of **revoked**, **inactive**, and **expired** tokens increases in the `IDN_OAUTH2_REFRESH_TOKEN` table. When a token is revoked, a record is also added to the `IDN_OAUTH2_REVOKED_TOKENS` table. These tokens are retained for purposes such as **logging**, **auditing**, and **validation**.
210+
211+
However, over time, the accumulation of such records can impact overall server performance and increase the size of the database. To ensure optimal performance, it is recommended to periodically clean up unused and expired tokens.
212+
213+
The following sections guide you through the different ways to perform cleanup and how to configure them.
214+
215+
- [**Token Cleanup via Stored Procedure** (Recommended)](#token-cleanup-via-stored-procedure)
216+
- [**Configuring WSO2 Identity Server for token cleanup**](#configuring-wso2-identity-server-for-token-cleanup)
217+
218+
#### Token cleanup via stored procedure
219+
220+
You can use the provided stored procedures to run a
221+
token cleanup task periodically to remove the old and invalid tokens and clean up the `IDN_OAUTH2_REVOKED_TOKENS` table.
222+
Follow the instructions below to configure token cleanup using this
223+
method.
224+
225+
!!! tip
226+
It is safe to run these steps in read-only mode or during a time when traffic on the server is low, but that is not mandatory.
227+
228+
1. **Disable Internal Token Cleanup**
229+
Update the `deployment.toml` file located in `<IS_HOME>/repository/conf`:
230+
231+
```toml
232+
[oauth.token_cleanup]
233+
enable = false
234+
```
235+
236+
2. **Run the Cleanup Script**
237+
Select the appropriate SQL script based on your database type and execute it.
238+
239+
- [MySQL Stored Procedure Script](https://github.com/wso2/carbon-identity-framework/blob/master/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/stored-procedures/mysql/non-persistence-access-token-cleanup/)
240+
241+
- [Oracle Stored Procedure Script](https://github.com/wso2/carbon-identity-framework/blob/master/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/stored-procedures/oracle/non-persistence-access-token-cleanup/)
242+
243+
This script:
244+
245+
- Backs up token-related tables (if enabled)
246+
- Deletes eligible expired, revoked, or inactive entries
247+
248+
3. **Restart the Server**
249+
Once cleanup is complete, restart **WSO2 Identity Server** with the updated and cleaned database. You can optionally **schedule periodic execution** of the cleanup procedure.
250+
251+
#### Configuring WSO2 Identity Server for token cleanup
252+
253+
You can also configure **WSO2 Identity Server** to trigger **refresh token cleanup** during the following events:
254+
255+
1. **On token refresh**: When issuing a new refresh token
256+
2. **On token revocation**: When a refresh token is explicitly revoked
257+
3. **User revoke events**: This includes events like **user deletion**, **user lockout**, or **user role deletion**.
258+
4. **Application revoke events**: This includes **application credentials revocation** or **application deletion**.
259+
260+
!!! warning "Manual cleanup required for IDN_OAUTH2_REVOKED_TOKENS and IDN_SUBJECT_ENTITY_REVOKED_EVENT"
261+
The tables `IDN_OAUTH2_REVOKED_TOKENS` and `IDN_SUBJECT_ENTITY_REVOKED_EVENT` do not have an automatic cleanup procedure by default. You must **manually implement** cleanup scripts for these tables to avoid database bloat and maintain performance.
262+
263+
Enable token cleanup by configuring the following properties in the `deployment.toml` file found in the `<IS_HOME>/repository/conf` folder.
264+
265+
```toml
266+
[oauth.token_cleanup]
267+
enable = true
268+
```
269+
270+
<table>
271+
<thead>
272+
<tr class="header">
273+
<th>Property</th>
274+
<th>Description</th>
275+
</tr>
276+
</thead>
277+
<tbody>
278+
<tr class="odd">
279+
<td><code>enable</code></td>
280+
<td>
281+
<p>Set this property to <code>true</code> to enable refresh token cleanup.</p>
282+
<p>Set it to <code>false</code> to disable token cleanup.</p>
283+
</td>
284+
</tr>
285+
</tbody>
286+
</table>

0 commit comments

Comments
 (0)