> This page is for Taurus PROTECT, version v3.50.
> For other versions, use one of these documentation indexes:
> - v3.58 (default): https://taurushq.ferndocs.com/protect-capital/v3.58/llms.txt
> - v3.56: https://taurushq.ferndocs.com/protect-capital/v3.56/llms.txt
> - v3.54: https://taurushq.ferndocs.com/protect-capital/v3.54/llms.txt
> - v3.52: https://taurushq.ferndocs.com/protect-capital/v3.52/llms.txt
> - v3.50: https://taurushq.ferndocs.com/protect-capital/v3.50/llms.txt
> - v3.48: https://taurushq.ferndocs.com/protect-capital/v3.48/llms.txt
> - v3.46: https://taurushq.ferndocs.com/protect-capital/v3.46/llms.txt
> - v3.44: https://taurushq.ferndocs.com/protect-capital/v3.44/llms.txt
> - v3.42: https://taurushq.ferndocs.com/protect-capital/v3.42/llms.txt
> - v3.40: https://taurushq.ferndocs.com/protect-capital/v3.40/llms.txt
> - v3.38: https://taurushq.ferndocs.com/protect-capital/v3.38/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://taurushq.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://taurushq.ferndocs.com/_mcp/server.

# Configuration

In order to use SSO with Taurus-PROTECT, a few components need to be configured with either SAML or OIDC (or both).

* **IdP** (e.g. Okta, Azure AD)
* **SP** (Taurus-PROTECT)
* (optional) **SCIM**

> **Note**
>
> **Note**
>
> The tenant of the SSO user is determined through the federated domain of the email which means that an identity provider can only be used for one single tenant.

## Validatord component configuration

The following configuration options must be included in validatord:

```
daemon:  
  sso:  
    public_host: http://local.taurusgroup.ch:12202
```

Where `public_host` refers to the publicly accessible URL to `tg-validatord`(backend) url.

\


### Configuration - SSO Scopes

When configuring Single Sign-On (SSO) using OpenID Connect (OIDC), administrators can define which scopes are requested during the authentication flow. Scopes determine what categories of user information the identity provider is allowed to share with your application.

Taurus-PROTECT supports the following scopes:

1. openid\
   Required for any OIDC-based authentication\
   The openid scope indicates that the application wants to authenticate the user using OpenID Connect. Without this scope, the identity provider will not issue an ID Token.\
   Provides:

The ID Token (id\_token) containing the user’s unique identifier (sub)

Notes:

This scope must always be included.\
It does not provide profile details by itself—only the identity claim.

2. profile\
   Optional, but commonly used\
   The profile scope requests access to the user’s basic profile information.\
   May include (depending on the identity provider):

* name
* family\_name
* given\_name
* preferred\_username
* locale
* picture

Usage:\
Use this scope if your application displays the user’s name or avatar, or if you need localized profile data.

3. email\
   Optional\
   The email scope grants access to the user’s primary email address.\
   Provides:

* email
* email\_verified flag

Usage:\
Enable this scope if the application requires an email address for notifications, identity mapping, or account provisioning.

4. groups\
   Optional, depends on the identity provider\
   The groups scope allows your application to receive a list of the groups the user belongs to. This is often used for authorization or role mapping.\
   Provides (if supported):

groups: an array of group names or IDs: e.g., \["admins", "engineering", "sales"]

Notes:

Some providers require additional configuration or admin consent before group claims are included.\
Returned group information can vary (names, GUIDs, security groups, distribution lists, etc.).

\


### Configuration - Tenant configuration

```
sso_automatic_user_update:  true
sso_bypass_admin_approval:  false
sso_enforce_authentication: false
```

`sso_automatic_user_update`

* **true**: Users will automatically be created / updated with the information provided by the IdP. If the user doesn’t exist yet it will create it, and if the last name of the user returned by the IdP is different with what is currently in the DB, it will update it.
* **false**: Users need to be created manually by the user manager with the username / external user id matching the subject/user ID returned by the IdP.

`sso_bypass_admin_approval`

* **true**: Automatic user/group changes made by the SSO system will directly be applied in Taurus-PROTECT without the need of an approval by an Admin.
* **false**: Automatic user/group changes made by the SSO system will need to be manually approved by the Admins.

`sso_enforce_authentication`

* **true**: Users can only log in with SSO, they won’t be able to log in directly with their Taurus-PROTECT credentials.
* **false**: Users can log in using either their Taurus-PROTECT credentials or via SSO. They’ll have a password and will be able to reset it.

## IdP Configuration

> **Note**
>
> **Each IdP has a different setup and configurations that it should provide in its documentation.**
>
> We provide a guide and examples for Okta and Azure AD configured for both OIDC and SAML.

### Okta - OIDC

#### Prerequisites

To get started, you need:

