Skip to main content

System for Cross-domain Identity Management

Need help?

SCIM (System for Cross-domain Identity Management) is a standard for automating the exchange of user identity information between identity domains or IT systems. It is designed to simplify the management of user identities in cloud-based applications and services. SCIM provides a common schema for representing user identities and a RESTful API for managing them. This allows organizations to automate the provisioning and de-provisioning of user accounts across multiple systems, reducing administrative burden and improving security.

In Ory Network, SCIM is available at the organization level. This means that within one project, you can have multiple organizations with different SCIM configurations. Each organization can have one or more SCIM clients, each with its own endpoint URL, authentication secret, and data mapping. This allows organizations to tailor their SCIM implementation to meet their specific needs and requirements.

Identities provisioned through the SCIM API are automatically created in Ory Network and added to that SCIM client's organization. The provisioned identities can then log in through any of the organization's configured SSO methods.

For the full endpoint reference — request and response shapes, pagination, filtering, and error responses — see the SCIM API reference.

How SCIM relates to organizations

SCIM in Ory Network is always scoped to an organization:

  • Each SCIM client belongs to exactly one organization. The organization is fixed when you create the client and determines where provisioned identities are placed.
  • An identity belongs to at most one organization. An identity can be a member of a single organization or of none, but never of two organizations at the same time.

Because of this, what happens when a SCIM client provisions a user (POST /Users) depends on whether a matching identity already exists, and which organization it belongs to:

SituationResult
No matching identity existsA new identity is created in the SCIM client's organization.
A matching identity exists in the same organizationThe existing identity is updated using the client's data mapping.
A matching identity exists with no organization, and a verified email domain matchesThe identity is linked into the organization and provisioning continues (see Auto-linking).
A matching identity exists in a different organizationProvisioning fails with a 409 Conflict error (see Cross-organization conflicts).

Auto-linking

When a SCIM client provisions a user that collides with an existing identity, Ory Network tries to link the SCIM record to that identity instead of creating a duplicate. A collision is detected by checking, in order:

  1. The login identifier (the identity's credentials identifier, typically derived from userName).
  2. A verified email address.
  3. A recovery address.

There is no matching on externalId.

When a collision is found:

  • If the existing identity is already a member of the SCIM client's organization, it is updated through the data mapping.
  • If the existing identity belongs to no organization, and it has a verified email whose domain matches one of the organization's verified domains, the identity is linked into the organization and provisioning continues. This is useful when a user signed up (or was provisioned by SSO) before the organization started using SCIM.
  • Otherwise — including when the existing identity belongs to a different organization — provisioning fails with a conflict.

Cross-organization conflicts

Because an identity can only belong to one organization, provisioning a user who already exists in a different organization fails with a 409 Conflict:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "409",
"scimType": "uniqueness",
"detail": "Could not create user: identity already exists in another scope"
}

To resolve this, either delete the existing identity, or move it into the target organization, before retrying provisioning. See the API reference for the full error model.

Set up identity provisioning with SCIM

To set up identity provisioning with SCIM, follow these steps:

Create an organization

If you haven't already, create an organization. This organization will be used to manage your SCIM settings and provision identities.

Configure a SCIM client

In the organization view, under SCIM clients, click Add SCIM client. This will open a form where you can configure your SCIM client's settings.

  • Client ID: Enter an identifier for your SCIM client. This identifier is part of the base URL that the client uses to access the Ory Network SCIM server, so it should be unique within your project.
  • Label: Enter a human-readable label for your SCIM client.
  • Authorization header secret: Enter a secret in the client authentication's secret field. Clients authenticate by sending this secret in the Authorization header of their requests. See Authentication for the exact header format.
  • Data mapping: When the client creates or updates a user, the supplied data is applied to the identity based on this data mapping. See Data mapping below.

Once the client is created, the Console shows its SCIM server URL. Configure your identity provider to send SCIM requests to that URL, using the authorization header secret as its token.

Data mapping

The data mapping is a Jsonnet script that defines how the data the SCIM client sends is mapped to the identity in Ory Network. This mapping is applied any time the SCIM client creates or updates a user (POST, PATCH, or PUT), and the identity is updated accordingly.

The mapping is unidirectional: it only runs when the SCIM client writes data. If an identity trait is later changed elsewhere (for example by the user or another SSO method), the SCIM client cannot read the updated value back. On read (GET), the SCIM attributes are returned from the data stored at provisioning time, not re-derived from the identity.

Relationship to the OIDC and SAML Jsonnet mapper

The SCIM data mapping uses the same Jsonnet engine and the same output schema as the OIDC and SAML SSO data mapping. The differences are:

  • It is configured per SCIM client (each client has its own mapper), not per SSO provider.
  • The input is the SCIM payload in std.extVar('scim') instead of OIDC claims or SAML attributes.
  • It additionally receives the existing identity in std.extVar('identity') (see below).

The script must return a JSON object as defined in the Jsonnet referenceidentity.traits, identity.metadata_public, identity.metadata_admin, and identity.verified_addresses. For the available SCIM input attributes, see the user resource schema.

Preserving data with the identity variable

