---
title: "Inbound SCIM"
description: "Let Okta, Microsoft Entra ID or another identity provider create, update, suspend and remove your directory's users and groups over SCIM 2.0."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.ezghcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Inbound SCIM

With inbound SCIM, your identity provider (such as Okta or Microsoft Entra ID) manages your
directory's users and groups over SCIM 2.0. It creates and updates users, suspends and
deprovisions them, and pushes groups and their members. Suspending someone there ends their
access to every application that trusts your directory, on their next request.

This is separate from IAM's [SCIM provisioning](/iam/scim), which provisions your organization's
members for the console. The two have different base URLs and tokens. An organization can use
both, with a separate app for each at the identity provider.

## Before you start

- Add the [identity provider](/sso/identity-providers) your people sign in through, and route
  your [verified email domains](/sso/domains) to it. SCIM provisions only people whose email
  address is in a verified domain routed to the token's identity provider.
- Creating and deleting directory SCIM tokens needs `sso.scimTokens.create` and
  `sso.scimTokens.delete`, which are in `SsoFullAccess`. A SCIM token provisions and suspends
  people, so treat these as administrator permissions.

## Create a SCIM token

A directory SCIM token names the identity provider whose people it provisions. Everything the
token creates belongs to that identity provider, and the token sees and changes only that
identity provider's users and groups.

### Console

1. Open **EZGH SSO** > **SCIM** and select **Create token**.
2. Enter a **Name**, and choose the **Identity provider** whose people it provisions.
3. Review, then select **Create token**.
4. Copy the token and the **Base URL**. The token isn't shown again.
### CLI

```sh
ezgh sso scim-tokens create okta-scim --identity-provider Okta > scim-token.txt
```

The token is printed once, alone on standard output; the base URL is printed on standard error.
### API

```sh
curl -X POST https://sso.ezghcloud.com/v1/organizations/$ORG_ID/sso/scim/tokens \
  -H "Authorization: Bearer $EZGH_API_KEY" -H "Content-Type: application/json" \
  -d '{ "name": "okta-scim", "identityProviderId": "<identity provider ID>" }'
```

The answer is `{ "scimToken", "token", "baseUrl" }`. `token` is shown only in this answer (and
replays of it with the same `Idempotency-Key`). See
[CreateScimToken](/sso-api/CreateScimToken/).

| Token property | Value |
| --- | --- |
| Format | `ezgh_dsc_` followed by 43 letters and digits |
| Expiry | Never |
| Rate limit | 1,200 requests per minute per token. Over it, `429` with `Retry-After`. |
| Accepted | Only by `https://sso.ezghcloud.com/scim/v2`. It isn't an API key, and IAM's SCIM endpoint doesn't accept it. |
| Stored | Only as a hash. The token list shows each token's `prefix` (`ezgh_dsc_` and 4 characters), identity provider, creator, creation time and when it was last used. |

A token that names no identity provider can't provision users (`400`, `invalidValue`): no domain
routes to it.

## Configure your identity provider

In your identity provider's SCIM 2.0 settings, set:

| Setting | Value |
| --- | --- |
| Base URL | `https://sso.ezghcloud.com/scim/v2` |
| Authentication | HTTP header, bearer token: your directory SCIM token |
| Unique identifier for users | `userName`, the person's email address |

The SCIM app can be the same app your people sign in with, or a separate one: the token decides
which identity provider the users belong to.

### Okta

1. In the Okta Admin Console, open the app integration you use for EZGH SSO. On **General** >
**App Settings**, set **Provisioning** to **SCIM**. Make sure the app's **Application username
format** is **Email**, so `userName` is the email address.
2. On **Provisioning** > **Integration**, set **SCIM connector base URL** to
`https://sso.ezghcloud.com/scim/v2` and **Unique identifier field for users** to `userName`.
Under **Supported provisioning actions**, select **Push New Users**, **Push Profile Updates**
and **Push Groups**. Set **Authentication Mode** to **HTTP Header** and paste the token as the
**Authorization** bearer token. Select **Test Connector Configuration**, then **Save**.
3. On **Provisioning** > **To App**, enable **Create Users**, **Update User Attributes** and
**Deactivate Users**.
4. Assign the people and groups to provision on **Assignments**, and push groups on **Push
Groups**.
### Microsoft Entra ID

