# OIDC client settings

Per-client settings that go beyond the basics on [OIDC clients](oidc-clients.md): where a client's keys come from,
what its sign-in page shows, signed userinfo, request objects by reference, session management and login
initiation. They arrived with `v1.1.0-rc.14`, and every one is off or empty until you set it. They are available in
the admin API, Dynamic Client Registration, the realm export and import, and the console. The flows themselves are
on [OpenID Connect flows](../integration/oidc-flows.md).

## Client keys: JWKS URL or JWK Set by value

A `private_key_jwt` client authenticates with a JWT signed by its own key. Its signed request objects are verified
with the same keys. The keys are registered in one of two ways, never both:

- **By URL:** `jwksUrl` (admin API) or `jwks_uri` (Dynamic Client Registration).
  - The URL must be https.
  - HelixIAM fetches it through the outbound guard and caches it, so a key rotation is picked up.
- **By value:** `jwks` (admin API, as a JSON string; Dynamic Client Registration, as the RFC 7591 JSON object).
  - It is stored with the client (V192).
  - It is shown and edited in the console under *Clients → the client → Keys → JWK Set (by value)*.
  - To rotate a key, update the client.

A JWK Set by value is checked before it is stored. Otherwise it is refused (`400`, field `jwks`):

- it holds 1 to 10 keys and at most 16384 characters;
- every key is a public signing key (RSA of at least 2048 bits, EC or OKP);
- a JWK Set with a private or symmetric key is refused, so no secret key ever reaches HelixIAM;
- an encryption key (`use: enc`) is refused.

The realm export carries the JWK Set; the import applies the same checks.

## Client registration metadata

These fields are settable through the admin API (camelCase), Dynamic Client Registration (the snake_case names of
OpenID Connect Dynamic Client Registration 1.0 §2) and the console (*Clients → the client*). They travel with the
realm export.

| Admin API / registration | Effect |
|---|---|
| `logoUri` / `logo_uri` | The sign-in and consent pages show the logo for this client. The page's image policy allows that origin. |
| `policyUri` / `policy_uri` | The sign-in and consent pages link to the privacy policy. |
| `tosUri` / `tos_uri` | The sign-in and consent pages link to the terms of service. |
| `idTokenSignatureAlg` / `id_token_signed_response_alg` | The ID token is signed with this algorithm (`RS256`, `PS256`, `ES256`). The realm needs an active key for it. `none` is refused. |
| `userinfoSignedResponseAlg` / `userinfo_signed_response_alg` | Userinfo is answered as a JWT (`application/jwt`) signed with this algorithm, with `iss` and `aud`. Without it, userinfo is JSON. Discovery lists the algorithms in `userinfo_signing_alg_values_supported`. |
| `requestUris` / `request_uris` | At most 10 https URLs a request object may be fetched from (`request_uri`, OIDC Core §6.2). |
| `initiateLoginUri` / `initiate_login_uri` | The client's login initiation URI for third-party initiated login (OIDC Core §4). It is https only, registered, and returned by the registration and client management endpoints. |

**Request URIs.** Discovery states `request_uri_parameter_supported: true` and
`require_request_uri_registration: true`:

- a `request_uri` that is not registered is refused (`invalid_request_uri`);
- a registered one is fetched through the outbound guard: at most 50 KB, no redirects;
- the fragment of a registered request URI is ignored when matching;
- a pushed authorization request's `request_uri` (`urn:ietf:params:oauth:request_uri:…`) is handled by the PAR flow.

**URLs and redirect URIs.**

- Every URL above must be https.
- A redirect URI with a fragment is refused at registration (`invalid_redirect_uri`, RFC 6749 §3.1.2).

## Session management (check_session iframe)

OpenID Connect Session Management 1.0 is switched on per client, and is off by default:

- **Console:** *Clients → the client → Login → Session management*.
- **Admin API:** `sessionManagement: true`.

For such a client:

- **The response:** its successful authorization responses carry `session_state`.
- **The cookie:** the browser gets the `HELIX_OPBS` cookie.
  - It holds a hash of the sign-in session, never its id.
  - It is scoped to `/realms/<realm>`, with `Secure` and `SameSite=None`.
  - It is cleared at RP-initiated logout.
- **The iframe:** the realm's `check_session_iframe` (`/realms/<realm>/connect/checksession`, listed in discovery
  where a client uses it) answers the relying party's `postMessage("client_id session_state")`:
  - `unchanged` while the sign-in lasts;
  - `changed` after a sign-out or a new sign-in;
  - `error` for a malformed message.

**What to know before switching it on:**

- That page may be framed by any origin. It holds no data, runs only its own static script and allows no form.
- The cookie must be readable in a third-party frame. Browsers that block third-party cookies make the iframe answer
  `changed`. Prefer back-channel or front-channel logout where they are available.

## See also

- [OpenID Connect flows, response modes and claims](../integration/oidc-flows.md)
- [OIDC clients](oidc-clients.md)
- [Dynamic Client Registration](../integration/api-reference.md#dynamic-client-registration)
