> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/security/session-management/session-management-reference.md).

# What an OpenIAM session is, and what ends one

Where an OpenIAM session lives, the cookie and its flags, the two timeouts and their shipped values, and exactly what a termination does and does not invalidate.

## What this covers

This is OpenIAM's **session management** surface: what a session is, how long it lives, and what ends one.

The model behind [Terminate a user's sessions](/administration-guide/security/session-management.md): the three things a signed-in browser actually is, the cookie and its fixed properties, the five things that end a session — two of which are settings — and the matrix of what a termination reaches. Read it when a security review asks how long a signed-in browser stays signed in, or when a termination did not have the effect you expected.

## A session is two rows and one cookie

There is no session object in the Webconsole to open. A signed-in browser is three things that have to agree:

| Part                 | Where                                                          | What it holds                                                                                                                                                                    |
| -------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The session record   | `AUTH_STATE`, keyed on `USER_ID` **and** `SESSION_ID` together | `AUTH_STATE` — `1` active, `0` revoked — plus `LAST_LOGIN`, `IP_ADDRESS`, `CONTENT_PROVIDER_ID` and `IS_NEW_FLAGS`                                                               |
| The token record     | `OAUTH_TOKEN`                                                  | `TOKEN`, `REFRESH_TOKEN`, `ID_TOKEN`, `EXPIRED_ON`, `CREATED_ON`, `PROVIDER_ID`, `USER_ID`, `GRAND_FLOW` and the `SESSION_ID` tying it to the row above                          |
| The browser's cookie | The user's browser                                             | An encrypted value carrying the user id, the token, the token's expiry, the cookie's creation time, and the **list of authentication levels this session has already satisfied** |

The token inside the cookie decrypts to three fields — user id, expiry timestamp, session id — and OpenIAM accepts it only when all three of these hold: it decrypts, the expiry is in the future, and the `AUTH_STATE` row for that user and session id still reads `1`. That last condition is what makes administrative termination work: flipping the row to `0` invalidates every copy of the cookie immediately, without needing to reach the browser.

An `OAUTH_TOKEN` row whose `SESSION_ID` is empty is a machine-to-machine token — a client-credentials grant with no browser behind it. Those are sessions too, and they are the ones people forget when a whole-estate clear goes through.

{% hint style="info" %}
**The servlet HTTP session is a different thing.** Each UI service also keeps an ordinary web session for the browser, and a few things live only there: the list of SAML partners this browser has been sent to (which is what single logout walks), the freshly generated TOTP secret during enrolment, and the help-desk confirmation. That session has its own lifetime, is not listed by anything on these pages, and does not survive the browser being closed. When single logout misses a service provider, this is usually why.
{% endhint %}

## The session cookie and its properties

| Property   | Value                                                                                                                                                                                                                                         |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Name       | The content provider's **Auth Cookie Name**, else `OPENIAM_AUTH_TOKEN`. When the `OPENIAM_CURRENT_USER_ID` cookie is present, the user id is **appended to the name** — so a cookie called `OPENIAM_AUTH_TOKEN3000` is normal, not corruption |
| Path       | `/`                                                                                                                                                                                                                                           |
| Domain     | The content provider's **Auth Cookie Domain**, else the host of the request                                                                                                                                                                   |
| `HttpOnly` | Always set                                                                                                                                                                                                                                    |
| `Secure`   | Set only when the request reached the service as `https`. Behind a TLS-terminating proxy this depends on the forwarded-protocol headers arriving intact                                                                                       |
| `Max-Age`  | Not set: it is a **session cookie**, discarded when the browser closes. Closing the browser does not revoke the server-side rows                                                                                                              |
| Value      | Encrypted while `org.openiam.ui.auth.cookie.encryption.enabled` is `true`, which is what ships                                                                                                                                                |

Two companion cookies travel with it, both `HttpOnly` and both on path `/`: `OPENIAM_CURRENT_USER_ID`, which is what appends the id to the cookie name and makes several accounts usable in one browser, and `OPENIAM_SESSION_ID_COOKIE`, which carries the session id for the gateway.

Read your own cookie name and domain on the content provider at `/webconsole/editContentProvider?providerId=<CP_ID>`; everything else in that table is fixed and has no field or property behind it. You can confirm the flags directly in the browser's cookie inspector, which is the only place they are visible.

## What ends a session

Five things, and only two of them are settings.

### Idle timeout: `TOKEN_LIFE`, thirty minutes, a sliding window

The token's expiry is set to the moment it was issued plus **`TOKEN_LIFE` minutes**. `TOKEN_LIFE` is parameter `159` on the authentication policy, it ships **`30`** on policy `4001`, and the unit is minutes. Read it on **Policy → Authentication Policy**, field **SSO Token Type Life**. A blank or non-numeric value falls back to `30` and says so in the ESB log: *"Property %s not valid for policy key %s for policy %s. Defaulting to %s"*.

It behaves as an **idle** timeout rather than a fixed one, because every request that reaches a UI service directly renews the token — same session id, same approved-level list, new expiry thirty minutes out. So the session ends thirty minutes after the *last* request, not thirty minutes after sign-in.

Which policy supplies the number is resolved from the request: the matched URI pattern's content provider, that provider's authentication provider, and that provider's **Authentication policy**. Where none of those resolve, the default authentication provider's policy is used. Two content providers pointing at two authentication providers can therefore run two different idle timeouts, and there is no single screen that shows you which one a given path gets — open the content provider, follow it to its authentication provider, and read the policy named there.

Through the Access Gateway the module owns the cookie and the UI hands it back unchanged, logging `Is proxy request - using cookie from proxy` in the UI service log. Renewal, and what a client that makes no requests needs from you, are covered in [Session lifetime and renewal](/administration-guide/gateway/access-gateway-reference.md#session-lifetime-and-renewing-the-session-cookie).

### Absolute lifetime: Max Active Session Time, and only for OAuth

**Max Active Session Time (minutes)** is an attribute of an **OAuth Client** authentication provider, optional, with no shipped default, added as of 2026.2.1.0. Its own description reads *"Maximum active session time in minutes for OAuth tokens (optional)"*, and the field help calls it the maximum time a session may stay active since initial authentication regardless of refresh-token use. Set it on **Access Control → Authentication Providers →** the OAuth client. Empty or `0` disables the check.

Two things to be honest about before you rely on it as a hard cap.

It only applies where an OAuth client is in the picture. A plain browser session on a content provider with no OAuth client attached is governed by the idle timeout alone. **There is no estate-wide absolute session lifetime setting in OpenIAM, and no system property for one** — this is the only absolute cap the product has, and nothing in **Administration → System Configuration** reports it.

And the timestamp it measures from is rewritten in normal operation: the stored token's creation time is set again when a new access token is issued onto the same row, and the browser cookie's creation time is set again each time the cookie is renewed. The practical effect on your release may therefore be a cap on time since the last token issue rather than time since first sign-in. This cannot be confirmed from the Webconsole. Measure it: set the value to `2`, sign in, keep clicking, and see whether you are bounced to the login page after two minutes or not at all. Record what you observe, and ask OpenIAM support if a control statement depends on it.

### Sign-out

Signing out through `/idp/logout` clears the auth cookie and the session-id cookie, revokes the OAuth token the cookie carries, chains SAML single logout if this browser has any SAML partner recorded, and asks the ESB to revoke the session. It is audited `LOGOUT`, with a child `REVOKE_OAUTH_TOKEN` event; the parent event carries either *"oAuth Token was revoked during logout."* or *"oAuth Token was not revoked during logout."*, which is the fastest way to tell whether the token half happened. Where `org.openiam.custom.redirect.logout.redirect` holds a URL — it ships empty, category `CustomRedirect` — the browser lands there afterwards.

{% hint style="danger" %}
**Do not switch on Global Logout on a content provider.** `CONTENT_PROVIDER.IS_GLOBAL_LOGOUT_SUPPORT` ships `'N'` and should stay that way on the current release. When it is on, a sign-out that does not name a specific session takes a different path — and that path reads the user's session rows for the content provider and writes them back **unchanged**. The sessions stay active, their OAuth tokens are not deleted, and only the browser's cookie is cleared. The user looks signed out; anyone holding a copy of that cookie is still signed in.

Prove it on your own system with a test identity: turn **Global Logout** on, sign in, sign out, then read the session record back. The read-only confirmation is `SELECT AUTH_STATE FROM AUTH_STATE WHERE USER_ID = '<user>'` — `1` after sign-out means the session survived. Turn the flag off, repeat, and the same query returns `0`.

Per-session revocation from **My Sessions** is *not* affected, because it names the session id explicitly. Leave the flag off, and report the behaviour to OpenIAM support as a defect rather than working around it.
{% endhint %}

### The user's account stops being usable

This is the one people miss, and it is often the right answer. Renewal re-checks the identity's status on every request, and refuses to renew for a user whose status is `DEACTIVATED`, `INACTIVE`, `LEAVE`, `LEAVE_WITH_PAY`, `LEAVE_OF_ABSENCE`, `TERMINATED` or `DECEASED`, or whose secondary status is `DISABLED`, `LOCKED` or `LOCKED_ADMIN`. The ESB log records *"RenewToken: user status failed for userId = %s"*.

So **disabling or locking a user ends their live sessions at their next request**, through the supported Webconsole path, with an audit trail — no ESB endpoint required.

### Concurrency: one more session evicts the oldest

`org.openiam.session.max.concurrent` ships **`0`**, meaning unlimited. Above `0`, a successful authentication counts the user's active sessions and evicts the oldest by last-login until the count fits — setting each evicted row's state to revoked and deleting that session's OAuth tokens. The ESB log line is *"Max concurrent sessions ({}) reached for user {}. Evicted oldest session: {}"*. Read the current value in the `Authentication` category of **Administration → System Configuration**.

### An administrator ends it

What an administrator can actually do, narrowest first — and what the console offers no path to — is on [Terminate a user's sessions](/administration-guide/security/session-management.md#the-ways-a-session-ends-narrowest-first).

## What termination does, and does not, invalidate

| Thing                                                                 | Revoke one session                                                                                                | Clear all sessions                       | User signs out                                                                    |
| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------- |
| The `AUTH_STATE` record                                               | Set to revoked                                                                                                    | Every active record set to revoked       | Set to revoked — **unless Global Logout is on**                                   |
| The OAuth access and refresh tokens bound to that session             | Deleted                                                                                                           | Deleted                                  | Revoked, and the outcome is stated in the `LOGOUT` audit event                    |
| Machine-to-machine tokens with no session id                          | Untouched                                                                                                         | **Deleted** — every unexpired token goes | Untouched                                                                         |
| The browser's copy of the cookie                                      | Untouched. It is simply refused from now on                                                                       | Untouched                                | Cleared, along with the session-id cookie                                         |
| An OAuth ID token already held by a relying party                     | Refused by OpenIAM once its row is gone, and a protocol revocation additionally blacklists it in the shared cache | Same                                     | Same                                                                              |
| A JWT the relying party validates by signature without asking OpenIAM | **Not invalidated.** Nothing OpenIAM does can recall it; it is accepted until its own expiry                      | Same                                     | Same                                                                              |
| A SAML session at a service provider                                  | **Not touched.** No logout request is sent to any partner                                                         | **Not touched**                          | Only the partners this browser recorded, and only through the browser — see below |
| A Kerberos or certificate desktop path                                | The next request silently authenticates again and gets a **new** session                                          | Same                                     | Same                                                                              |

Three consequences worth writing into a runbook. Administrative termination is **silent at the partners** — an application federated to OpenIAM keeps its own session until its own timeout, so "terminated in OpenIAM" is not "signed out of the applications". A user on Kerberos or client certificates cannot be kept out by terminating sessions, only by disabling the account. And the blacklist that holds revoked ID tokens lives in the shared cache, so it does not survive that cache being emptied.

## What single logout actually reaches

Sign-out chains SAML logout requests one partner at a time, redirecting the browser through each in turn, over the set of SAML partners **recorded in this browser's servlet HTTP session**. That sentence contains every limitation:

* **Only this browser.** A session the same person has open on their phone recorded nothing in this browser's HTTP session and is not reached. Neither is a session created before this HTTP session existed.
* **Only partners with an SLO endpoint configured.** A partner for which OpenIAM cannot build a logout request is dropped from the set and the chain continues — a partial logout that completes successfully and reports nothing. Register the partner's SLO URL in **Single-Logout URL of Service Provider** and its binding in **IDP Logout Method Binding** if you want it reached.
* **Only through a browser.** Administrative termination sends no logout request at all.
* **On the service-provider side, only the first partner.** When OpenIAM is the SP, sign-out redirects to the first identity provider recorded for the session on the assumption there is only one.

`/idp/saml2/idp/logout` and `/idp/saml2/idp/globalLogout` are two different endpoints doing two different jobs, and getting them the wrong way round is the usual cause of a logout loop — [OpenIAM as a SAML identity provider](/administration-guide/federation/saml-identity-provider.md#every-endpoint) has the pairing and the audit actions.

Confirm what your own logout reached, rather than assuming: sign in to two service providers in one browser, sign out through OpenIAM, then reload each service provider. The one that is still signed in is the one whose SLO URL is missing.

## Related

* [Terminate a user's sessions](/administration-guide/security/session-management.md) — the procedure this page supports
* [Step-up authentication](/administration-guide/security/step-up-authentication.md) — the approved-authentication-level list the session cookie carries, and how a URL demands more of it
* [OAuth 2.0 and OpenID Connect](/administration-guide/federation/oauth-and-oidc.md) — token lifetimes, refresh and revocation as protocol operations

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/security/session-management/session-management-reference.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
