# Sessions, prompt and max_age

> Control when OneiD asks users to sign in again, check sessions silently, and require a recent or MFA sign-in for sensitive actions.

Source: https://oltinid.com/docs/guides/sessions-and-reauthentication/ · Section: Guides · All OneiD documentation: https://oltinid.com/llms.txt

OneiD remembers a signed-in user with a browser session, which gives single sign-on across your applications. The `prompt`, `max_age` and `id_token_hint` parameters let your application decide when that session is good enough and when the user must sign in again. The ID token's `auth_time`, `amr` and `acr` claims tell you how and when the user actually signed in.

## The OneiD session

When a user signs in, OneiD keeps a browser session for 8 hours, extended while the user is active. While it lasts, any of your applications that sends the user to `/connect/authorize` gets a sign-in without a password prompt.

Your application has its own session, separate from OneiD's. OneiD's session decides whether the user must type a password; your session decides whether your application sends the user to OneiD at all.

Signing out of OneiD ends the OneiD session. See [Sign-out](https://oltinid.com/docs/guides/logout/).

## Authorisation request parameters

Add these to the authorisation request described in [Authorization code flow with PKCE](https://oltinid.com/docs/guides/authorization-code-pkce/).

| Parameter | Effect at OneiD |
|---|---|
| `prompt=none` | No sign-in page, no consent page. If interaction is needed, OneiD returns an error to your redirect URI. |
| `prompt=login` | Forces a new sign-in, even if the user has a OneiD session. |
| `prompt=select_account` | Same as `prompt=login`. OneiD has no account picker. |
| `prompt=consent` | Shows the consent page, even if consent was given before or the client does not ask for consent. |
| `max_age=N` | Forces a new sign-in if the user signed in more than `N` seconds ago, judged by `auth_time`. |
| `id_token_hint` | An ID token from an earlier sign-in. If it names a different user than the one signed in, OneiD forces a new sign-in. |

> **Not supported:** OneiD accepts `login_hint`, `ui_locales`, `display` and `acr_values` but they have no effect. In particular, sending `acr_values=urn:oltin:ac:mfa` does not force MFA.

## How and when the user signed in

The ID token carries three claims about the sign-in:

| Claim | Values | Meaning |
|---|---|---|
| `auth_time` | Seconds since 1970 | When the user last entered credentials, not when this token was issued. |
| `amr` | JSON array: `pwd`, `mfa`, `external` | How the user signed in. A password with an authenticator code gives `["pwd","mfa"]`. A sign-in at an upstream OpenID Connect provider gives `["external"]`. |
| `acr` | `urn:oltin:ac:pwd`, `urn:oltin:ac:mfa`, `urn:oltin:ac:external` | The same as `amr`, as one value. |

These claims are in the ID token only, not in the access token or userinfo.

## Require a recent sign-in

For actions such as changing payment details, ask for a fresh sign-in and then check that you got one.

```http
GET /connect/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&scope=openid&state=Wd2kP8sLq5Xn0Rt3&nonce=Hy6cV1mZb9Jf4Ks7&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&max_age=300 HTTP/1.1
Host: YOUR_ONEID
```

After the code exchange, check the ID token: `auth_time` must be no more than 300 seconds ago, allowing a small clock skew. Use `prompt=login` instead of `max_age` to force a sign-in regardless of age.

Always check `auth_time` yourself. The parameters ask OneiD to re-authenticate; the claim proves it happened.

## Require MFA for an action

OneiD does not enforce `acr_values`. To require MFA:

1. **Check the claims.** After sign-in, accept the action only if `amr` contains `mfa` (equivalently, `acr` is `urn:oltin:ac:mfa`).
2. **If it does not, ask the user to sign in again** with `prompt=login`, then check the new ID token. Whether the new sign-in includes an authenticator code depends on the user's MFA setup in OneiD.
3. **If MFA must always apply, ask your administrator** to make MFA mandatory for the users concerned. This is the only way to make OneiD itself require it.

```js
function hasMfa(idTokenClaims) {
  return Array.isArray(idTokenClaims.amr) && idTokenClaims.amr.includes('mfa');
}
```

> **Note:** When users sign in at an upstream OpenID Connect provider, `amr` is `["external"]` and `acr` is `urn:oltin:ac:external`. That provider's own MFA applies, and OneiD does not add its own code on top. The ID token does not tell you whether the provider used MFA.

## Check the session silently with prompt=none

`prompt=none` asks OneiD to complete the sign-in only if it can do so without showing anything. Use it to find out whether the user still has a OneiD session, for example on an important page of an application whose session outlives OneiD's.

```http
GET /connect/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&scope=openid&state=Fn3qR7tYw2Lp9Vx1&nonce=Pz8mK4cX6bJs0Dh5&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&prompt=none HTTP/1.1
Host: YOUR_ONEID
```

If the user has a session and nothing else is needed, the callback carries a code as usual. Otherwise it carries an error:

```http
GET /callback?error=login_required&state=Fn3qR7tYw2Lp9Vx1 HTTP/1.1
Host: app.example.com
```

| Error | Meaning | What to do |
|---|---|---|
| `login_required` | The user has no OneiD session, or must sign in again. | End your session, or start a normal sign-in. |
| `consent_required` | The user has not given consent for these scopes. | Start a normal sign-in so the user sees the consent page. |
| `interaction_required` | The user must do something first, such as change their password or set up MFA. | Start a normal sign-in. |

Run the check as a top-level redirect. OneiD pages cannot be framed, so a check in a hidden iframe does not work. For browser applications that need fresh tokens in the background, use refresh tokens instead. See [Browser applications and CORS](https://oltinid.com/docs/guides/browser-applications/).

## Pending password change or MFA enrolment

An administrator can require a user to change their password or to set up MFA. Until the user does so:

- On a normal sign-in, OneiD sends the user to change the password or enrol an authenticator before the sign-in to your application can complete.
- Under `prompt=none`, your application receives `interaction_required`.
- A refresh token request returns `invalid_grant`.

Your application does not need special handling beyond these errors. The user completes the step at OneiD.

## Learn more

- [Authorization code flow with PKCE](https://oltinid.com/docs/guides/authorization-code-pkce/)
- [Sign-out](https://oltinid.com/docs/guides/logout/)
- [Claims](https://oltinid.com/docs/reference/claims/)
- [OneiD accounts and MFA](https://oltinid.com/docs/sign-in-sources/oneid-accounts/)