* To enable SSO in Taurus-PROTECT configuration (tg-validatord and tg-protect-gui).

#### Configure OKTA SSO

Follow these steps to enable OKTA SSO.

1. In the OKTA admin console, browse to **Applications > Applications** and select **Create App Integration**.

![](/_fern-img/fbf1a356580d67c46bc8b2a6e791263e63b89a833387cd9ea381a70b3f82d493.webp)

2. Pick **OIDC - OpenID Connect** as Sign-in method and **Web Application** as Application type.

![](/_fern-img/6b523cd41e91a8be13d14708457e202cc74dea1978fc8d4077f37bfbdf26b37e.webp)

3. Input the application name (e.g. Taurus-PROTECT) and in the Sign-in redirect URI section add a URI matching the following pattern: `https://<Taurus-PROTECT frontend URL>/login/callback`. In the Assignment section tick Limit access to selected groups and add the desired groups in the list below. Click on Save to validate.

![](/_fern-img/200d222c477007e7048bf007eb34c714802909b23dd16b94195494476beb658c.webp)

4. Browse to the General tab of the application and take note of the following information:
   1. Client ID
   2. Client Secret

![](/_fern-img/5f19856fcb259e9049c8acaf6a59e6088ff674e74d6a642ea485724c695605fb.webp)

### Okta - SAML

#### Prerequisites

To get started, you need:

* To enable SSO in Taurus-PROTECT configuration (tg-validatord and tg-protect-gui).

#### Configure OKTA SSO

Follow these steps to enable OKTA SSO.

1. In the OKTA admin console, browse to **Applications > Applications** and select **Create App Integration**.

![](/_fern-img/fbf1a356580d67c46bc8b2a6e791263e63b89a833387cd9ea381a70b3f82d493.webp)

2. Pick SAML 2.0 as Sign-in method and validate with Next.

![](/_fern-img/134050cd406aa1b4471251b90e7ebd482423975451d1fb081fd109e9628f418d.webp)

3. Input the application name (e.g Taurus-PROTECT) and click **Next** to continue.

![](/_fern-img/4ceff7abfe1d3e73dee9c03e923d6ffd648c3f2fd0ea523b232b61b80d4325a1.webp)

4. In the Configure SAML tab enter the following values:
   1. In the Single sign-on URL  text box, type a URL using the following pattern: `https://<Taurus-PROTECT backend URL>/api/rest/v1/authentication/saml/acs.` Be sure the checkbox **Use this for Recipient URL and Destination URL is ticked**.
   2. In the **Audience URI (SP Entity ID)** text box, type a URL using the following pattern: `https://<Taurus-PROTECT backend URL>/api/rest/v1/authentication/saml/metadata`.
   3. In the **Attribute Statements (optional)** section add the **externaluserid** claim with the **user.email** as value.
   4. (Optional) In the **Group Attribute Statements (optional)** section add the groups claim and filter the desired groups.

![](/_fern-img/f291fd774cf1e1aa94aaa6565a94e04e252d0d890d5ecd8de9a3a00a9394b30d.webp)

5. In the **Feedback** section, set the **App type** to **This is an internal app that we have created** and validate with the **Finish** button.

### Azure AD - OIDC

#### Prerequisites

To get started, you need:

* A Microsoft Entra subscription.
* To enable SSO in Taurus-PROTECT configuration (tg-validatord and tg-protect-gui).

#### Configure Microsoft Entra SSO

Follow these steps to enable Microsoft Entra SSO.

1. Sign in to the Microsoft Entra admin center as at least a Cloud Application Administrator.
2. Browse to **Identity > Applications > App registrations > New registration**.
3. Input the application name (e.g. Taurus-PROTECT) and in the **Redirect URI (optional)** section select **Web** as a platform and a URI matching the following pattern: `https://<Taurus-PROTECT frontend URL>/login/callback`. Select **Register** to register the application.

![](/_fern-img/5397c2f5a9f5211f7c74625e910441dcb42d063a57b79e27ca54e33a6fff9405.webp)

4. Browse to **Overview** and take note of the following information:
   1. **Application (client) ID**
   2. **Directory (tenant) ID**

![](/_fern-img/1d0d168b0ee06fff5ba5392cff5b2014e1b1cf790bb148fc8a6891817713394d.webp)

5. Browse to **Certificates & secrets** > **Client secrets** and select **New client secret**.

![](/_fern-img/5287c3d6914b6c6ed94e2e086083a0549a1d0801a8b301d54a024e7c3a24ae2d.webp)

6. Pick a **Description**, an **Expiration** and select \*\*
7. \*\*:

![](/_fern-img/ef01b5365343d0d1970a30be64e10d554dd1eadda2e2adbedbd034a27514c225.webp)

7. Be sure to save the secret’s Value somewhere safe. You won’t be able to access it later.
8. Browse to Token configuration and select Add optional claim. Select ID as Token type and add the following claims:
   1. email
   2. family\_name
   3. given\_name
   4. preferred\_username

