Browser Sessions
When someone signs in, O2ID sets one o2id_session cookie holding a
session container — a group of simultaneously-valid account sessions.
One browser can be signed in as several accounts at once; signing in as a
second account adds it to the container instead of replacing the first.
The cookie is HttpOnly, SameSite=Lax, scoped to /, and expires when
the longest-lived account in the container does. Each account in the
container has its own lifetime (see an application's sessionSeconds); an
expired account drops out of the container on the next request.
A container is not tenant-scoped, so one browser can hold accounts in several tenants and Organizations at the same time. Each tenant only ever sees its own accounts in the container.
An authorization request with no prompt continues as the container's
most-recently-used account for the tenant it resolved to — which is
the account that last signed in, or was last picked in the account
chooser.
A container holds at most 5 accounts. Signing in beyond that drops the least-recently-used one.
Account chooser
GET /t/{tenant}/select-account lists every account the browser is signed
in as, with a "Continue as…" action per account, a "Sign out" action per
account, "Use a different account", and "Sign out of all accounts". It's
part of the login portal bundle, alongside the login and
consent pages.
You don't link to it directly — /oauth2/authorize?prompt=select_account
redirects there, and POST /t/{tenant}/select-account (fields:
transaction_id, account) completes the pending authorization as the
chosen account. The chooser reads the accounts from
GET /t/{tenant}/session/accounts, which resolves them from the request's
own cookie.
The prompt parameter
prompt on /oauth2/authorize
controls whether the user is asked anything before a code is issued.
| Value | Behavior |
|---|---|
| (absent) | Continues as the most-recently-used account. Shows the login page if the browser has no account signed in. |
login | Always shows the login page. A successful sign-in adds an account to the container rather than replacing the current one. |
select_account | Shows the account chooser, even when only one account is signed in. Falls back to the login page when none is. |
none | Never shows any UI. Redirects back with error=login_required when no account is signed in, or error=consent_required when the request would need the consent screen. |
consent | Shows the consent screen even for an application the user already consented to. Has no effect on a trusted application, which has no consent step at all. |
Any other value is treated as the name of a flow trigger to run on the login page.
max_age, login_hint and id_token_hint are not implemented.
Signing out
POST /t/{tenant}/logout (form-encoded). Resolves what to sign out
from the request's own cookie — an account token that isn't in this
browser's container signs nothing out.
| Field | Value |
|---|---|
account | Optional. The account to sign out, from GET /session/accounts. Defaults to this tenant's most-recently-used account. |
all | Optional. true signs out of every account in the container, across every tenant, and clears the cookie. |
redirect_to | Optional. Where to send the browser afterwards. Honored only for a relative path; anything else answers 204. |
Signing out of one account leaves the container's other accounts signed in. The cookie is cleared once nothing is left in it.
curl -X POST https://your-o2id-instance/t/system/logout \
--cookie "o2id_session=…" \
-d "all=true"
This is the portal's own sign-out, not OIDC RP-Initiated Logout: there is
no end_session_endpoint, no id_token_hint validation and no
post_logout_redirect_uri allow-list.