> ## Documentation Index
> Fetch the complete documentation index at: https://developers.lighton.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SCIM user provisioning from Microsoft Entra ID

> Let Microsoft Entra ID create, update, deactivate and delete Console accounts automatically over SCIM 2.0.

Microsoft Entra ID can create, update, deactivate and delete Console accounts for you over SCIM 2.0. Setup takes about 20 minutes and needs an Entra administrator and a Console company admin.

Entra provisions groups too by default: every group you assign to the application is created in Console with its members. [SCIM group provisioning from Microsoft Entra ID](https://developers.lighton.ai/groups-auto-provisioning-configuration.md) explains that side; step 5 below says how to turn it off if you only want users.

**The steps at a glance:**

1. [Before you start](#1-before-you-start-console-side) (Console admin): check that SCIM is enabled, then create a dedicated Company Admin account and an API key for it.
2. [Create the enterprise application](#2-create-the-enterprise-application-in-entra) (Entra admin): a non-gallery application, or reuse the one you use for SSO.
3. [Connect Entra to Console](#3-connect-entra-to-console) (Entra admin): enter the tenant URL and the API key, then test the connection.
4. [Map the user attributes](#4-map-the-user-attributes) (Entra admin): keep six rows, change `externalId` to `objectId`, delete the rest.
5. [Choose who is provisioned and start](#5-choose-who-is-provisioned-and-start) (Entra admin): assign users or groups, test one user, start provisioning.

> [!WARNING]
>
> If people already sign in to Console with SSO, read [Users who already sign in with SSO](#users-who-already-sign-in-with-sso) at the end of this guide before you start provisioning. A mismatched attribute creates a second account for each of them.

## 1. Before you start (Console side)

1. **Check that SCIM is enabled.** It is on by default, at two levels:
   * the instance, through the `SCIM_INSTANCE_ACTIVATION` config key;
   * your company, through the **Activate SCIM** setting of the company in the Django admin.
2. **Create a dedicated account for Entra**, for example `scim-entra@your-company.com`, with the **Company Admin** role. Entra acts as this account: it needs to create, edit and delete users and groups. Use a dedicated account so that nobody deactivates it by accident.
3. **Create an API key for that account.** Sign in as the account and create the key from the API keys page. Do not restrict the key to workspaces. Copy the key: you paste it into Entra in step 3.

Users are always created in the company of the account that owns the API key.

## 2. Create the enterprise application in Entra

1. In the [Microsoft Entra admin center](https://entra.microsoft.com), go to **Identity > Applications > Enterprise applications**.
2. Click **New application**, then **Create your own application**.
3. Enter a name (for example `Console`), select **Integrate any other application you don't find in the gallery (Non-gallery)**, then click **Create**.

> [!NOTE]
>
> If you already use an enterprise application for Console SSO, add provisioning to that one instead of creating a new one.

![Entra Application Creation](https://mintcdn.com/lighton-developers/HZnJl48AbGHUwmoG/images/Entra-application-creation.png?fit=max\&auto=format\&n=HZnJl48AbGHUwmoG\&q=85\&s=734cd824c59e0926ef1b3ff3daa82f0b)

## 3. Connect Entra to Console

* In the application, open **Provisioning** and click **+ New configuration**.

![Entra Provisioning](https://mintcdn.com/lighton-developers/HZnJl48AbGHUwmoG/images/Entra-provisioning.png?fit=max\&auto=format\&n=HZnJl48AbGHUwmoG\&q=85\&s=52e12dda2e0aa6852fdb7968aaa79281)

![Entra Scim New Config](https://mintcdn.com/lighton-developers/HZnJl48AbGHUwmoG/images/Entra-scim-new-config.png?fit=max\&auto=format\&n=HZnJl48AbGHUwmoG\&q=85\&s=50043e33f939878983d9bcb75cd9e435)

* Fill in the admin credentials:

<table>
  <colgroup>
    <col width="127" />

    <col width="412" />
  </colgroup>

  <thead>
    <tr>
      <th>Field</th>
      <th>Value</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Tenant URL</td>
      <td>`https://<console-domain>/scim/v2/?aadOptscim062020`</td>
    </tr>

    <tr>
      <td>Secret token</td>
      <td>The API key created in step 1</td>
    </tr>
  </tbody>
</table>

> [!NOTE]
>
> * `<console-domain>` is `api.lighton.ai` on the LightOn SaaS, or your own domain on-premise.
> * Keep the `?aadOptscim062020` suffix: it makes Entra send updates in the standard SCIM format. [Microsoft documentation](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/application-provisioning-config-problem-scim-compatibility#flags-to-alter-the-scim-behavior)

![Entra Scim Credentials 1](https://mintcdn.com/lighton-developers/HZnJl48AbGHUwmoG/images/Entra-scim-credentials-1.png?fit=max\&auto=format\&n=HZnJl48AbGHUwmoG\&q=85\&s=17fe042b07cfe342c97c7ebc85042e95)

* Click **Test connection**. A success means Console is reachable, the key is valid and SCIM is on.
* Click **Create**.

![Entra Scim Connection Test 1](https://mintcdn.com/lighton-developers/HZnJl48AbGHUwmoG/images/Entra-scim-connection-test-1.png?fit=max\&auto=format\&n=HZnJl48AbGHUwmoG\&q=85\&s=1fb403e003376052e4e4f27e8b242d8b)

> [!NOTE]
>
> On the LightOn SaaS, ask LightOn support if the connection test in step 3 returns `403`.

## 4. Map the user attributes

Entra's default mapping sends attributes Console does not store. Console rejects any **update** that contains one of them, including the supported changes sent in the same request. Keep only the six rows below.

1. Open **Provisioning > Attribute mapping > Provision Microsoft Entra ID Users**.
2. Make sure the mapping holds exactly these rows:

<table>
  <colgroup>
    <col width="451" />

    <col width="241" />

    <col width="325" />
  </colgroup>

  <thead>
    <tr>
      <th>Source Attribute (Microsoft Entra ID)</th>
      <th>Console attribute (target)</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>`userPrincipalName`</td>
      <td>`userName`</td>
      <td>Entra's default. Required.\
      **Matching Precedence = 1**</td>
    </tr>

    <tr>
      <td>`givenName`</td>
      <td>`name.givenName`</td>

      <td />
    </tr>

    <tr>
      <td>`mail` or `Coalesce([mail], [userPrincipalName]) `if some users have no `mail` and your UPNs are real email addresses.</td>
      <td>`emails[type eq "work"].value`</td>
      <td>Required.</td>
    </tr>

    <tr>
      <td>`objectId`</td>
      <td>`externalId`</td>
      <td>Required. Entra's default is `mailNickname`: change it to `objectId`.</td>
    </tr>

    <tr>
      <td>`surname`</td>
      <td>`name.familyName`</td>

      <td />
    </tr>

    <tr>
      <td>`Switch([IsSoftDeleted], , "False", "True", "True", "False")`</td>
      <td>`active`</td>
      <td>Entra's default. Keep it.</td>
    </tr>
  </tbody>
</table>

3. **Delete every other row**, in particular:`displayName`, `title`, `preferredLanguage`, `name.formatted`, `phoneNumbers[...]`, `addresses[...]`, `roles` and every `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:...` row (`employeeNumber`, `department`, `manager`...).
4. Click **Save**.

![Entra Scim User Attributes](https://mintcdn.com/lighton-developers/jF73gJLYqpqa_08X/images/Entra-scim-user-attributes.png?fit=max\&auto=format\&n=jF73gJLYqpqa_08X\&q=85\&s=3a453ee3fdf6b7b5d388567b53f09112)

> [!NOTE]
>
> Console needs an email to create an account, and an email can belong to only one Console account.

## 5. Choose who is provisioned and start

1. Open **Provisioning > Settings** and set **Scope** to **Sync only assigned users and groups**.

![Entra Scim Only Assigned](https://mintcdn.com/lighton-developers/jF73gJLYqpqa_08X/images/Entra-scim-only-assigned.png?fit=max\&auto=format\&n=jF73gJLYqpqa_08X\&q=85\&s=ff853c8950ac92a2ca968d15de46727e)

2. Open **Users and groups** and assign the users, or the groups whose members should get a Console account. Assigning groups requires Entra ID P1 or P2.

![Entra Scim Users Groups Assignment](https://mintcdn.com/lighton-developers/jF73gJLYqpqa_08X/images/Entra-scim-users-groups-assignment.png?fit=max\&auto=format\&n=jF73gJLYqpqa_08X\&q=85\&s=08623634e1fbfaa364bd14811617a6d6)

> [!WARNING]
>
> An assigned group is also created in Console, because group provisioning is on by default.\
> Entra's default group mapping already suits Console; check it holds only the three rows listed in [step 2 of the group guide](https://developers.lighton.ai/groups-auto-provisioning-configuration.md#2-check-the-group-mapping).
>
> To provision users only, open **Provisioning > Attribute mapping > Provision Microsoft Entra ID Groups** and set **Enabled** to **No**.
>
> Members of assigned groups still get their accounts.

3. Test with one user: **Provisioning > Provision on demand**, pick a user, click **Provision**. Check that every step is green and that the account appears in Console.
4. Back on the **Overview**, click **Start provisioning**.

> [!TIP]
>
> The first cycle provisions everyone in scope. Entra then sends changes about every 40 minutes.
>
> **The first cycle provisions can take some time to be triggered** (up to 40 minutes), use **Provision on demand** to push some users immediately if needed.

![Entra Scim Successfull Overview 1](https://mintcdn.com/lighton-developers/jF73gJLYqpqa_08X/images/Entra-scim-successfull-overview-1.png?fit=max\&auto=format\&n=jF73gJLYqpqa_08X\&q=85\&s=f12aa1feac55b99f7f0e48012dd4c725)

## What happens in Console

<table>
  <colgroup>
    <col width="397" />

    <col width="479" />
  </colgroup>

  <thead>
    <tr>
      <th>In Entra ID</th>
      <th>In Console</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>User assigned to the application (directly or through a group)</td>
      <td>Account created in the API key owner's company, active if the Entra account is enabled. The user receives a welcome email. An existing account is taken over instead (see [Users who already sign in with SSO](#users-who-already-sign-in-with-sso)).</td>
    </tr>

    <tr>
      <td>Name, email or `userName` changed</td>
      <td>Account updated at the next cycle.</td>
    </tr>

    <tr>
      <td>Account disabled (**Block sign in**)</td>
      <td>Account deactivated: the user cannot sign in. Their data is kept.</td>
    </tr>

    <tr>
      <td>Account enabled again</td>
      <td>Account reactivated.</td>
    </tr>

    <tr>
      <td>User unassigned, or removed from the assigned group</td>
      <td>Account deactivated (Entra's default for users leaving the scope).</td>
    </tr>

    <tr>
      <td>User deleted (moved to **Deleted users**)</td>
      <td>Account deactivated. Restoring the user in Entra reactivates it.</td>
    </tr>

    <tr>
      <td>User permanently deleted (or 30 days after deletion)</td>
      <td>Account **anonymized and deactivated**. This cannot be undone; provisioning the person again creates a new, empty account.</td>
    </tr>
  </tbody>
</table>

Manage provisioned users in Entra. An edit made in the Console admin panel to a synced field is overwritten the next time Entra sends that field.

## Troubleshooting

Errors appear in **Provisioning > Provisioning logs**. Filter on **Status: Failure** and open the entry.

| Error | Cause | Fix |
| - | - | - |
| `401 Unauthorized` (also on **Test connection**) | The secret token is wrong, revoked, or contains more than the key. | Paste the API key alone, without `Bearer`. Create a new key if needed. |
| `403 Forbidden` | SCIM is off for the instance or the company, or the key owner is not a company admin. | Check step 1. |
| `501 Not Implemented` on an update | The mapping sends an attribute Console does not store. The whole update was rejected. | Remove the attribute (step 4), then **Provision on demand** for the affected users. |
| `Email is required for user creation` or `Email value is required` | The email attribute is empty for this user. | Fill it in Entra, or choose another email attribute (step 4). |
| `User with this Email address already exists.` | An account with this email exists under another username (see [Users who already sign in with SSO](#users-who-already-sign-in-with-sso)). | Set that account's username to the user's UPN in Console, then **Provision on demand**. |
| `404` on an update | The account was anonymized, or belongs to another company. | Provision the user again: a new account is created. |

If Entra puts the application in **quarantine** after repeated failures, fix the cause, then click **Restart provisioning** on the **Overview**.

## Users who already sign in with SSO

Console may already hold accounts for some of your users: SSO creates one at a person's first sign-in when auto-provisioning is on, and an admin may have created others by hand. Before creating anyone, Entra looks for an existing account in your company whose username equals the user's `userName`, ignoring case. An account created by SSO has, as username, the email SSO sent at that first sign-in.

| The account's username is the user's SCIM `userName` | The SCIM email | What happens |
| - | - | - |
| Yes | Any | **Entra takes over the existing account.** It updates the name and email, then manages it like any provisioned account. Workspaces and group memberships are kept. No welcome email is sent. |
| No | Same email as the account | **Creation is refused** with `User with this Email address already exists.` The person keeps their account, but Entra does not manage it. |
| No | Different from the account | **A second account is created.** SSO keeps opening the old one, so the person never gets the access you give the new one (groups included), and the new one counts as an extra user. |

With the mapping of step 4, an SSO account is in the first row when its username is the person's UPN, and in the second row otherwise, never the third. The second row happens when SSO sends `mail` and it differs from the UPN, or when the UPN changed after the person's first SSO sign-in. Fix it once: a Console admin sets those accounts' username to their current UPN, then **Provision on demand** takes them over.

The other direction needs nothing: when a provisioned user signs in with SSO for the first time, Console links the sign-in to their account by email, as long as SSO sends the same email.

**Check before you start.** Run **Provision on demand** (step 5) on a person who already signs in with SSO. The provisioning log must show an **Update** of the existing account, not a **Create**.

**If duplicates were already created:** fix the mapping (step 4), delete the duplicate accounts in the Console admin panel, then click **Restart provisioning** on the application's **Overview** so that Entra looks every user up again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.