![](/_fern-img/53777a76b860b14f253a886e9da2f2d2f611f5a1bfa240d9e061d67607b1fe69.webp)

9. Select **Add** to validate and tick the box **Turn on the Microsoft Graph email, profile permission (required for claims to appear in token)**. Validate with **Add**.

![](/_fern-img/ffd1c05edb082ef9faab658b7a77789bf25971fa9c627310d08a4cdd8130622c.webp)

10. (Optional) Select **Add groups claims** and pick **Groups assigned to the application** (…).

![](/_fern-img/d1405c9a132dbe2d1d676d7c09b2f23bf922c0997a18c77726fe0b61eebb77df.webp)

11. Browse to **API permissions** and select **Grant admin consent for `<tenant name>`**. Confirm with **Yes**.

![](/_fern-img/817d7712c42e99a1f4f98e9991a584a3bc2c88966a91502757fd94802eafb40b.webp)

12. Browse to **Enterprise applications** and select the application you just created. In the **Manage > Properties** tab make sure:
    1. **Enabled for users to sign-in**? is set to Yes.
    2. (Optional) Upload a logo for the application.
    3. **Assignment required?** is set to Yes.
    4. **Visible to users?** is set to No.

![](/_fern-img/6844d952564e8a926bcfb0dba3f69696ccf87426af79c058d00bcd9845d3c3d8.webp)

13. Browse to **Manage > Users and groups** and assign the relevant users/groups to the application. If you want to setup group mapping, take note of the Azure groups names and IDs.

### Azure AD - SAML

#### Prerequisites

To get started, you need:

* A Microsoft Entra subscription.
* To enable SSO in Taurus-PROTECT configuration (tg-validatord and tg-protect-gui).

#### Configure Microsoft Entra SSO

Follow these steps to enable Microsoft Entra SSO.

1. Sign in to the Microsoft Entra admin center as at least a Cloud Application Administrator.
2. Browse to **Identity > Applications > Enterprise applications > New application.**
3. Select **Create your own application.**
4. Input the application name (e.g. Taurus-PROTECT) and select **Integrate any other application you don't find in the gallery (Non-gallery).**

![](/_fern-img/81bb7d0ad8add677ce367cbc85fee5de7b150d56852283d52d454557393a246b.webp)

5. On the application **Overview** page that opens, select 2. **Set up single sign on**.

![](/_fern-img/48c1584a1781c9e84650e057f064b8245c308b8b3d1ca6c5e7bec368130970aa.webp)

6. Select **SAML** as your single sign-on method.

![](/_fern-img/cdff936af6d85c9199fa4ba8f8642b09a5c58d02f6160b48b12940199cee4b00.webp)

7. Select the pencil icon to edit the **Basic SAML Configuration.**

![](/_fern-img/615398503d63be4220fde373669f8e7bdab6a97e71060bba5b95ad21430a7127.webp)

8. Enter the following values:
   1. In the Identifier (Entity ID) text box, type a URL using the following pattern: `https://<Taurus-PROTECT backend URL>/api/rest/v1/authentication/saml/metadata`.
   2. In the Reply URL (Assertion Consumer Service URL) text box, type a URL using the following pattern: `https://<Taurus-PROTECT backend URL>/api/rest/v1/authentication/saml/acs`.
   3. Sign on URL text box: leave blank.
   4. Relay State (Optional) text box: leave blank.
   5. Logout Url (Optional) text box: leave blank.
9. Select Save and the cross button to exit Basic SAML Configuration.
10. Your Taurus-PROTECT application expects the SAML assertions in a specific format, which requires you to add custom attribute mappings to your SAML token attributes configuration. Select the pencil icon to edit the **Attributes & Claims.**
    1. Select Add new claim and add:
       1. Name: externaluserid
       2. Namespace: `https://<your company>/claims`, e.g. `[https://taurushq.com/claims](https://taurushq.com/claims)`
       3. Source: Attribute
       4. Source attribute: user.mail
    2. Select Add a group claim and add (optional, only if you want to map Azure groups to Taurus-PROTECT groups/roles):
       1. Which groups: Groups assigned to the application
       2. Source attribute: Group ID

![](/_fern-img/282e2d4ef1e0fa80b75966090fee34b659f649952ca75d28bd63f0c3ff10af0e.webp)

11. In the **SAML Signing Certificates** section, click **Download** to download the **Federation Metadata XML** from the given options.

![](/_fern-img/be9048c5115670b60a19fbf63056760bb144c9274de917ec7d10c52c6a5ed553.webp)

12. Browse to **Manage > Properties** and make sure.
    1. **Enabled for users to sign-in?** is set to Yes.
    2. (Optional) Upload a logo for the application.
    3. **Assignment required?** is set to Yes.
    4. **Visible to users?** is set to No.

