> For the complete documentation index, see [llms.txt](https://incident-tracker.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://incident-tracker.gitbook.io/docs/admin-guide/application-information/authentication-settings/account-provisioning/scim.md).

# SCIM Provisioning

### Purpose

This guide provides instructions for configuring SCIM (System for Cross-domain Identity Management) user provisioning between Microsoft Entra ID and Incident Tracker. SCIM provisioning automates account lifecycle management by synchronizing user data from your identity provider (IdP) to Incident Tracker in a secure and scalable manner.

{% hint style="success" %}
If SSO is configured already, SCIM can use the same Enterprise Application.
{% endhint %}

***

### Key Benefits

* ✅ **Automated Account Creation:** Assigned users in Entra ID are automatically created in Incident Tracker.
* 🔄 **Ongoing Synchronization:** User updates in Entra ID are automatically reflected in Incident Tracker.
* 🚫 **Automatic Deactivation:** Users removed or unassigned in Entra are automatically disabled in Incident Tracker.
* 🔐 **Enterprise-Grade Security:** Built using standard SCIM 2.0 protocol for modern identity management.

***

### Prerequisites

Ensure the following prerequisites are met before beginning the setup:

| Requirement                  | Description                                                                                                          |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Microsoft Entra Admin Access | Permissions to manage Enterprise Applications                                                                        |
| SCIM Bearer Token            | Provided by Incident Tracker Support                                                                                 |
| SCIM Tenant URL              | <p>Cloud: <code><https://public-api.incident-tracker.com/scim/v2/></code><br>On-prem: Customer-specific base URL</p> |

***

### Configuration Steps

{% hint style="success" %}
If SSO is configured already, SCIM can use the same Enterprise Application *(Skip Step 1)*.
{% endhint %}

#### 1. Create the Enterprise Application

1. Sign in to the [Microsoft Entra Admin Center](https://entra.microsoft.com)
2. Go to **Enterprise Applications**
3. Click **+ New Application**
4. Choose **Create your own application**
5. Name the application (e.g., `Incident Tracker Provisioning`)
6. Select **Integrate any other application you don't find in the gallery**
7. Click **Create**

***

#### 2. Configure Provisioning

1. Open the Enterprise Application
2. Navigate to the **Provisioning** tab
3. Click **Get Started**
4. Set the SCIM Connection fields below.

**SCIM Connection Settings**

| Field        | Value                                                                      |
| ------------ | -------------------------------------------------------------------------- |
| Tenant URL   | `https://public-api.incident-tracker.com/scim/v2/` *(or your on-prem URL)* |
| Secret Token | Provided by Incident Tracker Support                                       |

Click **Test Connection** to verify the configuration.

***

#### 3. Configure Attribute Mappings

1. In the **Provisioning** tab, click **Attribute mapping**
2. Select **Provision Microsoft Entra ID Groups**
   1. Change ***Enabled*** to ***No*** and save
3. Select **Provision Azure Active Directory Users**
4. Review and configure the recommended mappings in the table below. All other mappings can be removed.

| Azure AD Attribute (Source) | SCIM Attribute (Target)                                                    | Notes                                                        |
| --------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------ |
| `userPrincipalName`         | `userName`                                                                 | Primary login identifier                                     |
| `givenName`                 | `name.givenName`                                                           | Required                                                     |
| `surname`                   | `name.familyName`                                                          | Required                                                     |
| `mail`                      | `emails[type eq "work"].value`                                             | Primary email                                                |
| `manager`                   | `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager.value` | Manually added as a Direct mapping type                      |
| `accountEnabled`            | `active` *(or `enabled`)*                                                  | Maps Entra account status to Incident Tracker enabled status |
| `objectId`                  | `externalId`                                                               | Maps user's GUID (immutable identifier)                      |

> ℹ️ **Manager Notes**
>
> * Uses Azure AD `objectId` (GUID)
> * GUID must match an existing user in Incident Tracker
> * If unmatched, field is ignored
> * If Manager is empty in Entra, but exists in Incident Tracker, it remains in Incident Tracker

> ℹ️ **Enabled Field Notes**
>
> * `accountEnabled` in Entra controls active/disabled state
> * Mapped to `enabled` in Incident Tracker
> * Users set to `false` in Entra will be disabled in Incident Tracker

Click **Save** when finished.

***

#### 4. Assign Users or Groups

1. Go to the **Users and Groups** tab
2. Click **+ Add user/group**
3. Select the users or groups to provision
4. Click **Assign**

> ⚠️ Group-based provisioning triggers **user-level** provisioning events. Group membership data is not included in SCIM payloads.

***

#### 5. Start Provisioning

1. Return to the **Provisioning** tab
2. Click **Start Provisioning**

Provisioning runs automatically on a scheduled interval (approximately every 40 minutes by Entra default).

***

### Monitoring & Maintenance

#### View Logs

Use the **Provisioning Logs** tab to monitor:

* ✅ Successful provisioning events
* ⚠️ Skipped records
* ❌ Errors or misconfigurations

Logs can be filtered by status, user, and timestamp.

***

#### Deactivation Handling

Incident Tracker automatically disables user accounts when:

* They are **unassigned** from the SCIM application, or
* They are **disabled** in Microsoft Entra ID

No manual cleanup is required.

***

### Troubleshooting & Errors

| Issue                         | Resolution                                                            |
| ----------------------------- | --------------------------------------------------------------------- |
| Test connection fails         | Verify SCIM URL and token. Contact support if needed.                 |
| Users not provisioning        | Ensure they are assigned to the SCIM application.                     |
| Attribute changes not syncing | Confirm mappings match Incident Tracker requirements.                 |
| Manager field not syncing     | Ensure manager has a valid `objectId` and exists in Incident Tracker. |

<details>

<summary>PATCH Response Codes</summary>

When a **PATCH** request is made with a user object and ID, the API may return:

* **200 OK** – Request succeeded.
  * Returns updated user object as JSON.
  * Partial updates apply: if one attribute (e.g., first name) is updated successfully but another (e.g., email) fails, a `200` is still returned.
* **400 Bad Request** – Invalid request payload or parameters.
* **401 Unauthorized** – Authentication failure. Token may be invalid or expired. Re-enter and retry.
* **404 Not Found** – User not found.
* **409 Conflict** – Update failed due to attribute conflicts.
  * No attributes are updated when all attempted updates fail (e.g., only email or username updates were attempted and all conflicted).
* **500 Internal Server Error** – Unexpected server exception.

</details>

***

### Supported Endpoints

Incident Tracker supports the following SCIM 2.0 endpoints:

| Method   | Endpoint      | Description                                                                                                 |
| -------- | ------------- | ----------------------------------------------------------------------------------------------------------- |
| `GET`    | `/Users`      | Returns a paginated list of users. Supports filtering, sorting, and pagination parameters.                  |
| `POST`   | `/Users`      | Creates a new user (**single user only; bulk operations are not supported**). Requires standard attributes. |
| `PATCH`  | `/Users/{id}` | Updates an existing user's attributes. Soft delete sets user inactive.                                      |
| `DELETE` | `/Users/{id}` | Deletes a user in Incident Tracker. Runs if user is completely deleted in Entra.                            |

> ⚠️ POST attempts made to endpoint `/Users` for account creation will only attempt when the meta field attribute resourceType = "User"

> ⚠️ **Bulk Operations Not Supported**\
> The SCIM `/Bulk` endpoint is **not currently supported**.
>
> * Only single-user create, update, or delete requests are accepted.
> * Multiple users must be provisioned individually.&#x20;

***

#### GET /Users — Filtering, Sorting, and Pagination

The `/Users` endpoint supports optional query parameters for filtering, sorting, and pagination.

***

**🔍 Filter Support**

* Only the `eq` (equals) operator is supported
* Supported attributes:
  * `userName`
  * `externalId`
  * `emails.value`
  * `active`

**Format:**

```http
filter={attribute} eq "{value}"
```

Examples:

GET /scim/v2/Users?filter=userName eq "<john.doe@example.com>"\
GET /scim/v2/Users?filter=active eq "true"

⚠️ Operators such as `ne`, `co`, or `sw` are not accepted.

**↕️ Sorting Support**

Sort users by creation date using the `sortBy` parameter:

| Value    | Behavior                     |
| -------- | ---------------------------- |
| `newest` | Newest to oldest             |
| `oldest` | Oldest to newest *(default)* |

> If an invalid value or no value is passed, `sortBy` defaults to `oldest`.

***

**📄 Pagination Support**

Pagination is controlled by the `startIndex` and `itemsPerPage` parameters:

| Parameter      | Description                                                                                                                    |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `startIndex`   | 1-indexed starting position. `"1"` represents the first record. Defaults to `"1"` if invalid or not supplied.                  |
| `itemsPerPage` | Number of results to return from `startIndex`. Defaults to `100` if invalid or not supplied. **Maximum allowed value is 100**. |
| `sortBy`       | Sort order (`newest` or `oldest`). Defaults to `oldest` if invalid or not supplied.                                            |

<details>

<summary>Pagination Examples</summary>

#### *First 50 newest users*

GET /scim/v2/Users?startIndex=1\&itemsPerPage=50\&sortBy=newest

#### *25 users starting from the 101st, oldest first*

GET /scim/v2/Users?startIndex=101\&itemsPerPage=25\&sortBy=oldest

#### *Active users only, first 50, newest first*

GET /scim/v2/Users?filter=active eq "true"\&startIndex=1\&itemsPerPage=50\&sortBy=newest

✅ Filtering, sorting, and pagination can be combined in a single request.

</details>

***

<details>

<summary>SCIM User object example</summary>

```
{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
  ],
  "id": "test-user-001",
  "userName": "test.user@example.com",
  "name": {
    "givenName": "TestFirstName",
    "familyName": "TestLastName"
  },
  "emails": [
    {
      "value": "test.user@example.com",
      "type": "work",
      "primary": true
    }
  ],
  "active": true,
  "manager": {
    "id": "test-manager-001",
    "ref": "/Users/test-manager-uuid",
    "displayName": "TestManagerName",
    "email": "manager@example.com",
    "externalId": "test-manager-uuid"
  },
  "meta": {
    "resourceType": "User",
    "created": "2025-01-01T00:00:00",
    "lastModified": "2025-01-02T00:00:00",
    "location": "https://test-api.example.com/scim/v2/Users/test-user-uuid",
    "version": "W/\"2025-08-13T16:13:35.6964556Z\""
  },
  "externalId": "test-user-uuid"
}
```

</details>
