# SCIM

Automated user and group provisioning with SCIM 2.0

import EnterpriseEditionInfo from "/snippets/enterprise-edition-info.mdx";

<EnterpriseEditionInfo />

Configure Quor with SCIM 2.0 to automatically provision and deprovision users and groups from your identity provider.

Quor has been tested with **Okta** and **Microsoft Entra ID** (Azure AD).
Other SCIM 2.0 providers have not been validated yet. If you need support for a specific provider,
reach out on our [Slack](https://join.slack.com/t/onyx-dot-app/shared_invite/zt-2twesxdr6-5iQitKZQpgq~hYIZ~dv3KA)
or [Discord](https://discord.gg/onyx) channels and we can add it to the roadmap.

<Note>
  SCIM handles **provisioning** — syncing users and groups into Quor.
  You still need a separate authentication method (e.g. [OIDC](/deployment/authentication/oidc)
  or [SAML](/deployment/authentication/saml)) for user sign-in.
</Note>

## What SCIM Does

- **User provisioning** — Automatically create Quor accounts when users are assigned in your IdP
- **User deprovisioning** — Deactivate Quor accounts when users are unassigned or suspended
- **Group sync** — Push group membership changes from your IdP to Quor
- **Profile updates** — Keep user attributes (name, email) in sync

## Generate a SCIM Token

Before configuring your identity provider, generate a SCIM bearer token in Quor.

<Steps>
  <Step title="Navigate to SCIM Settings">
    In your Quor instance, go to the **Admin Panel** → **Permissions** → **SCIM**.
  </Step>

  <Step title="Generate Token">
    Click **Generate SCIM Token**. A new bearer token will be created for your IdP to authenticate with.

    <Warning>
      The token is displayed **only once**. Copy or download it immediately.
      Generating a new token will revoke the previous one.
    </Warning>
  </Step>
</Steps>

You will need these two values when configuring your identity provider:

| Field | Value |
|-------|-------|
| **SCIM Base URL** | `https://YOUR_ONYX_DOMAIN/scim/v2` |
| **Bearer Token** | The token generated above |

## Configure Your Identity Provider

Use the **SCIM Base URL** and **Bearer Token** from the previous step when configuring provisioning in your IdP.

<CardGroup cols={2}>
  <div className="icon-dark-invert">

  <Card title="Okta" icon="/assets/icons/okta.svg" href="https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_scim.htm">
    Follow Okta's guide to add SCIM provisioning to your application
  </Card>
  </div>
  <Card title="Microsoft Entra ID" icon="microsoft" href="https://learn.microsoft.com/en-us/entra/identity/app-provisioning/use-scim-to-provision-users-and-groups#getting-started">
    Follow Microsoft's guide to configure automatic provisioning
  </Card>
</CardGroup>

When prompted for connection details, use:

| IdP Field | Value |
|-----------|-------|
| **SCIM Base URL** / **Tenant URL** | `https://YOUR_ONYX_DOMAIN/scim/v2` |
| **Authentication** | Bearer token (HTTP Header) |

## Verifying the Connection

Once provisioning is configured,
the **SCIM** page in the Quor Admin Panel will show a **Connected** status once the IdP has made its first request.
You can also check the **Users and Groups** page to confirm that provisioned users and groups appear correctly.

## Supported Attributes

The SCIM discovery endpoints are **unauthenticated** — no token required.
You can query them directly to see exactly what Quor supports without guessing.

```bash
curl -s https://YOUR_ONYX_DOMAIN/scim/v2/Schemas -H "Accept: application/scim+json" | jq .
curl -s https://YOUR_ONYX_DOMAIN/scim/v2/ServiceProviderConfig -H "Accept: application/scim+json" | jq .
curl -s https://YOUR_ONYX_DOMAIN/scim/v2/ResourceTypes -H "Accept: application/scim+json" | jq .
```

The tables below reflect the current responses.

### User Attributes (`/scim/v2/Schemas`)

| Attribute | Type | Required | Notes |
|-----------|------|----------|-------|
| `userName` | string | Yes | Unique identifier — typically the user's email address |
| `name.givenName` | string | No | First name |
| `name.familyName` | string | No | Last name |
| `name.formatted` | string | No | Full name including middle names and titles |
| `emails[].value` | string | No | Email address |
| `emails[].type` | string | No | Label, e.g. `work` |
| `emails[].primary` | boolean | No | Whether this is the primary email |
| `active` | boolean | No | Whether the account is active |
| `externalId` | string | No | Identifier from the IdP (case-sensitive) |

**Enterprise User extension** (`urn:ietf:params:scim:schemas:extension:enterprise:2.0:User`):

| Attribute | Type | Required | Notes |
|-----------|------|----------|-------|
| `department` | string | No | Department |
| `manager.value` | string | No | Manager's user ID |

### Group Attributes (`/scim/v2/Schemas`)

| Attribute | Type | Required | Notes |
|-----------|------|----------|-------|
| `displayName` | string | Yes | Human-readable group name |
| `members[].value` | string | No | User ID of the group member |
| `members[].display` | string | No | Display name of the member (read-only) |
| `externalId` | string | No | Identifier from the IdP (case-sensitive) |

### Supported Operations (`/scim/v2/ServiceProviderConfig`)

| Feature | Supported |
|---------|-----------|
| PATCH | Yes |
| Bulk operations | No |
| Filtering | Yes (max 100 results) |
| Change password | No |
| Sorting | No |
| ETags | No |
| Authentication | Bearer token |

### Resource Types (`/scim/v2/ResourceTypes`)

| Resource | Endpoint | Schema |
|----------|----------|--------|
| User | `/scim/v2/Users` | `urn:ietf:params:scim:schemas:core:2.0:User` + Enterprise extension (optional) |
| Group | `/scim/v2/Groups` | `urn:ietf:params:scim:schemas:core:2.0:Group` |
