Skip to content
3 changes: 2 additions & 1 deletion main/config/navigation/authenticate.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@
]
},
"docs/authenticate/enterprise-connections/private-key-jwt-client-auth",
"docs/authenticate/enterprise-connections/enable-dpop-enterprise-connections"
"docs/authenticate/enterprise-connections/enable-dpop-enterprise-connections",
"docs/authenticate/enterprise-connections/session-expiry-enterprise-connections"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
---
title: Configure Session Expiry for Enterprise Connections (IPSIE)
Comment thread
avanscoy marked this conversation as resolved.
description: Learn how to enforce upstream Identity Provider session expiry using the IPSIE `session_expiry` claim for Okta and OIDC Enterprise connections.
validatedOn: 2026-06-25
---

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">

Session Expiry is supported for Okta and OIDC Enterprise connections and is not available for Microsoft Entra ID (Azure AD) connections. Microsoft does not include the `session_expiry` claim in Entra ID Tokens.

</Callout>

Auth0 supports the `session_expiry` claim based on the [Interoperability Profile for Secure Identity in the Enterprise (IPSIE) standard](https://openid.net/specs/ipsie-openid-connect-sl1-profile-1_0.html) for Okta and OIDC Enterprise connections. When enabled, Auth0 captures the `session_expiry` (represented in seconds as a Unix timestamp) from the upstream Identity Provider (IdP) and includes it in the ID Token issued to your application.

Auth0 consumes the `session_expiry` claim and synchronizes the local Auth0 session with the upstream IdP's session lifecycle. This ensures when a user's session expires at the Enterprise IdP, their Auth0 session also terminates.

<Warning>
Comment thread
avanscoy marked this conversation as resolved.
The customer is responsible for processing the received `session_expiry` claim and to terminate and manage user sessions in their applications.
</Warning>
Comment thread
avanscoy marked this conversation as resolved.

Comment thread
avanscoy marked this conversation as resolved.
<Card title="Before you start">

Before enabling session expiry enforcement:

* You must have an existing [Okta](/docs/authenticate/identity-providers/enterprise-identity-providers/okta/express-configuration) or [OIDC](/docs/authenticate/identity-providers/enterprise-identity-providers/oidc) Enterprise connection.
* The upstream identity provider must emit a `session_expiry` claim in its ID Token.

</Card>

## How it works

When a user authenticates through a `session_expiry`-enabled Enterprise connection, Auth0:
Comment thread
avanscoy marked this conversation as resolved.
Outdated

1. Captures the `session_expiry` claim from the upstream IdP's ID Token.
2. Calculates session expiration by evaluating specific parameters and sets the final Auth0 sessions expiration to the minimum (earliest) value of the following factors:
Comment thread
avanscoy marked this conversation as resolved.
Outdated
* The IdP `session_expiry` claim: The absolute timestamp in an ID Token from the upstream Identity Provider.
* Your Auth0 tenant's default Absolute Expiration setting: The session lifetime limit you configure in Auth0 Dashboard or Management API. To learn more, read [Configure Session Lifetime Settings](/docs/manage-users/sessions/configure-session-lifetime-settings).
* Auth0 Actions [`setExpiresAt`]: Any custom expiration timestamp programmatically set during the login transaction with the Post-Login Action [`api.session.setExpiresAt()`](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-api-object#api-session-setexpiresat-absolute) method.
3. Uses a Post-Login Action you configure during enablement to pass the final evaluated session expiration to your application by injecting it as a [custom claim](/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-api-object#api-idtoken-setcustomclaim-key-value) into the Auth0-issued ID Token.

The `session_expiry` claim is a [UNIX timestamp](https://en.wikipedia.org/wiki/Unix_time) in seconds representing the absolute expiration limit for the user's session:

```json
{
"iss": "https://YOUR_DOMAIN.auth0.com/",
"aud": "YOUR_CLIENT_ID",
"sub": "oidc|username@domain.com",
"iat": 1748534400,
"exp": 1748538000,
"session_expiry": 1748566800
}
```

| Claim | What it represents | Scope |
| --- | --- | --- |
| `exp` | ID Token lifetime (typically minutes) | Token validation |
| `session_expiry` | Absolute expiration (seconds) | Session management |

The `session_expiry` claim is not a replacement for `exp`. The ID Token's own `exp` remains short-lived and unchanged. `session_expiry` is a session-level limit included with the token claims.

**`session_expiry` is fixed at login.** It is set once when the user authenticates and is not updated when tokens are refreshed. A user already logged in before this feature is enabled will not have `session_expiry` on their existing session; the claim only appears after their next login.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">

This feature addresses scheduled session expiry only. For real-time session revocation, like when a user is off-boarded mid-session, we recommend you use [Back-Channel Logout](/docs/authenticate/login/logout/back-channel-logout).

</Callout>

## Enable session expiry enforcement

Configure session expiry enforcement on your Enterprise connection using the Auth0 Dashboard or Management API.

<Tabs>
<Tab title="Auth0 Dashboard">

1. Navigate to [**Authentication > Enterprise**](https://manage.auth0.com/#/connections/enterprise) in the Auth0 Dashboard.
2. Select the Okta or OIDC Enterprise connection you want to configure.
Comment thread
avanscoy marked this conversation as resolved.
Outdated
3. Select the **Settings** tab.
4. Enable **Use ID Token for Session Expiry**.
5. Select **Save**.

</Tab>
<Tab title="Management API">

To use the Management API, you need a [Management API access token](/docs/secure/tokens/access-tokens/management-api-access-tokens) with `update:connections` scope.

Make a `PATCH` request to the [Update a connection](https://auth0.com/docs/api/management/v2/connections/patch-connections-by-id) endpoint:

```http
PATCH https://YOUR_DOMAIN/api/v2/connections/YOUR_CONNECTION_ID
Content-Type: application/json
Authorization: Bearer YOUR_MANAGEMENT_API_TOKEN

{
"options": {
"id_token_session_expiry_supported": true
}
}
```

Replace the placeholder values:

* **`YOUR_DOMAIN`**: Your Auth0 tenant domain. Example: `travel0.us.auth0.com`.
* **`YOUR_CONNECTION_ID`**: The ID of your Okta or OIDC Enterprise connection.
* **`YOUR_MANAGEMENT_API_TOKEN`**: A Management API token with `update:connections` scope.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">

If you `PATCH` the `options` parameter, the entire `options` object is overridden. Ensure all existing properties are included when you `PATCH` `options`.

</Callout>

</Tab>
</Tabs>

## Send session expiration to your application

While Auth0 uses the calculated session expiration to manage its own session layer, your downstream applications may also need to know this absolute expiration time to enforce local session limits. Configure a Post-Login Action to inject the final, evaluated session expiration in an Auth0-issued ID Token and pass the token to your application.

<Tabs>
<Tab title="Auth0 Dashboard">

1. Navigate to [**Actions > Library**](https://manage.auth0.com/#/actions/library) in the Auth0 Dashboard and select **Build Custom**.
2. Enter a name for the Action, select **Login / Post Login** as the trigger, and select **Create**.
3. Add the following code to your Action:

```javascript
exports.onExecutePostLogin = async (event, api) => {
// Check if a session expiration has been established
if (event.session?.expires_at) {
// Convert the ISO string date to a Date object
const exp_date = new Date(event.session.expires_at);
// Set the session_expiry custom claim as a Unix timestamp (seconds)
api.idToken.setCustomClaim('session_expiry', Math.floor((exp_date.getTime()) / 1000));
}
};
```

4. Under the Test panel, select **Run** and review results.
5. Select **Deploy**.
6. Navigate to [**Actions > Flows**](https://manage.auth0.com/#/actions/flows) and select **Login**.
Comment thread
avanscoy marked this conversation as resolved.
Outdated
7. In the **Add Action** panel, locate your Action and drag it into the Login flow. Select **Apply**.

</Tab>
<Tab title="Management API">

Configuring the Action via the Management API requires three steps: create the Action, deploy it, then bind it to the Login trigger. You need a [Management API access token](/docs/secure/tokens/access-tokens/management-api-access-tokens) with `create:actions`, `read:actions`, and `update:actions` scopes.

### Create the Action

1. Make a `POST` request to the [Create an action](https://auth0.com/docs/api/management/v2/actions/post-action) endpoint:

```http
POST https://YOUR_DOMAIN/api/v2/actions/actions
Content-Type: application/json
Authorization: Bearer YOUR_MANAGEMENT_API_TOKEN

{
"name": "Set session_expiry claim",
"supported_triggers": [
{ "id": "post-login" }
],
"code": "exports.onExecutePostLogin = async (event, api) => {\n if (event.session?.expires_at) {\n const exp_date = new Date(event.session.expires_at);\n api.idToken.setCustomClaim('session_expiry', Math.floor((exp_date.getTime()) / 1000));\n }\n};"
}
```

Note the `id` value in the response since you need it in the following steps.

### Deploy the Action

1. Make a `POST` request to the [Deploy an action](https://auth0.com/docs/api/management/v2/actions/post-deploy-action) endpoint:

```http
POST https://YOUR_DOMAIN/api/v2/actions/actions/YOUR_ACTION_ID/deploy
Authorization: Bearer YOUR_MANAGEMENT_API_TOKEN
```

### Bind the Action to the Login trigger

1. Make a `PATCH` request to the [Update trigger bindings](https://auth0.com/docs/api/management/v2/actions/patch-bindings) endpoint:

```http
PATCH https://YOUR_DOMAIN/api/v2/actions/triggers/post-login/bindings
Content-Type: application/json
Authorization: Bearer YOUR_MANAGEMENT_API_TOKEN

{
"bindings": [
{
"ref": {
"type": "action_id",
"value": "YOUR_ACTION_ID"
},
"display_name": "Set session_expiry claim"
}
]
}
```

<Callout icon="triangle-exclamation" color="#F59E0B" iconType="regular">

The `PATCH /api/v2/actions/triggers/post-login/bindings` request replaces all existing bindings. To preserve existing Actions in your Login flow, first retrieve your current bindings with `GET /api/v2/actions/triggers/post-login/bindings`, then include those bindings alongside the new one in your `PATCH` request.

</Callout>

Replace the placeholder values:

* **`YOUR_DOMAIN`**: Your Auth0 tenant domain. Example: `travel0.us.auth0.com`.
* **`YOUR_MANAGEMENT_API_TOKEN`**: A Management API token with `create:actions`, `read:actions`, and `update:actions` scopes.
* **`YOUR_ACTION_ID`**: The `id` returned in the Create Action response.

</Tab>
</Tabs>

## Use session expiry with Auth0 SDKs

If you use [Auth0 SDKs](/docs/libraries) and have configured the Post-Login Action described above, session expiry is enforced automatically. The SDK reads `session_expiry` from the ID Token at login, persists it with the session, and treats the session as expired once the current time reaches or passes `session_expiry`:

| SDK type | How expiry is enforced |
| --- | --- |
| **Regular Web App** (Next.js, Express, Python) | Middleware clears the session and redirects with `prompt=login`; `getAccessToken()` throws `SessionExpiredError` |
| **Single-Page App** (React, Angular, Vue) | `getTokenSilently()` / `getAccessTokenSilently()` rejects and triggers re-login with `prompt=login` |
| **Mobile** (iOS/Swift, Android/Kotlin) | `CredentialsManager.credentials()` returns `noCredentials` and the app's existing login path handles re-authentication |

The Post-Login Action is required to inject the `session_expiry` claim into the ID Token. Once set, when a session expires, the SDK behaves the same as any other session expiry: the user is redirected to log in. No additional error handling is required.

## Add session expiry values to your application

An optional step is to add session expiration values to your application. For example, your application can read `session_expiry` to show users a session-expiring warning or you can bind your application's own session lifetime to the upstream IdP's value.

<Tabs>
<Tab title="Single-Page App">

```javascript
const claims = await auth0.getIdTokenClaims();
const sessionExpiresAt = claims?.session_expiry; // Unix seconds
const remainingSeconds = sessionExpiresAt - Math.floor(Date.now() / 1000);
```

</Tab>
<Tab title="Regular Web App">

```javascript
const session = await auth0.getSession();
const sessionExpiresAt = session?.sessionExpiresAt; // top-level field, Unix seconds
const remainingSeconds = (sessionExpiresAt ?? Infinity) - Math.floor(Date.now() / 1000);
```

</Tab>
<Tab title="Mobile (Swift)">

```swift
credentialsManager.credentials { result in
switch result {
case .success(let credentials):
let sessionExpiresAt = credentials.idToken?.session_expiry // Unix seconds
case .failure:
startLogin()
}
}
```

</Tab>
</Tabs>

Do not persist the `session_expiry` value in a long-lived store, such as a cookie or `localStorage`, without re-validating it on each read. The value is only meaningful relative to the current wall-clock time.

## Verify in tenant logs

After enabling session expiry enforcement, verify session expiry is working by checking [tenant logs](/docs/deploy-monitor/logs).

Navigate to [**Auth0 Dashboard > Monitoring > Logs**](https://manage.auth0.com/#/logs) and look for a successful login (`s`) event for a user authenticating through the configured Enterprise connection. When the upstream IdP's `session_expiry` is less than or equal to your tenant's configured absolute session lifetime, the log entry includes the `idp_session_expiry` field (a Unix timestamp in seconds):

```json
{
"type": "s",
"description": "Success Login",
"details": {
"idp_session_expiry": 1782472241
}
}
```

If the IdP did not send a `session_expiry` claim and you enable the feature, login fails with an error message: `The upstream Identity Provider did not return a session_expiry claim`.

## Disable session expiry enforcement

<Tabs>
<Tab title="Auth0 Dashboard">

1. Navigate to [**Authentication > Enterprise**](https://manage.auth0.com/#/connections/enterprise) in the Auth0 Dashboard.
2. Select the connection you want to configure.
3. Select the **Settings** tab.
4. Disable **Use ID Token for Session Expiry**.
5. Select **Save**.

</Tab>
<Tab title="Management API">

Set `id_token_session_expiry_supported` to `false` in your connection options:

```http
PATCH https://YOUR_DOMAIN/api/v2/connections/YOUR_CONNECTION_ID
Content-Type: application/json
Authorization: Bearer YOUR_MANAGEMENT_API_TOKEN

{
"options": {
"id_token_session_expiry_supported": false
}
}
```

</Tab>
</Tabs>

## Learn more

* [Session Lifecycle](/docs/manage-users/sessions/session-lifecycle)
* [Configure Session Lifetime](/docs/manage-users/sessions/configure-session-lifetime)
* [Sessions with Actions](/docs/manage-users/sessions/manage-sessions-actions)
* [Back-Channel Logout](/docs/authenticate/login/logout/back-channel-logout)
* [IPSIE SL1 OpenID Connect Profile](https://openid.net/specs/ipsie-openid-connect-sl1-profile-1_0.html)
6 changes: 6 additions & 0 deletions main/docs/manage-users/sessions/session-lifecycle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ Session lifetime has the following limits:
| Persistent | Inactivity timeout | Timeframe after which a session expires if there’s no interaction with the Authorization Server | 3 days | 100 days |
| | Require Login after | Maximum session lifetime, regardless of activity | 30 days | 365 days |

## Session expiry from upstream identity providers

When using Okta or OIDC enterprise connections, you can enforce the session lifetime asserted by the upstream identity provider. Auth0 captures the `session_expiry` claim from the upstream IdP's ID token and uses it as an upper bound on the user's session — ensuring Auth0 sessions cannot outlive the IdP session that created them.

To learn more, read [Configure Session Expiry for Enterprise Connections (IPSIE)](/docs/authenticate/enterprise-connections/session-expiry-enterprise-connections).

## Next steps

* To learn more about using Actions to configure the session lifecycle, read [Sessions with Actions](/docs/manage-users/sessions/manage-sessions-actions).
Expand Down
Loading