Skip to main content

v26.2.19

v26.2.19

Stop forwarding the OIDC login_hint upstream parameter

Kratos no longer forwards the login_hint upstream parameter to OIDC providers. A caller-supplied login_hint cannot be trusted, and on providers that act on it (such as Google, Microsoft, and Auth0) it can steer account, tenant, or OAuth client selection at the identity provider and enable a phishing client swap.

The hd, prompt, auth_type, and acr_values upstream parameters are unchanged and still forwarded.

Breaking changes

login_hint is removed from the upstream_parameters of the login, registration, and settings OIDC methods. If you previously sent upstream_parameters.login_hint when submitting one of these flows, the value is now ignored and no longer reaches the upstream provider. The account chooser or sign-in form on the provider is no longer pre-filled from this value. No action is required; remove the parameter from your integration to avoid confusion.

Bind an identity to an organization through the settings flow

The self-service settings flow now accepts an optional organization query parameter. Calling createBrowserSettingsFlow or createNativeSettingsFlow with an organization ID scopes the flow to that organization's SSO providers. The organization query parameter is only honored when one of the identity's email addresses is under the organization's configured domains; otherwise the flow falls back to a regular (unscoped) settings flow. The flow's UI returns only link nodes for the matching OIDC and SAML providers, with already-linked providers shown as disabled. Submitting a link runs the upstream IDP authentication and, on the callback, links the credential and sets identity.organization_id — no logout, no manual account linking.

The email-domain check uses the identity's email verifiable addresses. Identities whose schema has no verification.via: email annotation have no email verifiable addresses and therefore cannot use the organization query parameter — the flow silently falls back to an unscoped settings flow.

If the authenticated identity is already bound to an organization, that organization wins over the query parameter. Unlink submissions are rejected for organization-scoped flows. Link submissions are restricted to the flow's organization scope: an organization-scoped flow links only that organization's providers, and an unscoped flow links only providers that belong to no organization.

If the identity's organization_id references an organization that has since been deleted, the settings flow falls back to the unscoped path — accounts offboarded from a deleted organization keep working with account recovery and self-service settings.

Browser autofill and logout hardening for self-service flows

Several self-service flows now emit the standard hints that browsers and password managers use to autofill credentials and one-time codes:

  • One-time code inputs in the login, registration, recovery, and verification code flows carry autocomplete="one-time-code", which lets browsers offer the code straight from the SMS or email and enables the Web OTP API on supported platforms.
  • The identifier input in the password login form carries autocomplete="username", so password managers offer the saved username. The identifier-first and passkey flows keep their existing username webauthn token.
  • SMS one-time code messages for login, registration, and verification now end with an origin-bound last line (@<domain> #<code>), matching the recovery code message. This binds the code to the requesting origin for the Web OTP API.

A new public endpoint, GET /.well-known/change-password, implements the W3C change-password URL. It responds with 303 See Other and redirects to the configured settings UI (selfservice.flows.settings.ui_url), so password managers can deep-link users to where they change their password.

Browser logout can now clear site data. When the new selfservice.flows.logout.clear_browser_data setting is enabled, a successful browser logout over HTTPS sends the Clear-Site-Data response header, instructing the browser to clear cookies, storage, and caches for the origin. The setting is off by default to avoid clearing data that other applications on the same origin may rely on.

Cursor-based pagination for SCIM

The SCIM Users and Groups list endpoints now support cursor-based pagination as described in RFC 9865. Request the first page by sending an empty cursor query parameter (for example GET /Users?cursor&count=100), then follow the nextCursor value returned in each response to fetch the next page. Pagination ends when a response no longer includes nextCursor.

Cursor pagination keeps database load bounded no matter how deep you page, so it is the recommended way to read large numbers of users or groups — it has no equivalent of the startIndex offset limit. The existing count/startIndex offset pagination is unchanged and remains the default. Cursor responses omit totalResults.

Support for both methods is advertised under pagination in GET /ServiceProviderConfig. Cursors are valid for one hour; an expired or malformed cursor returns a 400 error with the expiredCursor or invalidCursor SCIM error type.

Filter SCIM users by group membership

The SCIM API now supports filtering users by group membership. GET /Users?filter=groups.value eq "<group-id>" returns the direct members of the given group. The filter combines with both pagination modes — startIndex / count and cursor pagination — so members of large groups can be enumerated page by page:

GET /Users?filter=groups.value eq "47ac10b5-58cc-4372-a567-0e02b2c3d479"&cursor=...&count=100

Fix SCIM timeouts and conflicts on large group updates

A membership change now re-evaluates the mapper only for the members that actually changed: the members added or removed, plus all current members when the group's display name changes.

Fix missing schemas and meta in SCIM ServiceProviderConfig

The GET /ServiceProviderConfig response now includes the required schemas and meta attributes, as defined in RFC 7644. They were previously omitted because the response was serialized in a way that skipped the custom JSON encoder. SCIM clients that validate the resource against the SCIM schema now receive a compliant response.

Improved SCIM protocol conformance

SCIM list and query responses now follow RFC 7643/7644 more closely:

  • count=0 returns only totalResults without fetching a page, also when combined with cursor pagination.
  • Empty result pages always render Resources: [] and include itemsPerPage.
  • The attributes and excludedAttributes query parameters support dotted sub-attribute paths such as name.givenName or members.value.
  • Group externalId filtering is now case-exact, matching user filtering.
  • PATCH operations normalize multi-valued attributes so at most one entry is primary, and patched resources are re-validated before they are saved.
  • Update conflicts return 409 with scimType: uniqueness only for genuine unique-attribute collisions; other failures return 500 so identity providers retry instead of giving up.

Kratos OEL now ships the full enterprise feature set

Kratos OEL release adds enterprise features: organization OIDC sign-in, SCIM provisioning, FedCM, CAPTCHA, and device authentication.

On upgrade, Kratos OEL applies additional enterprise schema migrations. These are additive and run automatically as part of the standard migrate step.

Require a privileged session to change a recovery address

Changing an identity's recovery address through the settings flow now requires a privileged (recently authenticated) session, matching the protection that already applied to credentials and verifiable addresses.

Previously, an identity using a recovery-only address schema could have its recovery address changed by a stale, non-privileged session without re-authentication. Such a change is now rejected and prompts the user to re-authenticate (session_refresh_required).

The default email-as-identifier schema was already protected and is unaffected.