# Provision people with SCIM

> Canonical HTML: https://screenrig.ai/docs/scim

Your identity provider adds, updates and removes people in screenRIG over SCIM
2.0, and keeps their project access in step with its groups. It works with
Microsoft Entra ID, Okta and any SCIM 2.0 client that sends a bearer token.

## What provisioning does

- **Joiners.** Assign a person to the application in your provider and screenRIG
  creates their account. They sign in through
  [single sign-on](https://screenrig.ai/docs/single-sign-on.md) and have no
  password. They have no project until a group gives them one.
- **Movers.** A group bound to a project gives its members that project. Joining
  or leaving the group adds or removes the access.
- **Leavers.** Deactivating or unassigning a person ends their sessions and
  their access. Agents and OAuth grants a person approved keep working until the
  person is deactivated, by user provisioning or by screenRIG staff: requiring
  single sign-on and disabling the person at your provider do not end them.

## Before you start

- [Single sign-on](https://screenrig.ai/docs/single-sign-on.md) is set up and
  the organization has a verified domain. Provisioning creates only addresses at
  your verified domains.
- You are an admin of the organization.

## Turn it on

1. In Organization settings, open **User provisioning (SCIM)** and choose
   **Turn on provisioning**. Copy the **Base URL**,
   `https://api.screenrig.ai/scim/v2`. It is on the API origin, not the
   dashboard's.
2. Under Provisioning tokens, choose **Create token**, enter a **Token name**
   (`Entra`, for example) and confirm. Copy the token now: `srscim_` followed by
   43 characters, **shown once**. screenRIG keeps only a hash.

Turning provisioning on and creating a token ask for your passkey or password. A
single sign-on session counts instead as a recent sign-in for 10 minutes, when
your provider says when the person authenticated; otherwise the dashboard asks
the person to sign in again at the provider.

An organization holds up to five tokens. To rotate one, create a new token,
paste it into your provider, then revoke the old one; provisioning keeps
running. The list shows when each token was last used. Turning provisioning off
makes every request answer 403 and changes nobody's access.

## Microsoft Entra ID

1. Open your enterprise application (the one that carries single sign-on),
   choose Provisioning, and set Provisioning Mode to **Automatic**.
2. Under Admin Credentials, enter the base URL as **Tenant URL** and the
   token as **Secret Token**. Choose **Test Connection**, then **Save**.
3. Open Mappings, Provision Microsoft Entra ID Users. Map `userName` from
   `userPrincipalName` (or from `mail` when your user principal names are not
   the addresses people sign in with), `emails[type eq "work"].value` from
   `mail`, and leave `active` on its default,
   `Switch([IsSoftDeleted], , "False", "True", "True", "False")`. Keep the other
   mappings Entra proposes. screenRIG uses the work email, else the primary
   email, else `userName`; that address must be at a verified domain and be the
   address your single sign-on sends.
4. Keep Provision Microsoft Entra ID Groups enabled to give access by group.
5. In Settings, set Scope to **Sync only assigned users and groups**, then
   assign the people and groups under Users and groups.
6. Set Provisioning Status to **On** and save. Entra runs a first cycle, then
   syncs about every 40 minutes. **Provision on demand** syncs one person or
   group at once.

## Okta

1. Open your screenRIG application. On General, edit App Settings and set
   Provisioning to **SCIM**.
2. Open Provisioning, Integration, Edit. Enter the base URL as the SCIM
   connector base URL and `userName` as the Unique identifier field for users,
   tick Push New Users, Push Profile Updates and Push Groups, and set
   Authentication Mode to **HTTP Header**. In a custom SCIM app, paste the token
   into the HTTP Header field. Where Okta asks for an **API Token** (Okta's SCIM
   test apps), enter `Bearer`, a space and the token. Both work. Choose **Test
   Connector Configuration**, then **Save**.
3. Open To App, Edit, and enable Create Users, Update User Attributes and
   Deactivate Users. Leave Sync Password off: screenRIG ignores passwords.
4. On Sign On, set Application username format to **Email**.
5. Assign the people and groups on Assignments, and push the groups you bind on
   Push Groups.

Okta deactivates a person with `active: false` and never deletes.

## Groups and projects

Provisioned groups are listed in Organization settings, under User
provisioning (SCIM), in **Provisioned groups**, with their member counts and the
projects they are bound to. A group gives no access until a person who can
approve in a project binds it:

1. In the project, open Access, then **Groups**. Any member reads the bindings;
   the project owner and members who can approve bind a group.
2. Under **Bind a group**, choose a **Group** and a **Role**: **Member**, a plain
   membership, or **Approver**, which also approves reviews. Choose **Bind
   group**. **Remove binding** unbinds it.

- A person in several bound groups holds the highest role, Approver over Member.
- Joining or leaving a group adds or removes the membership. Unbinding a group,
  or deleting it in your provider, withdraws what it gave.
- Provisioning removes only what it added. A membership granted by hand stays,
  and a member a group raised to Approver returns to what they had when they
  leave it.
- A project holds up to 200 members. A person it refuses is recorded as a
  failure in the provisioning events and nothing else changes.
- Groups grant project roles only, never organization admin. Admins see bindings
  and project names, not project content.

## Who can be provisioned

- An address at a verified domain with no account creates one, with no password.
- A person who has no password or passkey, whom your organization manages, or
  at an organization that requires single sign-on, is taken over and signs in
  through single sign-on.
- A person who already has a sign-in of their own and is a member of one of your
  organization's projects is linked for access only, unless your organization
  requires single sign-on. Provisioning manages their access to your projects
  and never their name, email or sign-in.
- Anyone else is refused with an error that names the reason: an account with
  its own sign-in that is not a member of your projects, a person another
  organization manages, and screenRIG staff. Invite such a person to one of your
  projects first, and provisioning then links them for access.

## Deactivation and DELETE

`active: false`, sent by PUT or PATCH, and DELETE both end a person's access.
`active: true` reverses a deactivation, as the table says.

| The person | Deactivation | DELETE |
| --- | --- | --- |
| Is managed by your organization | The account is deactivated by your provisioning. Sessions and dashboard tokens end. Project memberships and the agents they answer for are suspended, not removed. Access a group gave is withdrawn | The same, and the person is no longer provisioned. The account is not erased |
| Is linked for access only | Access to your organization's projects ends and their sessions end: group access is withdrawn and memberships granted by hand are saved, then removed. The account and its sign-in stay theirs | The same, and the person is no longer provisioned. The saved memberships are discarded |

| The person | Reactivation (`active: true`) |
| --- | --- |
| Is managed by your organization | Reinstates the account, but only a deactivation your provisioning made. Memberships and the agents they answer for return, and groups grant access again. Sessions and dashboard tokens do not return: the person signs in again through single sign-on. After a DELETE, a `POST` of the same address reinstates the account, and your provider's next group sync grants group access again |
| Is linked for access only | Restores the saved memberships, each as it was, in the projects still in your organization, and groups grant access again. A project at its 200-member limit refuses one and records a failure. After a DELETE nothing is saved: the person is provisioned again only after an invitation to one of your projects |

A person deactivated by anyone but your provisioning, such as screenRIG staff,
stays deactivated: `active: true` fails with `400 mutability`. A project a person owns is never transferred: a linked person
keeps their access to it, and a managed person's project waits with the rest of
their account until reactivation. Move its ownership before deactivating the
owner if others must keep managing it. The last admin of the organization cannot
be deactivated as a managed person; the request fails with `400 mutability`, so
add another admin first.

## Reference

Base URL `https://api.screenrig.ai/scim/v2`. The token goes in
`Authorization: Bearer srscim_TOKEN`, and a bare token is accepted too. Requests
and responses are `application/scim+json`; `application/json` is accepted.

| Method | Path | Notes |
| --- | --- | --- |
| GET | `/ServiceProviderConfig`, `/ResourceTypes`, `/Schemas` | Patch and filter are supported. Bulk, sort, ETags and password change are not |
| GET | `/Users`, `/Groups` | `filter`, `startIndex` (1-based), `count` (default 100, at most 200, `0` returns only the total), `attributes`, `excludedAttributes` |
| POST | `/Users`, `/Groups` | 201 with `Location`. 409 `uniqueness` for a `userName` already provisioned or a duplicate `displayName` (case-insensitive) |
| GET, PUT, PATCH, DELETE | `/Users/{id}`, `/Groups/{id}` | DELETE answers 204. PATCH of a group answers 204, or 200 with the group when `attributes` or `excludedAttributes` is given. A group PUT without `members` keeps its members |

**Filters** are one to four `attribute eq value` terms joined by `and`. A value is
a quoted string, or `true` or `false` for `active`. Users filter on `userName`
(case-insensitive), `externalId` (exact), `id`, `emails` or `emails.value`,
`displayName` and `active`. Groups filter on `displayName`, `externalId`, `id`
and `members` or `members.value`. Anything else is 400 `invalidFilter`.

**PATCH** reads operations the way Entra and Okta send them, with or without
`?aadOptscim062020`. Operation names are case-insensitive, and booleans are
`true`, `false`, `"True"` or `"False"`. An operation may omit `path` or use dotted
keys such as `{"name.givenName": "Ada"}`. Paths include
`emails[type eq "work"].value`, `members` (add, replace, and remove with a value
array) and `members[value eq "<id>"]` (remove). Attributes screenRIG does not use
are accepted and ignored.

**Limits.** An organization may send 600 requests a minute across its tokens, not
per address, because Entra and Okta share source addresses. Over the limit the
answer is 429 with `Retry-After`. Failed authentications are limited to 30 per
10 minutes for each address.

**Errors** use the SCIM envelope with `scimType`, such as `invalidFilter`,
`uniqueness` or `mutability`:

```json
{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "409", "scimType": "uniqueness", "detail": "…" }
```

User provisioning in Organization settings lists the latest 500 requests, kept
for 30 days, failures included with their reason. Look there first when
something does not arrive.

## Troubleshooting

| Symptom | Cause and fix |
| --- | --- |
| 401 | The token is wrong or revoked. Paste it as shown, or create a new one |
| 403 | Provisioning is off in Organization settings |
| A refusal that names a domain | The person's email is not at a verified domain. Check the `userName` and email mappings, or verify the domain |
| 409 `uniqueness` | The `userName` is already provisioned, or a group with that name exists |
| 400 `mutability` | The person is the last admin of the organization, or someone other than your provisioning deactivated them, which `active: true` does not reverse |
| 429 | The organization spent its 600 requests a minute. The provider retries after `Retry-After` |
| A provisioned person cannot sign in | The provisioned address differs from the address single sign-on sends |
| A provisioned person has no project | No group they belong to is bound to a project |
| A group change is slow to appear | Entra syncs about every 40 minutes. Use Provision on demand |

## Related

- [Single sign-on](https://screenrig.ai/docs/single-sign-on.md): connect Entra ID, Okta, Google Workspace or another provider, and require it.
- [Authentication](https://screenrig.ai/docs/authentication.md): how agents sign in and how access is approved.
- [API reference](https://screenrig.ai/docs/api.md): the `/scim/v2` and provisioning routes.