1. In the Entra admin center, open **Enterprise applications** and the application you use for
EZGH SSO (or create a non-gallery application). Open **Provisioning** and set
**Provisioning Mode** to **Automatic**.
2. Under **Admin Credentials**, set **Tenant URL** to `https://sso.ezghcloud.com/scim/v2` and
**Secret Token** to the token. Select **Test Connection**, then **Save**.
3. Under **Mappings**, check that `userName` is mapped from the attribute that holds the person's
email address (`userPrincipalName` or `mail`), and that group provisioning is on if you want
groups.
4. Assign users and groups to the application, set **Provisioning Status** to **On**, and save.
Entra ID provisions in cycles, so changes can take a while to arrive.

## What SCIM changes

While a live SCIM token names an identity provider:

- It creates, updates, suspends and deprovisions users in the domains routed to it, and pushes
  groups.
- **Only provisioned users sign in through it.** Signing in through that identity provider
  admits only users its SCIM provisioned. That includes people who signed in before SCIM was
  turned on: they sign in again once SCIM provisions their email address, which takes their
  existing user over. Nobody is created on first sign-in (no JIT users), and someone it hasn't
  provisioned sees an error page. The identity provider's `provisioning` shows
  `{ "jit": false, "scim": true }`.
- **Its users and groups are locked** (`locked: true`). You can't update, suspend, reactivate or
  delete its users, or rename, delete or change the members of its groups, in EZGH SSO. These
  requests return `409` with `managed_by_scim`. The console shows **Managed by your identity
  provider**.
