Skip to main content

Data mapping with Jsonnet

Some modules, like the OpenID Connect and OAuth2 Method, support Jsonnet, allowing you to write code that modifies your identity's data and loads it into Ory Kratos.

We highly recommend checking out the official Learning Jsonnet Tutorial.

note

Jsonnet evaluation runs in a separate worker process that is fully isolated from the filesystem by the Landlock sandbox. Jsonnet code can transform claims and produce identity traits, but it cannot read files from disk under any circumstances.

Input and output

Jsonnet is a data-templating language that allows you to define identity traits and metadata based on input data from external sources.

Input

The input for Jsonnet is typically provided as an external variable using std.extVar. For example:

  • For OpenID Connect (OIDC), the input is available in std.extVar('claims').
  • For SCIM, the input is available in std.extVar('scim'). SCIM additionally provides the existing identity (if one exists) in std.extVar('identity'), which exposes traits, metadata_public, and metadata_admin so a mapper can preserve or merge data that SCIM does not manage. See SCIM data mapping.

The specific structure of the input object depends on the data provided by the OIDC claims or SCIM payload.

In your Jsonnet script, assign the input to a local variable:

local claims = std.extVar('claims'); // For OIDC
// or
local scim = std.extVar('scim'); // For SCIM

Output

The output of the Jsonnet code must conform to the following structure:

{
identity: {
traits: {}, // Custom traits for the identity
metadata_public: {}, // Public metadata visible to the user
metadata_admin: {}, // Admin metadata visible only to administrators
verified_addresses: [{ // Addresses listed here will be marked as verified
value: string, // Verified address value (e.g., the email address)
via: "email" // Verification method (e.g., "email")
}]
}
}

Formatting Jsonnet code

Format Jsonnet code snippets using:

kratos help jsonnet format

# For example:
kratos jsonnet format --write path/to/files/*.jsonnet

Linting Jsonnet code

Lint Jsonnet code snippets using:

kratos help jsonnet lint

# For example:
kratos jsonnet lint path/to/files/*.jsonnet

The command will exit with an exit code of 1 and print all found lint errors to stderr if the code snippet contains lint issues.

Tips & tricks

The purpose of this section is to provide you with examples for common use cases.

Optionality

When you're unsure whether a field will be set in the claims variable, use the following to make the trait field optional:

local claims = std.extVar('claims');

{
identity: {
traits: {
email: claims.sub,
[if "website" in claims then "website" else null]: claims.website,
},
},
}

Defaults

Set defaults for the claims variable:

local claims = {
website: 'I am the default website value'
} + std.extVar('claims');

{
identity: {
traits: {
website: claims.website
}
}
}

Raising errors

You can raise errors in the Jsonnet code. Keep in mind that these will be shown as system errors, not validation errors, and that the user will end up on the Error UI!

local claims = std.extVar('claims');

if std.length(claims.sub) == 0 then
error 'claim sub not set'
else
{
identity: {
traits: {
// ...
},
},
}

Mapping SCIM data

For SCIM, the input is the SCIM user payload in std.extVar('scim'), and the existing identity (if any) is in std.extVar('identity'). Because the mapping uses full-replace semantics, merge the existing metadata_public and metadata_admin back in so that data managed by other sources (such as OIDC or SAML SSO) is not overwritten on each sync:

local scim = std.extVar('scim');
local identity = std.extVar('identity');

{
identity: {
traits: {
email: scim.userName,
[if "name" in scim then "name" else null]: {
first: std.get(scim.name, 'givenName', ''),
last: std.get(scim.name, 'familyName', ''),
},
},
// Preserve metadata SCIM does not manage, then override only what SCIM should manage.
metadata_public: std.get(identity, 'metadata_public', {}) + {
// Add or override only what SCIM should manage here.
},
},
}

See SCIM data mapping for more details.