Sessions and SSO
How long people stay signed in, how one sign-in carries across clients, the consent and terms screens, and how sign-out reaches every app.
Every sign-in opens a session: a record on the server, tied to one client and one browser, that every token issued afterwards names. Ending the session stops those tokens on their next use, even if they have not expired. Around that core sit four decisions you make per client: how long sessions last, whether they are shared with other clients, whether the person is asked for consent or to accept terms, and how your apps hear about a sign-out.
Session lifetime and Remember me
How long a session lasts is the client’s session lifetime, which also sets how long its ID tokens are valid:
| Setting | Default | Accepted range | Where |
|---|---|---|---|
| Session | 600 minutes (10 hours) | 1 to 525,600 minutes (one year) | Client, Edit, Security, token lifetimes |
On the sign-in screen, Remember me decides what happens when the browser closes. Ticked, the session cookie is persistent and survives a browser restart; unticked, it ends when the browser closes.
Single sign-on
With single sign-on, someone who signed in to one client of the realm enters another without typing credentials again. It is opt-in per client and off by default: two apps that happen to share a realm do not share sign-ins unless you say so.
Turn it on for each client that should share
In Clients, open the client, choose Edit and, in Configuration, under Who may sign in, turn on Single sign-on (SSO). Do it on every client that takes part: a sign-in only carries between clients that both have it on.
Decide whether to always show the account chooser
Always ask for the account on SSO shows the chooser even when a single account is signed in. Leave it off to enter directly with that account.
Whether a sign-in can be reused is decided again on every request, never from what was true when it was made. It is reused only when:
- The account is active and not suspended, and its password has not changed since.
- The account may enter the target client — with Restrict to linked accounts on, it has to be linked to it.
- The sign-in satisfies the request’s
max_age. - Nothing the target client requires is missing, such as a second factor it asks for and the original sign-in did not present.
A session opened through single sign-on reports the original sign-in in auth_time, amr and acr, never a fresh one, and always ends with the browser: a Remember me chosen in another app is not inherited.
The account chooser
A browser remembers its recent sign-ins to the realm, forgetting the oldest first. The hosted login shows Choose an account, with Continue as … for each one and Use another account, when:
- More than one account could enter the client.
- The request carries
prompt=select_account. - The client has Always ask for the account on SSO on, unless the request is silent or carries a
login_hint.
Silent requests
A request with prompt=none never shows a screen. When it cannot be answered from the existing session, it returns to your redirect URI with an error saying what was missing:
| Error | What was missing |
|---|---|
login_required | There is no reusable sign-in. |
account_selection_required | More than one account could be used. |
interaction_required | The person has to answer something first, such as terms or a second factor. |
consent_required | The client asks for consent that has not been given. |
Consent
Turn on Ask for consent in the client’s Configuration when the app should ask before receiving the person’s data — typically a third-party app. It is off by default, which suits your own apps.
- The screen lists the scopes being asked for, with readable names for the standard ones (
profile,email,phone,address,offline_access) and your description for custom scopes. The person chooses Allow or Don’t allow. - It is shown on the first sign-in and again only when a scope not yet granted is asked for. Consent only grows: a narrower request removes nothing.
prompt=consentshows the screen on any client, whatever was granted.- Declining records nothing and returns
access_deniedto the redirect URI.
People see and remove what they granted on the Applications tab of the account pages; removing access also ends their sessions in that app. Administrators find the same list on the user’s Access tab in Users.
Terms of use
Publish the documents and a version
In the client’s Configuration, under Terms of use, set the Terms of service URL, the Privacy policy URL and the Terms version (up to 64 characters, for example
2026-09). The links open in a new tab from the terms screen.Turn on the terms step
In Login layout, switch on terms acceptance. It is always asked right after sign-in, before consent.
The person ticks I have read and accept the terms and chooses Accept and continue, or Decline, which returns access_denied to your app. Each acceptance is recorded with the version, the links shown, the IP address and the browser. Changing the version asks every account to accept again on its next sign-in.
Sign-out
To sign someone out, send the browser to the realm’s end-session endpoint (OpenID Connect RP-Initiated Logout):
| Parameter | Purpose |
|---|---|
id_token_hint | The ID token of the session to end. Required to end anything; an expired token is accepted. |
post_logout_redirect_uri | Where to return afterwards. Must exactly match a registered post-logout redirect URI, or a redirect URI when none is registered. |
state | Returned unchanged with the redirect. |
client_id | The client, when the hint does not already say it. |
ui_locales, theme | Language and palette of the screens shown on the way. |
const ISSUER = 'https://authio.api.hyperio.tech/realms/acme'
export function signOutUrl(idToken: string, state: string): string {
const url = new URL(ISSUER + '/protocol/openid-connect/logout')
url.searchParams.set('id_token_hint', idToken)
url.searchParams.set('post_logout_redirect_uri', 'http://localhost:3000/')
url.searchParams.set('state', state)
return url.toString()
}- With a valid
id_token_hint, the session ends and the browser returns topost_logout_redirect_uri. - Without one, nothing ends: the person sees Do you want to sign out? and decides, and the return address is ignored. Any page can link to the endpoint, so a sign-out never happens without proof.
- A return address that is not registered is not followed: the person stays on You’re signed out, which says the address is not registered.
Telling your apps
A session can end without your app being involved: another app signed out, an administrator ended it, a suspension started. To hear about it, register a logout address in the client’s Configuration:
| Mechanism | How it works | Address rules |
|---|---|---|
| Back-channel logout URI | Authio posts a signed logout_token from its servers whenever a session of the client ends, for any reason. Failed deliveries are retried for up to 6 attempts, the delay growing up to 6 hours. | Absolute https (http only on loopback), no fragment, up to 2,048 characters. |
| Front-channel logout URI | During a browser sign-out, Authio loads the address in a hidden frame; Requires the issuer and session ID adds iss and sid to it. | Absolute http or https, no fragment, up to 2,048 characters. |
The logout token has typ logout+jwt in its header and carries iss, aud, sub, sid, jti and events; it is valid for two minutes. Prefer back-channel when you can: browsers that block third-party cookies can stop a front-channel frame from clearing your cookie.
Ending sessions
| What happens | What ends |
|---|---|
| Sign-out, an administrator ending a session, refresh token reuse | The session and, if it came from single sign-on, the shared sign-in with every session it opened in other clients. |
| Your app revokes a token (RFC 7009) | Only that client’s session. The shared sign-in stays, so the person can come back through it. |
| The person removes an app’s access, or loses access to one client | Their sessions in that client only. |
| Suspension, deactivation or deletion of the account | Every session of the account. |
Where sessions are seen and ended:
- The person: the Sessions tab of the account pages, and the Security tab of the Authio app.
- Administrators: Sessions lists every open session of the realms in scope, with filters, ending in bulk and ending the shared sign-in behind a session; each user’s Activity tab and each client’s Activity tab show theirs.
Sessions live in a store with expiry, so these screens show what is open now. Past sign-ins are in the access log.