The mapper also receives the existing identity (if one exists) through the std.extVar('identity') variable, alongside the scim variable. It exposes traits, metadata_public, and metadata_admin, each defaulting to an empty object when unset.

This matters because the mapping uses full-replace semantics: the object your script returns overwrites the corresponding identity fields. If you map metadata_public without merging the existing values back in, any metadata that SCIM does not manage (for example an oid set by SAML or OIDC SSO) is lost on the next sync. To preserve it, merge the existing value:

local scim = std.extVar('scim');
local identity = std.extVar('identity');
local existingPublic = std.get(identity, 'metadata_public', {});

{
identity: {
traits: {
email: scim.userName,
},
// Keep metadata SCIM does not manage (for example values set by OIDC/SAML SSO),
// and override only what SCIM should manage.
metadata_public: existingPublic + {
// Add or override only what SCIM should manage here.
},
},
}
note

A few attributes are applied directly and are not controlled by the mapping: active sets whether the identity can log in, the organization is taken from the SCIM client's configuration, and password (if present) is stored as a password credential.

note

On multi-region Ory Network projects, provisioned identities (and their SCIM data) are stored in the same region as the identity. In addition to the standard mapper output, the mapper may set the region by returning an optional identity.region field; if it doesn't, the organization's default region is used. An invalid region value causes provisioning to fail with a 400 error.

Deprovisioning identities

There are two distinct ways to remove access, with different effects:

  • Deactivate: set active to false (for example through PATCH /Users/{id}). The identity is kept but cannot log in. This is reversible — set active back to true to restore access.
  • Delete: DELETE /Users/{id} permanently deletes the underlying Ory identity and returns 204 No Content. This cannot be undone.

Most identity providers map a user being unassigned or disabled to a deactivation rather than a deletion. Check your provider's configuration to confirm which behavior it uses.

Use the SCIM client

Once you have configured a SCIM client, you can use it to provision identities. The Ory Network SCIM server exposes endpoints for managing users and groups, service-discovery endpoints, pagination, and filtering — all documented in the SCIM API reference.

Refer to these guides for setting up SCIM with specific identity providers:

📄️ API reference

This page is a reference for the Ory Network SCIM server API. It describes the base URL and authentication, every available

Learn more

📄️ Provision from MS Entra

This page guides you through setting up SCIM provisioning from Microsoft Entra to Ory Network.

Learn more

📄️ Provision from Okta

This page guides you through setting up SCIM provisioning from Okta to Ory Network. Also refer to the

Learn more

📄️ Provision from Google Workspace

This page guides you through setting up SCIM provisioning from Google Workspace to Ory Network. Also refer to the Google Workspace

Learn more

Events

Ory Network emits events for SCIM operations that modify data. They surface in the Ory Console under Activity > Logs & Events, and can be used for auditing, automation, or integration with other systems.

SCIM actionEvents emittedDescription
POST /UsersIdentityCreatedA new identity is provisioned. If the user is auto-linked to an existing identity instead, IdentityUpdated is emitted.
PUT /Users/{id}IdentityUpdatedAn identity is replaced.
PATCH /Users/{id}IdentityUpdatedAn identity is partially updated.
DELETE /Users/{id}IdentityDeletedAn identity is deleted.
POST /GroupsSCIMGroupCreatedA new group is created.
PUT /Groups/{id}SCIMGroupUpdated (+ IdentityUpdated)A group is replaced. See the note below about member events.
PATCH /Groups/{id}SCIMGroupUpdated (+ IdentityUpdated)A group is partially updated. See the note below about member events.
DELETE /Groups/{id}SCIMGroupDeleted (+ IdentityUpdated)A group is deleted. See the note below about member events.
note

The IdentityUpdated events on group operations are only emitted when the client's data mapping derives identity data from group membership. In that case, an IdentityUpdated event is emitted for each affected member whose mapped data actually changes — the members added to or removed from the group (for PUT and PATCH), or all former members (for DELETE). If the mapping does not use group membership, group operations emit only the group event.

In addition, a SCIMProvisioningError event is emitted whenever a request fails. This is the SCIM provisioning error entry under Activity > Logs & Events that the provider guides point to for troubleshooting; it carries the failing request's status code and details.

Event attributes

EventAttributeDescription
All eventsSCIMClientThe ID of the SCIM client that made the request.
IdentityCreated, IdentityUpdatedIdentityActiveWhether the identity is active (true or false).
Group eventsSCIMGroupID, SCIMGroupExternalID, SCIMGroupDisplayNameIdentify the group. SCIMGroupUpdated also includes SCIMGroupAddedIdentityIDs and SCIMGroupRemovedIdentityIDs.
SCIMProvisioningErrorSCIMErrorStatusCode, SCIMErrorStatusText, SCIMErrorDetailDescribe the failure.

Limitations

The SCIM server advertises its capabilities through GET /ServiceProviderConfig. Notable limitations to be aware of:

  • Filtering supports only the eq operator, and only on a small set of indexed attributes. See Filtering.
  • Sorting, ETag/versioning, bulk operations, and a /Me endpoint are not supported. See Supported features.