![](/_fern-img/291cc58aff9a60d3cda546db2badf6c40f5cd84147d9eef4a009d09a07e15b95.webp)

13. Browse to **Manage > Users and groups** and assign the relevant users/groups to the application. If you want to setup group mapping, take note of the Azure groups names and IDs.

#### Azure users

In Azure AD, the following fields are used by Taurus-PROTECT and are mandatory:

* First name
* Last name
* Email

#### Define and create Azure groups

The user’s roles and assignments to groups in Taurus-PROTECT are assigned depending of which Azure groups the user belong to. An Azure group is mapped to a Taurus-PROTECT group containing a set of roles or directly to a set of roles.

Example of mappings:

* Azure group `taurus-protect-uat-operations`  → Taurus-PROTECT group Operations.
  * With the Operations group including roles: `tpuser,requestcreator,requestapprover,accountcreator,whitelistedaddresscreator`
* Azure group `taurus-protect-admins` → Taurus-PROTECT roles `tpuser,admin,usermanager`.

> **Note**
>
> **Superadministrators**
>
> Because of the sensitive nature of the Superadmins roles, such users cannot be automatically provisioned and assigned the superadmin role. Superadmins need to be created during the environments setup, and they will be able to login with SSO.

To handle the Admins and Operators, the following groups (Group type = Security) are created in Azure AD ([How to manage groups - Microsoft Entra](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal#create-a-basic-group-and-add-members)):

* taurus-protect-admins (Object Id: `68ca28ac-2c43-4182-a5f8-216cb47219af`)
* taurus-protect-operators-team1 (Object Id: `21a5474a-bdb5-45d4-a753-6db5d66d9d9e`)
* taurus-protect-operators-team2 (Object Id: `a2b5fa94-6811-4c4e-911f-eef47c36092b`)
* taurus-protect-operators-team3 (Object Id: `ab696e02-5756-4fa1-b1e8-57f9c98b7d2f`)

![](/_fern-img/54f5554d28791022d3cf522def6b8fdf713d3b2496fcbed73d95d1ce8e115bea.webp)

### Create Azure Application

Create your own Azure Enterprise application (Quickstart: Add an enterprise application - [Microsoft Entra ID](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/add-application-portal#add-an-enterprise-application)).

![](/_fern-img/7b58c28420a16c6898ffab6cfca38935cc44513c2e34e204896455015028cf77.webp)

### Set up single sign on

Basic SAML Configuration:

| Field                                      | Value                                                                     |
| :----------------------------------------- | :------------------------------------------------------------------------ |
| Identifier (Entity ID)                     | `https\://<protect backend url>/api/rest/v1/authentication/saml/metadata` |
| Reply URL (Assertion Consumer Service URL) | `https\://<protect backend url>/api/rest/v1/authentication/saml/acs`      |

![](/_fern-img/9e5b6ce63a4d1e7706c6ea896f0b691f9997bfc58502d9735c3867160ed54cfa.webp)

| Field                                                                                                                                    | Value                        |
| :--------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------- |
| Unique User Identifier (Name ID)                                                                                                         | user.email                   |
| [http://schemas.microsoft.com/ws/2008/06/identity/claims/groups](http://schemas.microsoft.com/ws/2008/06/identity/claims/groups)         | user.groups \[SecurityGroup] |
| [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress](http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress) | user.mail                    |
| [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname](http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname)       | user.givenname               |
| [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name](http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name)                 | user.principalname           |
| [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname](http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname)           | user.surname                 |
| [https://rktaurusgroup.onmicrosoft.com/claims/externaluserid](https://rktaurusgroup.onmicrosoft.com/claims/externaluserid)               | user.mail                    |
| urn:oid:0.9.2342.19200300.100.1.3                                                                                                        | user.mail                    |
| urn:oid:2.5.4.4                                                                                                                          | user.surname                 |
| urn:oid:2.5.4.42                                                                                                                         | user.givenname               |

![](/_fern-img/0c9ee6c4f066f12bd8dd663e2c5bc290bc7e39010f532e136ff97542a2c93dbb.webp)

Download the Federation METADATA XML:

![](/_fern-img/7c78dd1c212f710eb3952820b1907527088153299a20058b89ac51afe41c779e.webp)

The file `taurus-protect.xml` contains the Federation Metadata XML.

### Configure SSO in Taurus-PROTECT

see SP configuration - SAML for more info.

Login with an Admin and create an SSO configuration:

![](/_fern-img/3ca695e0ff69976bf729a10f6c83457ea270a290edb91f3ce4c8d70952adba47.webp)

Configure the SAML Mode:

| Field    | Value                                                        |
| :------- | :----------------------------------------------------------- |
| Mode     | SAML                                                         |
| Domain   | `<domain name>`                                              |
| Metadata | Contents of file taurus-protect.xml downloaded from Azure AD |

![](/_fern-img/c6519ab3dcc9d9f3ff874c85c095d63484a84a55d20e8bf3c624f1cfe3d6611e.webp)

In the **Advanced** tab, configure a custom mapping, i.e. **Add custom Claims**:

| Value (Group Object Id)              | Roles                                                                                    | Groups |
| :----------------------------------- | :--------------------------------------------------------------------------------------- | :----- |
| 68ca28ac-2c43-4182-a5f8-216cb47219af | Admin, TP User, User manager                                                             |        |
| 21a5474a-bdb5-45d4-a753-6db5d66d9d9e | Account creator, Request approver, Request creator, TP User, Whitelisted address creator | Team1  |
| a2b5fa94-6811-4c4e-911f-eef47c36092b | Account creator, Request approver, Request creator, TP User, Whitelisted address creator | Team2  |
| ab696e02-5756-4fa1-b1e8-57f9c98b7d2f | Account creator, Request approver, Request creator, TP User, Whitelisted address creator | Team3  |

The **Group Object Id** must be used, and not the group names. When using group membership for in-application authorization, it's preferable to use the group ObjectID attribute, it is immutable and unique in Azure AD.

![](/_fern-img/e1de1a1daf6c5261aca1181c3b116927b46afdf9ebab0a47df9249239fdc5e8e.webp)

## SP Configuration - Taurus-PROTECT

### Configuration - SSO

A new SSO configuration can be created by an *Admin* via the Create menu or directly from the SSO tab.

![New SSO configuration from Create menu](/_fern-img/1cfcbb8b31e15396deed976bd60af30ac717cdd0abba88ceec191d99d1b1d1b6.webp)![New SSO configuration from SSO tab](/_fern-img/f3b1ad36769143b8ff83e1ccff8e23d595aab7c42bc59c9e54997264d080521d.webp)

#### SAML - General

| Field    | Value                                                                       |
| :------- | :-------------------------------------------------------------------------- |
| Domain   | Domain name (emails domain name)                                            |
| Metadata | Metadata provided by the IdP (usually accessible through a public endpoint) |

![Example - SAML \\\`\\\<taurushq.com>\\\` domain](/_fern-img/b3449d445848f01adcc94a0f3c38d6d2d52065d916ae1e1a59fc9ec31305947c.webp)

#### SAML - Advanced

| Field                       | Value                                                                                                                                                              |
| :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Certificate                 | SAML requests are signed using an automatically generated certificate. You can set your own by providing one. It must match the private key                        |
| Private key                 | SAML requests are signed using an automatically generated private key. You can set your own by providing one. It must match the certificate                        |
| Role claim URI              | Set claim to define user roles. Changes will automatically be created when it doesn't match with the current user roles.                                           |
| Group claim URI             | Set claim to define the user groups. Changes will automatically be created when it doesn't match with the current user groups.                                     |
| Public key claim URI        | Set claim to define the public key of the user using the PEM format. Changes will automatically be created when it doesn't match with the current user public key. |
| Force authentication on IDP | Force authentication on the IdP for each login request.                                                                                                            |
| Claim name                  | Set claim name for custom mapping.                                                                                                                                 |

#### Custom mapping

| Value                   | Roles                         | Groups                         |
| :---------------------- | :---------------------------- | :----------------------------- |
| ID of the group in IdP. | List of Taurus-PROTECT roles. | List of Taurus-PROTECT groups. |

![Example - Custom mapping](/_fern-img/55a0193c41d97d8353ad024faf8f8358ccea359d27fdc5c0070ecce9c254d235.webp)

### OIDC - General

| Field         | Value                            |
| :------------ | :------------------------------- |
| Domain        | Domain name (emails domain name) |
| Client id     | Client id from the **IdP**.      |
| Client secret | Client secret from the **IdP**.  |

### OIDC - OpenID configuration

Automatic (recommended):

| Field                    | Value                                                                                                                          |
| :----------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
| OpenID configuration URL | This is the URL provided by the IdP containing all the OIDC configuration fields. All the fields will be filled automatically. |

Manual:

| Field            | Value                                                                                                      |
| :--------------- | :--------------------------------------------------------------------------------------------------------- |
| Issuer           | Domain of the IdP (usually found in the configuration).                                                    |
| Authenticate url | Authorise endpoint of the IdP.                                                                             |
| Token url        | Token endpoint of the IdP.                                                                                 |
| User info url    | (optional) Endpoint to fetch user details. It can be useful when the mandatory URIs miss some user fields. |
| JWKS             | Json Web Key Set of the IdP for signature-based.                                                           |
| Hmac key         | Base64 encoded secret of the token for hash-based signatures.                                              |

### OIDC - Advanced

| Field            | Value                                                                                                      |
| :--------------- | :--------------------------------------------------------------------------------------------------------- |
| Issuer           | Domain of the IdP (usually found in the configuration).                                                    |
| Authenticate url | Authorise endpoint of the IdP.                                                                             |
| Token url        | Token endpoint of the IdP.                                                                                 |
| User info url    | (optional) Endpoint to fetch user details. It can be useful when the mandatory URIs miss some user fields. |
| JWKS             | Json Web Key Set of the IdP for signature-based.                                                           |
| Hmac key         | Base64 encoded secret of the token for hash-based signatures.                                              |

#### Custom mapping

| Value                       | Roles                         | Groups                         |
| :-------------------------- | :---------------------------- | :----------------------------- |
| ID of the group in **IdP.** | List of Taurus-PROTECT roles. | List of Taurus-PROTECT groups. |

![Example Custom Mapping](/_fern-img/55a0193c41d97d8353ad024faf8f8358ccea359d27fdc5c0070ecce9c254d235.webp)

## SCIM Configuration

The **SCIM** is a specification to standardise user management between applications. The goal is that each application/service provider (such as Taurus-PROTECT) provide similar endpoints, that expect the same type of inputs and return the same type of responses. This enable a client to build the same requests to create/update/delete a user in different services.

To ensure consistency of entities between services, **SCIM** providers need to follow or define schema. For example, the User entity is following the urn:ietf:params:scim:schemas:core:2.0:User schema.

### Tenant configuration

```
scim_bypass_admin_approval: false
scim_enforce_virtual_mode:  false
virtual_roles:              []
```

`scim_bypass_admin_approval`

* true: User/Group changes made on the SCIM endpoints will directly be applied without any Admin approval.
* false: User/Group changes made on the SCIM endpoints will generate an admin change that will have to be approved by an Admin.

`virtual_roles`

* A virtual role is a role regrouping multiple roles like:\_ user\_creator,tpuser,requestercreator,accountcreator\_. When assigning this virtual role to a user through SCIM or an admin change, it will assign the different roles from the virtual role to the user.

Example:

```
virtual_roles: 
  tp-full-user: tpuser,accountcreator,whitelistedaddresscreator,requestcreator,requestapprover,requestcanceler,contractcaller
  tp-admin: admin,usermanager
```

`scim_enforce_virtual_mode`

* **true**: Groups and roles changes can only be made via the **SCIM** endpoint with virtual groups.
* **false**: Groups and roles changes can be made by Admins as well as the SCIM endpoint with virtual groups.

### Authentication - Authorisation

The SCIM endpoints require the scim role from Taurus-PROTECT.

#### Generate an API token

To get a long-lived JWT for calls on the SCIM endpoints. An API key can be generated using the Taurus-PROTECT API. This endpoint needs to be called with the technical user (tgvalidatord role).

POST /api/rest/v1/steward/tenants/\{tenantId}/apikeys

Example of request body:

expiration: Expiration date of the JWT.

roles: Roles of the API Key.

#### SCIM Endpoints - Generic

#### GET /api/rest/v1/scim/v2/ServiceProviderConfig

This endpoint is used to expose to the client what options of the SCIM specification Taurus-PROTECT provides. This is where we’ll inform whether we support a changePassword request, patch or bulk operations through our SCIM endpoints.

Example of ServiceProviderConfig response:

```
{
    "schemas":
      ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
    "documentationUri": "https://docs.taurushq.com/protect-capital/reference/introduction",
    "patch": {
      "supported":true
    },
    "bulk": {
      "supported":false
    },
    "filter": {
      "supported":true,
      "maxResults": 50
    },
    "changePassword": {
      "supported":false
    },
    "sort": {
      "supported":false
    },
    "etag": {
      "supported":false
    },
    "authenticationSchemes": [
      {
        "name": "OAuth Bearer Token",
        "description":
          "Authentication scheme using the OAuth Bearer Token Standard",
        "specUri": "http://www.rfc-editor.org/info/rfc6750",
        "documentationUri": "https://docs.taurushq.com/protect-capital/reference/authenticationservice_startlogin",
        "type": "oauthbearertoken",
        "primary": true
      }
    ],
    "meta": {
      "location": "/api/rest/v1/scim/v2/ServiceProviderConfig",
      "resourceType": "ServiceProviderConfig",
      "created": "2022-05-02T04:56:22Z",
      "lastModified": "2022-05-02T04:56:22Z"
    }
  }
```

#### SCIM Endpoints - Users

The User entity will use the urn:ietf:params:scim:schemas:core:2.0:User schema. This schema only requires three attributes:

* **id**: Service provider (Taurus-PROTECT) defined identifier - Validatord.
* **externalId**: Client defined identifier.
* **meta**: Read-only metadata maintained by the service provider (Taurus-PROTECT). Optional custom attributes can be added to it.

In the following endpoints, the \{**id**} represent a Taurus-PROTECT backend user ID.

* GET /api/rest/v1/scim/v2/Users/\{id}

Get a User.

[RFC 7644: System for Cross-domain Identity Management: Protocol ](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.1)

Example of call:

```
curl --location --request GET '127.0.0.1:50000/api/rest/v1/scim/v2/Users/1' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--data-raw ''
```

Example of response:

```
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "id":"145",
  "externalId":"dschrute",
  "meta":{
    "resourceType": "User",
    "created":"2022-04-01T18:29:49.793Z",
    "lastModified":"2022-04-01T18:29:49.793Z",
    "location":"https://validatord.com/api/rest/v1/scim/v2/Users/145",
  },
  "name":{
    "familyName": "Schrute",
    "givenName": "Dwight",
  },
  "emails":[
    {
      "value":"dschrute@example.com",
      "type":"work",
      "primary": true
    }
  ],
  "active": true,
  "roles": [
      {
        "value": "RequestCreator"
      },
      {
        "value": "AccountCreator"
      },
  ],
  "groups": [
      {
        "value": "team1"
      },
      {
        "value": "team2"
      },
  ]
}
```

* GET /api/rest/v1/scim/v2/Users

Get Users.

Query parameters:

* filter: See explication below
* startIndex: Pagination - Starts from 1 (default: 1)
* count: Pagination - Limit per page (default: 100, max: 10’000)

*Filter*: Query users if they start with/equal/ends with a special value for the following columns : `firstName, lastName, externalUserId, email`

Examples of filter value we support:

```
filter="name.familyName eq \"Scott\""
filter="externalId sw \"MicScott\"" // ('sw' here means starts with)
filter="emails[value eq \"abc@example.com\"]"
```

Example of a call:

```
curl --location --request GET '127.0.0.1:50000/api/rest/v1/scim/v2/Users' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--header 'Content-Type: application/json' \
--data-raw '{
    "filter":"name.familyName eq \"Dupont\""
}'
```

Example of response:

```
{
     "schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
     "totalResults":10,
     "itemsPerPage":2,
     "startIndex":1,
     "Resources":[
       {
         "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
         "id":"145",
         "externalId":"dschrute"
         ...
       },
       {
         "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
         "id":"146",
         "externalId":"mickaelscott"
         ...
       }
     ]
}
```

* PATCH /api/rest/v1/scim/v2/Users/\{id}

Update a User.

RFC 7644: System for Cross-domain Identity Management: Protocol

Request body:

```
{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ],
    "Operations": [
        {
            "op": <operation>,
            "path": <field>,
            "value": <value>
        }
    ]
}
```

* *op*: add, remove or replace
* *path*: user field
* *value*: value to set

Example of a call:

```
curl --location --request PATCH '127.0.0.1:50000/api/rest/v1/scim/v2/Users/1' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--header 'Content-Type: application/json' \
--data-raw '{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:PatchOp"
    ],
    "Operations": [
        {
            "op": "replace",
            "path": "name.familyName",
            "value": "Scott"
        }
    ]
}
```

* POST /api/rest/v1/scim/v2/Users

Create a User.

Example of request body:

```
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "externalId":"dschrute",
  "name":{
    "familyName": "Schrute",
    "givenName": "Dwight"
  },
  "emails":[
    {
      "value":"dschrute@example.com",
      "type":"work",
      "primary": true
    }
  ],
  "roles": [
      {
        "value": "requestcreator"
      },
      {
        "value": "accountcreator"
      }
  ]
}
```

If the request return an error about user already existing, it must return an error code 409 (conflict).

Example of call in validatord:

```
curl --location --request POST 'https://tg-validatord-cockroach-7f1a32d5572d5e3a.int.t-dx.com/api/rest/v1/scim/v2/Users' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImI3NDFkY2NiLWU2OGYtNDNkMy05MzJhLTExNWFiNTk4YWM1NiIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwMzk5fQ.xcjKNk5Ll6Qn3lRef3OdW-Ngx7Et5JEZzCP9NL32FLM' \
--header 'Content-Type: application/json' \
--data-raw '{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "externalId":"dschrute",
  "name":{
    "familyName": "Schrute",
    "givenName": "Dwight"
  },
  "emails":[
    {
      "value":"dschrute@example.com",
      "type":"work",
      "primary": true
    }
  ],
  "roles": [
      {
        "value": "requestcreator"
      },
      {
        "value": "accountcreator"
      }
  ]
}'
```

* DELETE /api/rest/v1/scim/v2/Users/\{id}

Delete a User.

warning It can be noted that when re-creating a user with the same info after it has been deleted, this user won’t have the same ID as it had before deletion.

Example of call:

```
curl --location --request DELETE '127.0.0.1:50000/api/rest/v1/scim/v2/Users/1' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--data-raw ''
```

#### SCIM Endpoints - Groups

The Group entity uses the urn:ietf:params:scim:schemas:core:2.0:Group schema.

* **id**: Service provider (Taurus-PROTECT) defined identifier - Validatord.
* **displayName**: The name of the User, suitable for display to end-users.
* **members**: List of Users with id and display fields for each User.
* **meta**: Read-only metadata maintained by the service provider (Taurus-PROTECT). Optional custom attributes can be added to it.

In the following endpoints, the **\{id}** represents our backend user ids

* GET /api/rest/v1/scim/v2/Groups/\{id}

Get a Group.

[RFC 7643: System for Cross-domain Identity Management: Core Schema](https://datatracker.ietf.org/doc/html/rfc7643#section-8.4)

Example of call:

```
curl --location --request GET '127.0.0.1:50000/api/rest/v1/scim/v2/Groups/1' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--data-raw ''
```

Example of response:

```
{
     "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
     "id": "11",
     "displayName": "Risk management group",
     "members": [
       {
         "value": "145",
         "$ref":
   "/api/rest/v1/scim/v2/Users/145",
         "display": "Dwight Schrute"
       },
       {
         "value": "146",
         "$ref":
   "/api/rest/v1/scim/v2/Users/146",
         "display": "Mickael Scott"
       }
     ],
     "meta": {
       "resourceType": "Group",
       "created": "2010-01-23T04:56:22Z",
       "lastModified": "2011-05-13T04:42:34Z",
       "version": "W\/\"3694e05e9dff592\"",
       "location":
   "/api/rest/v1/scim/v2/Groups/11
     }
}
```

* GET /api/rest/v1/scim/v2/Groups

Get Groups.

[RFC 7644: System for Cross-domain Identity Management: Protocol](https://datatracker.ietf.org/doc/html/rfc7644#section-3.4.2.4)

Query parameters:

* **filter**: See explication below
* **startIndex**: Pagination - Starts from 1 (default: 1)
* **count**: Pagination - Limit per page (default: 100, max: 10’000)

Filter: Query users if they start with/equal/ends with a special value for the displayName column.

Examples of filter value we support:

```
filter="displayName eq \"Risk management group\""
filter="displayName sw \"Risk management group\"" // ('sw' here means starts with)
```

Example of a call:

```
curl --location --request GET '127.0.0.1:50000/api/rest/v1/scim/v2/Groups' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--header 'Content-Type: application/json' \
--data-raw '{
    "filter":"displayName eq \"Compliance\""
}'
```

Example of response:

```
{
     "schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
     "totalResults":10,
     "itemsPerPage":2,
     "startIndex":1,
     "Resources":[
       {
         "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
         "id":"11",
         "externalId":"riskmanagement"
         ...
       },
       {
         "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
         "id":"12",
         "externalId":"compliance"
         ...
       }
     ]
}
```

* POST /api/rest/v1/scim/v2/Groups/\{id}

Create a Group.

Example of call:

```
curl --location --request POST 'https://tg-validatord-cockroach-7f1a32d5572d5e3a.int.t-dx.com/api/rest/v1/scim/v2/Groups' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImI3NDFkY2NiLWU2OGYtNDNkMy05MzJhLTExNWFiNTk4YWM1NiIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwMzk5fQ.xcjKNk5Ll6Qn3lRef3OdW-Ngx7Et5JEZzCP9NL32FLM' \
--header 'Content-Type: application/json' \
--data-raw '{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "externalId":"compliance",
  "displayName":"Compliance"
}'
```

Example of a request body:

```
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "externalId":"compliance",
  "displayName":"Compliance"
}
```

If the request return an error about user already existing, it must return an error code 409 (conflict).

* DELETE /api/rest/v1/scim/v2/Groups/\{id}

It can be noted that when re-creating a group with the same info after it has been deleted, this group won’t have the same ID as it had before deletion.

Example of call:

```
curl --location --request DELETE '127.0.0.1:50000/api/rest/v1/scim/v2/Groups/1' \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXh0ZXJuYWxVc2VySUQiOiIiLCJ0ZW5hbnRJRCI6MSwiY2FwaXRhbFRlbmFudElEIjowLCJmaXJzdG5hbWUiOiIiLCJsYXN0bmFtZSI6IiIsInJvbGVzIjpbInNjaW0iXSwiZW1haWwiOiIiLCJqd3RfcmVuZXdhYmxlX2Ftb3VudCI6MjQsImtleSI6ImRmY2UyZjY5LTQ0NzktNGNkNy04ZGU0LTIyZTNiM2MzZThkYSIsImV4cCI6MTY2OTk5MzQ0NiwiaWF0IjoxNjU0NjkwOTA0fQ.oQWXY1tEYGyCeeQ0gOYiOuJCy__eOC4WitgihiL0TEo' \
--data-raw ''
```