- You still manage their [assignments](/sso/assignments), their
  [sessions](/sso/users#sessions), and provisioned users' membership in groups you created.
- The identity provider's [group mappings](/sso/identity-providers#group-mappings) apply only to
  groups you created.

## Users

A provisioned user is a directory user with `source: scim`. Their SCIM `id` is the user's ID.

- **Email address:** the primary email, else the `work` email, else the first email, else
  `userName`, in lowercase. It must be in a verified domain routed to the token's identity
  provider (`400`, `invalidValue`), checked on every write: a domain that loses its verification
  or routing stops provisioning at once. `acme.com` doesn't cover `eu.acme.com`. An email address
  another user of the directory has is `409`, `uniqueness`.
- **Name:** `displayName`, else `name.formatted`, else `name.givenName` and `name.familyName`,
  else the email address. `givenName` and `familyName` come from `name`, and `department` from
  the enterprise extension.
- **Existing users:** creating a user whose email address the directory already has takes that
  user over when they're hosted, created by JIT, or provisioned by a token that no longer exists.
  They become `source: scim`, sign in only through the identity provider, and lose their
  password, TOTP, passkeys and unused activation links; a pending user becomes active. A user
  that this identity provider already provisioned, or that another identity provider's live token
  manages, is `409`, `uniqueness`.
- **New users** count against `sso.users.count`. A full quota is `403` (`quota_exceeded`).
- **`active: false` suspends the user:** their sessions, sign-ins in progress, unused links,
  application grants and refresh tokens, and EZGH resource tokens end on their next request, and
  applications with a [back-channel logout URI](/sso/applications#logout) are told. They can't
  sign in. `active: true` restores their sign-in; ended sessions and grants don't come back. A
  `PUT` without `active` leaves it unchanged.
- **`DELETE` deprovisions the user:** they're removed as [DeleteUser](/sso-api/DeleteUser/)
  removes a user, with their groups, assignments, sessions, grants and IAM policy attachments, and
  their quota is freed.

Stored attributes: `userName` (unique in the directory, compared without case), `externalId`,
`name`, `displayName`, `emails` (up to 10), `active`, and the enterprise extension's `department`
and `manager`. `groups` is read-only. Other attributes are accepted and ignored.

Changes are pushed on to applications that provision the user. See
[Outbound provisioning](/sso/provisioning).

## Groups

A provisioned group is a directory group with `source: scim`. Its SCIM `id` is the group's ID, and
`displayName` its name.

- Group names are unique in the directory, including groups you created: pushing a group whose
  name another group has is `409`, `uniqueness`.
- Members are users only, and each must be a user this identity provider provisioned (`400`,
  `invalidValue`). Groups can't contain groups. A `PUT` without `members` leaves them unchanged.
- New groups count against `sso.groups.count`.
- Provisioned groups work like any other group: in the `groups` claim, SAML attributes and
  [assignments](/sso/assignments).

## Supported operations

| Endpoint | Methods |
| --- | --- |
| `/ServiceProviderConfig` | `GET` |
| `/ResourceTypes`, `/Schemas` | `GET` |
| `/Users` | `GET`, `POST` |
| `/Users/{id}` | `GET`, `PUT`, `PATCH`, `DELETE` |
| `/Groups` | `GET`, `POST` |
| `/Groups/{id}` | `GET`, `PUT`, `PATCH`, `DELETE` |

- `/Users` and `/Groups` list only what the token's identity provider provisioned, oldest first.
  Lists take `startIndex`, `count` (default 100, at most 200; `0` returns only the total),
  `attributes` and `excludedAttributes`.
- `filter` takes `eq` comparisons joined with `and`. Users can be filtered by `userName`,
  `externalId`, `id`, `displayName`, `active` and `emails` (`emails.value`,
  `emails[type eq "work"].value`). Groups can be filtered by `displayName`, `externalId`, `id` and
  `members` (`members.value`, `members[value eq "…"]`).
- `PATCH` supports `add`, `replace` and `remove`, in the forms Okta and Microsoft Entra ID send. It
  applies all operations or none. A group `PATCH` returns `204`.
- Request bodies are at most 1 MiB.
- Not supported: bulk operations, `/Me`, `POST /.search`, sorting, ETags (`If-Match` is
  ignored), password changes and nested groups.

Errors use the SCIM error format:

| Status | `scimType` | When |
| --- | --- | --- |
| `400` | `invalidSyntax` | The body isn't valid JSON, or a `PATCH` operation is malformed |
| `400` | `invalidFilter` | The filter isn't supported |
| `400` | `invalidValue` | A required attribute is missing, a value is invalid, a member isn't one of this identity provider's users, the email domain isn't verified and routed to the token's identity provider, or the token names no identity provider |
| `400` | `noTarget` | `remove` without a path |
| `401` | | No directory SCIM token, or one that was deleted |
| `403` | | The directory's user or group quota is full (`quota_exceeded`) |
| `404` | | No such user or group for this token |
| `409` | `uniqueness` | The `userName`, email address or group name is taken, or another identity provider's SCIM manages the user |
| `429` | | Over the token's rate limit |
| `503` | | Temporarily unavailable. Retry after `Retry-After` seconds. |

## Activity in Trails

Every change your identity provider makes, and every refused change, is recorded in
[Trails](/sso/trails) with `eventSource` `sso.ezghcloud.com`: `ProvisionUser`,
`UpdateProvisionedUser`, `SuspendUser`, `ReactivateUser`, `DeprovisionUser`, `ProvisionGroup`,
`UpdateProvisionedGroup`, `UpdateGroupMembership` and `DeprovisionGroup`. `userIdentity` is the
`EzghService` `scim.ezghcloud.com`, with the token's ID and name. Reads aren't recorded, and the
token never is.

## Rotate a token

Tokens don't expire. To rotate one, create a second token for the same identity provider, switch
your identity provider to it, then delete the first. Both name the same identity provider, so
nothing changes for its users and groups.

## Turn SCIM off

Deleting the last token that names an identity provider turns SCIM off for it. Deleting the
identity provider revokes its tokens too.

### Console

On **EZGH SSO** > **SCIM**, select **Delete** next to the token, and confirm.
### CLI

```sh
ezgh sso scim-tokens delete okta-scim
```
### API

Call [DeleteScimToken](/sso-api/DeleteScimToken/).

When SCIM turns off for an identity provider:

- It can no longer change anything: the token fails from its next request.
- Its users and groups stay, unlocked: you can edit, suspend, reactivate and delete them in EZGH
  SSO. Suspended users stay suspended until you reactivate them.
- Signing in through the identity provider creates people on their first sign-in again, and links
  existing users by email address.
- A new token for the identity provider manages its users and groups again.

Source: https://docs.ezghcloud.com/sso/scim/index.mdx
