diff --git a/docs/kratos/organizations/organizations.mdx b/docs/kratos/organizations/organizations.mdx index 14232c5f1f..ffeb5cca99 100644 --- a/docs/kratos/organizations/organizations.mdx +++ b/docs/kratos/organizations/organizations.mdx @@ -433,6 +433,89 @@ local claims = std.extVar('claims'); } ``` +#### Update identity on login + +By default, Ory runs the data mapper only the first time a user signs in through a SAML connection. To keep identity data in sync +with the SAML identity provider (IdP), set `update_identity_on_login` to `automatic` on the connection. With this setting, Ory +re-runs the connection's Jsonnet data mapper on every SAML login and updates the identity's traits and metadata whenever they +change. + +Use automatic when the SAML IdP is the source of truth for attributes that change over time, such as group memberships, roles, or +profile information. + +The default is `never`. Existing SAML connections keep their current behavior until you opt in. + +```mdx-code-block + + +``` + +1. Go to and open the organization that holds the SAML connection. +2. Edit the Enterprise SAML SSO connection. +3. Set **Update identity on login** to **automatic**. + +```mdx-code-block + + +``` + +To enable it, set `update_identity_on_login` on the connection you want to update. Change the provider index (0 in the example +below) to match your connection's position in the providers array. + +```shell +curl -X PATCH --location "https://api.console.ory.com/projects/$PROJECT_ID" \ + -H "Authorization: Bearer $WORKSPACE_API_KEY" \ + -H "Content-Type: application/json" \ + -d '[ + { + "op": "replace", + "path": "/services/identity/config/selfservice/methods/saml/config/providers/0/update_identity_on_login", + "value": "automatic" + } + ]' \ + | jq ".project.services.identity.config.selfservice.methods.saml" +``` + +```mdx-code-block + + +``` + +##### Access the current identity in the mapper + +When you set `update_identity_on_login` to automatic, Ory passes the current identity to the data mapper as an additional variable +`std.extVar('identity')`. Use it to write conditional logic — for example, to preserve trait values a user has already set, or to +merge SAML IdP data selectively. The `identity` variable holds the identity's current `traits`, `metadata_public`, and +`metadata_admin`. + +```jsonnet +local claims = std.extVar('claims'); +local identity = std.extVar('identity'); + +// Keep the display name if the user has set one, otherwise use the value from the IdP (if any). +local displayName = std.get(identity.traits, "display_name", std.get(claims.raw_claims, "displayName", "")); + +{ + identity: { + traits: { + email: claims.email, + [if displayName != "" then "display_name" else null]: displayName, + // Always update groups from the IdP. + [if std.objectHas(claims, "raw_claims") && std.objectHas(claims.raw_claims, "groups") then "groups" else null]: + claims.raw_claims.groups, + }, + }, +} +``` + +##### Behavior details + +- Metadata preservation. When the mapper omits `metadata_public` or `metadata_admin` from its output, Ory preserves the existing + values. When the mapper explicitly outputs `{}`, the field is cleared. +- Schema validation. Before Ory persists the identity, it validates the update against the identity schema. If the mapper produces + invalid traits, Ory fails the login with a validation error. +- No credential changes. This feature never modifies credentials or verified addresses. + #### Signing certificate expiry details The SAML connection includes a `valid_to` attribute, which is an array of expiry dates for the signing certificates associated