From 0c32434ed7c0bb62e27ce7e5d2457011da272e0b Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Mon, 23 Mar 2026 12:05:12 +0100 Subject: [PATCH 1/3] docs: document update_identity_on_login for OIDC providers Add documentation for the new `update_identity_on_login` provider setting that re-runs the Jsonnet data mapper on every OIDC login to keep identity traits and metadata in sync with the upstream provider. Covers: - Console and CLI configuration - The `identity` ext var available in the mapper during login - Metadata preservation behavior - Schema validation and behavior details --- docs/kratos/social-signin/90_data-mapping.mdx | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/docs/kratos/social-signin/90_data-mapping.mdx b/docs/kratos/social-signin/90_data-mapping.mdx index 0027663273..e4ac1fb0a5 100644 --- a/docs/kratos/social-signin/90_data-mapping.mdx +++ b/docs/kratos/social-signin/90_data-mapping.mdx @@ -192,6 +192,108 @@ local claims = std.extVar('claims'); } ``` +### Update identity on login + +By default, the data mapper runs only during registration. If you want to keep identity data in sync with the upstream provider, +set `update_identity_on_login` to `automatic` on the provider configuration. This re-runs the Jsonnet data mapper on every login +and updates the identity's traits and metadata when they change. + +This is useful when the upstream identity provider is the source of truth for user attributes such as group memberships, roles, or +profile information that can change over time. + +#### Configure in the Ory Console + +1. Go to . +2. Select the provider you want to configure. +3. Open **advanced settings**. +4. Set **Update identity on login** to **automatic**. + +#### Configure via the CLI + +```shell +ory patch identity-config \ + --replace '/selfservice/methods/oidc/config/providers/0/update_identity_on_login="automatic"' +``` + +Or set it in the full provider configuration: + +```json +{ + "selfservice": { + "methods": { + "oidc": { + "config": { + "providers": [ + { + "id": "my-provider", + "provider": "generic", + "update_identity_on_login": "automatic", + "mapper_url": "base64://..." + } + ] + } + } + } + } +} +``` + +#### Access the current identity in the mapper + +When `update_identity_on_login` is set to `automatic`, the data mapper receives the current identity as an additional variable +`std.extVar('identity')`. This lets you write conditional logic — for example, preserving existing trait values or merging data +selectively. + +The `identity` variable contains: + +```json5 +{ + traits: { + /* current identity traits */ + }, + metadata_public: { + /* current public metadata */ + }, + metadata_admin: { + /* current admin metadata */ + }, +} +``` + +Example: update the user's groups from the provider while preserving an existing display name set by the user: + +```jsonnet title="data-mapper.jsonnet" +local claims = std.extVar('claims'); +local identity = std.extVar('identity'); + +{ + identity: { + traits: { + email: claims.email, + // Keep the display name if the user has set one. + [if "display_name" in identity.traits && identity.traits.display_name != "" then "display_name"]: + identity.traits.display_name, + // Always update groups from the provider. + [if "groups" in claims.raw_claims then "groups" else null]: + claims.raw_claims.groups, + }, + metadata_admin: { + [if "office" in claims.raw_claims then "office" else null]: + claims.raw_claims.office, + }, + }, +} +``` + +#### Behavior details + +- **No unnecessary writes.** The identity is only updated in the database when traits or metadata actually changed. +- **Metadata preservation.** When the mapper omits `metadata_public` or `metadata_admin` from its output, existing values are + preserved. When the mapper explicitly outputs `{}`, the field is cleared. +- **Schema validation.** The updated identity is validated against the identity schema before it is persisted. If the mapper + produces invalid traits, the login fails with a validation error. +- **No credential changes.** Credentials and verified addresses are never modified by this feature. + ### Emails and phone numbers :::danger From 365eb0386e76787e182f191cf6da203bff67b7cf Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Wed, 25 Mar 2026 19:26:27 +0100 Subject: [PATCH 2/3] code review Co-authored-by: Vincent --- docs/kratos/social-signin/90_data-mapping.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/kratos/social-signin/90_data-mapping.mdx b/docs/kratos/social-signin/90_data-mapping.mdx index e4ac1fb0a5..0d48c09c6b 100644 --- a/docs/kratos/social-signin/90_data-mapping.mdx +++ b/docs/kratos/social-signin/90_data-mapping.mdx @@ -287,12 +287,12 @@ local identity = std.extVar('identity'); #### Behavior details -- **No unnecessary writes.** The identity is only updated in the database when traits or metadata actually changed. -- **Metadata preservation.** When the mapper omits `metadata_public` or `metadata_admin` from its output, existing values are +- No unnecessary writes. The identity is only updated in the database when traits or metadata actually changed. +- Metadata preservation. When the mapper omits `metadata_public` or `metadata_admin` from its output, existing values are preserved. When the mapper explicitly outputs `{}`, the field is cleared. -- **Schema validation.** The updated identity is validated against the identity schema before it is persisted. If the mapper +- Schema validation. The updated identity is validated against the identity schema before it is persisted. If the mapper produces invalid traits, the login fails with a validation error. -- **No credential changes.** Credentials and verified addresses are never modified by this feature. +- No credential changes. Credentials and verified addresses are never modified by this feature. ### Emails and phone numbers From 2e318b317403c9d8f29ec7b42608e519e3951430 Mon Sep 17 00:00:00 2001 From: Henning Perl Date: Thu, 26 Mar 2026 11:33:14 +0100 Subject: [PATCH 3/3] chore: format --- docs/kratos/social-signin/90_data-mapping.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/kratos/social-signin/90_data-mapping.mdx b/docs/kratos/social-signin/90_data-mapping.mdx index 0d48c09c6b..9172c5a815 100644 --- a/docs/kratos/social-signin/90_data-mapping.mdx +++ b/docs/kratos/social-signin/90_data-mapping.mdx @@ -290,8 +290,8 @@ local identity = std.extVar('identity'); - No unnecessary writes. The identity is only updated in the database when traits or metadata actually changed. - Metadata preservation. When the mapper omits `metadata_public` or `metadata_admin` from its output, existing values are preserved. When the mapper explicitly outputs `{}`, the field is cleared. -- Schema validation. The updated identity is validated against the identity schema before it is persisted. If the mapper - produces invalid traits, the login fails with a validation error. +- Schema validation. The updated identity is validated against the identity schema before it is persisted. If the mapper produces + invalid traits, the login fails with a validation error. - No credential changes. Credentials and verified addresses are never modified by this feature. ### Emails and phone numbers