WhyLabs SCIM V2 User Provisioning
The System for Cross-domain Identity Management (SCIM) is a standard protocol that allows for simplified user provisioning and management in identity management systems. This document outlines the steps to use the SCIM V2 protocol with WhyLab's SCIM V2 service for automated user provisioning.
Introduction to SCIM V2
SCIM V2 is a RESTful protocol designed to simplify the management of user identities, attributes, and resources. It offers a standardized way to create, read, update, and delete user data within an identity provider.
References
- SCIM (System for Cross-domain Identity Management) Specification:
WhyLabs Account Management and SCIM
The WhyLabs SCIM API enables provisioning of users and managing of organization memberships for multiple organizations belonging to a single parent organization. This parent organization is the "account".
Administrators within the account organization can create an API token that grants access to the SCIM API for the account. This token and API can be used by provisioning systems to automate user and membership provisioning.
Setting up an account
Please contact us to set up an account organization, providing:
- the list of organizations to be managed under the account
- the list of administrators to be added into the account organization
Setting up the groups to be provisioned
Each organization and role pair in WhyLabs is represented as a SCIM group, for example the Member role in org-3454 is
represented as the SCIM group org-3454:member
.
Set up your provisioner with three groups (org-xxxx:admin
, org-xxxx:member
and org-xxxx:viewer
)
for each managed organization in the account.
You may also manage the users and roles in the account organization. We recommend you only use the account organization for account management and so the groups in the account organization representing Member and Viewer roles should be kept empty.
Note that WhyLabs SCIM groups cannot be created or deleted, as they are defined automatically by the organizations in the account, and the predefined WhyLabs roles.
Typical Provisioning Flow with Automated Provisioners
Automated provisioners like Okta, SailPoint, and similar identity management systems enable organizations to automate the process of user provisioning, deprovisioning, and synchronization across various applications and services. When integrated with a SCIM V2 service, these provisioners facilitate efficient user lifecycle management. Here's a typical provisioning flow:
Integration Setup: Integrate the WhyLabs SCIM API (acting as a SCIM Service Provider) with the automated provisioner (acting as a SCIM Client). This involves configuring the provisioner to communicate with the WhyLabs SCIM V2 endpoints, typically using endpoint URLs, authentication credentials, and other necessary settings.
User creation:
- Provisioner initiates: When a new user is created or onboarded within the automated provisioner (e.g., Okta or SailPoint), the provisioner generates a SCIM request to create the corresponding user in your SCIM V2 service. The request includes user details and attributes.
- WhyLabs SCIM service processes: WhyLabs SCIM Service receives the SCIM request, validates it, and creates the user based on the provided attributes.
User updates:
- Provisioner initiates: When a user's attributes are updated within the automated provisioner, such as a change in the user's email or department, the provisioner sends a SCIM update request to the SCIM V2 service.
- WhyLabs SCIM service processes: WhyLabs SCIM Service processes the update request, modifying the corresponding user's attributes accordingly.
Group membership changes:
- Provisioner initiates: If a user's group memberships change within the provisioner (user added to/removed from groups), the provisioner sends SCIM requests to update the group memberships.
- WhyLabs SCIM service processes: WhyLabs SCIM Service receives these group membership update requests and adjusts the user's group memberships accordingly.
User Deprovisioning:
- Provisioner initiates: When a user is offboarded or deactivated in the provisioner, the provisioner generates a SCIM request to deactivate or delete the corresponding user in your WhyLabs SCIM Service.
- WhyLabs SCIM service processes: WhyLabs SCIM Service processes the deprovisioning request, deactivating or deleting the user and updating their status.
Error handling and logging:
- Both the automated provisioner and WhyLabs SCIM Service should have mechanisms to handle errors, retries, and logging. This ensures that provisioning operations are reliable and transparent.
Synchronization intervals:
- The automated provisioner may periodically synchronize user and group data with the WhyLabs SCIM V2 service to ensure data consistency. This synchronization interval should be configured based on organizational needs.
The specific steps, configurations, and settings can vary depending on the automated provisioner being used.
Authentication
Before making any SCIM requests, ensure you have appropriate authentication credentials. The WhyLabs SCIM service uses token-based authorization and required a WhyLabs API token that has been created with account management scope. A suitable token can be generated by Administrators using the Access Token UI in the account organization.
Tokens generated in other organizations grant no access outside of the specific organization. Only an account API token can be used to manage other organizations.
The account API token only allows provisioning of users and memberships in the account organization and its managed organizations. It cannot be used for other administration or user tasks within those managed organizations.
Endpoint URLs
SCIM V2 requests are sent to specific endpoint URLs that correspond to different resource types:
- Users:
https://api.whylabsapp.com/scim/Users
- Groups:
https://api.whylabsapp.com/scim/Groups
HTTP Methods
SCIM V2 uses standard HTTP methods to perform CRUD operations:
GET
: Retrieve resources or search for resourcesPOST
: Create new resourcesPUT
: Update existing resourcesPATCH
: Update specific attributes of existing resourcesDELETE
: Delete resources
Request Headers
Include the necessary headers in your requests:
Authorization
: Used for authentication, in the form of "Bearer [Token]".Content-Type
: Specify the content type of the request body, set toapplication/scim+json
orapplication/json
.Accept
: Set toapplication/scim+json
orapplication/json
to indicate the desired response format.
Response Handling
SCIM responses include standard HTTP status codes and a JSON payload. The payload structure follows the SCIM schema for the corresponding resource type.
Error Handling
SCIM V2 uses standard HTTP status codes and includes error details in the response payload. Refer to the SCIM specification for information about common error codes and their meanings.
SCIM User Attributes
Required SCIM User Attributes
Only a single attribute needs to be provided by the provisioner for successful WhyLabs user provisioning.
userName
: The unique username for the user. This must be set to the user's email, and will be verified if the user is not already registered with WhyLabs.
A SCIM create user request will return a unique id
for the user, which the provisioner must use in subsequent
requests.
Optional SCIM User Attributes
WhyLabs supports the following optional SCIM user attributes, which are required by some provisioners:
name
: A complex attribute representing the user's name, includinggivenName
(first name) andfamilyName
(last name). This attribute is supported because it is required by some provisioners. It is not used by WhyLabs itself.emails
: An array of email addresses associated with the user. This attribute is supported because it is required by some provisioners. It is not used by WhyLabs itself.active
: A boolean indicating whether the user account is active. This attribute is used by some provisioners instead of the DELETE action. If a user is set to inactive, WhyLabs will delete any memberships associated with that user within the account.externalId
: A unique ID by which the user is known to the provisioner.
We recommend only including these attributes if required to do so by your provisioner.
Request Examples
Listing Account Users
This request will retrieve up to 100 account users, starting from the first user. Pagination parameters are optional.
GET https://api.whylabsapp.com/scim/Users?startIndex=1&count=100
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
The response looks like:
{
"Resources": [
{
"id": "user-12358495436789576954786047676457ddacc245436556756970678667651234",
"active": true,
"userName": "[email protected]",
"groups": [
{
"value": "org-12A4A6:member",
"display": "org-12A4A6:member",
"type": "direct"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"meta": {
"resourceType": "User",
"location": "https://api.whylabsapp.com/scim/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234"
}
},
...
}
]
}
Creating a User
This request will create a new user with the specified userName (email). Other supported optional SCIM attributes may be included in the request.
POST https://api.whylabsapp.com/scim/Users?startIndex=1&count=100
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"[email protected]"
}
A successful response looks like:
{
"userName": "[email protected]",
"id": "user-12358495436789576954786047676457ddacc245436556756970678667651234",
"active": true,
"meta": {
"location": "https://api.whylabsapp.com/scim/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234"
}
}
An unsuccessful response due to the user already existing will have a status code of 409 with a response body like:
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:Error"
],
"detail": "scimgateway[plugin-songbird] Resource email with ID [email protected] already exists.",
"status": "409"
}
Getting a specific User
A specific user can be retrieved using the user's ID:
GET https://api.whylabsapp.com/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234
Content-Type: application/json
Authorization: {{authz}}
A successful response looks like:
{
"id": "user-12358495436789576954786047676457ddacc245436556756970678667651234",
"active": false,
"userName": "[email protected]",
"groups": [
{
"value": "org-12A4A6:member",
"display": "org-12A4A6:member",
"type": "direct"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"meta": {
"resourceType": "User",
"location": "https://api.whylabsapp.com/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234"
}
}
Updating a User
WhyLabs SCIM API supports PUT for updating a full user record and PATCH for updating specific attributes. When using the minimum required user attributes, provisioners may not need to update a user because the userName (email) attribute cannot be changed.
A PUT request with optional attributes looks like:
PUT https://api.whylabsapp.com/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "[email protected]",
"name": {
"firstName": "Test",
"givenName": "User3"
},
"emails": [{
"value": "[email protected]",
"type": "work"
}],
"active": true
}
The response looks like the response in Getting a specific User.
See the section on Deleting a User for an example using PATCH.
Deleting a User
WhyLabs SCIM API supports deleting a user. The request looks like:
DELETE https://api.whylabsapp.com/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
A successful response will return a 204 status.
A provisioner that uses the active
status attribute rather than deleting a user can
update this status using a patch request like:
PATCH https://api.whylabsapp.com/Users/user-12358495436789576954786047676457ddacc245436556756970678667651234
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [{
"op": "replace",
"path": "active",
"value": true
}]
}
The response looks like:
{
"id": "user-12358495436789576954786047676457ddacc245436556756970678667651234",
"active": false,
"userName": "[email protected]",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"meta": {
"resourceType": "User"
}
}
Creating and Deleting Groups
WhyLabs SCIM API does not support creating or deleting groups, because the groups correspond to the organizations within the account and the predefined WhyLabs roles. A POST or DELETE call to the Groups API will return a 400 status code, similar to:
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:Error"
],
"scimType": "mutability",
"detail": "scimgateway[plugin-songbird] deleteGroup error: Deleting groups (whylabs organization:role) is not supported",
"status": "400"
}
Listing all Groups
This request will retrieve the groups corresponding to each role in the account organization and all managed organizations within the account. Groups for roles with no members will be included:
GET https://api.whylabsapp.com/Groups
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
The successful response looks like:
{
"Resources": [
{
"id": "org-12A4A6:admin",
"displayName": "org-12A4A6:admin",
"members": [
{
"value": "user-12358495436789576954786047676457ddacc24543655675697067866765",
"display": "[email protected]"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group"
],
"meta": {
"resourceType": "Group",
"location": "https://api.whylabsapp.com/Groups/org-12A4A6:admin"
}
},
{
"id": "org-12A4A6:member",
"displayName": "org-12A4A6:member",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group"
],
"meta": {
"resourceType": "Group",
"location": "https://api.whylabsapp.com/Groups/org-12A4A6:member"
}
},
{
"id": "org-12A4A6:viewer",
"displayName": "org-12A4A6:viewer",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group"
],
"meta": {
"resourceType": "Group",
"location": "https://api.whylabsapp.com/Groups/org-12A4A6:viewer"
}
},
...
],
"totalResults": 6,
"itemsPerPage": 6,
"startIndex": 1,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
]
}
Getting a specific Group
This request will retrieve a specific group (organization and role):
GET https://api.whylabsapp.com/Groups/org-12A4A6:admin
Accept: application/json
Content-Type: application/json
Authorization: {{authz}}
The response looks like:
{
"id": "org-12A4A6:admin",
"displayName": "org-12A4A6:admin",
"members": [
{
"value": "user-12358495436789576954786047676457ddacc24543655675697067866765",
"display": "[email protected]"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group"
],
"meta": {
"resourceType": "Group",
"location": "https://api.whylabsapp.com/Groups/org-12A4A6:admin"
}
}
Updating Membership of Groups
WhyLabs SCIM API supports updating groups via either PUT or PATCH. A PUT request must contain the full list
of members of the group. Under members
, the value
field is the user ID and the display
field is the userName
(email).
The following request will replace any existing members of group org-789See:member
with the single specified member:
PUT https://api.whylabsapp.com/Groups/org-789See:member
Content-Type: application/json
Authorization: {{authz}}
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"members": [{
"value": "user-12358495436789576954786047676457ddacc245436556756970678667651234",
}]
}
Note that the display name (email) is treated by WhyLabs as immutable and if it is specified in the PUT request, it will be ignored.
{
"id": "org-789See:member",
"displayName": "org-789See:member",
"members": [
{
"value": "user-12358495436789576954786047676457ddacc245436556756970678667651234",
"display": "[email protected]"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group"
],
"meta": {
"resourceType": "Group"
}
}
A SCIM PATCH request to update memberships specifies the values to be added or removed, like this:
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations" : [
{
"op": "add",
"path": "members",
"value": [{
"value": "user-12358495436789576954786047676457ddacc24543655675697067866765"
}]
},
{
"op": "remove",
"path": "members",
"value": [{
"value": "user-56790aecd243564900ac4535685907756877864564875460587068796047bbae"
}]
}
]
}
A successful response looks like:
{
"id": "org-789See:member",
"displayName": "org-789See:member",
"members": [
{
"value": "user-12358495436789576954786047676457ddacc24543655675697067866765",
"display": "[email protected]"
}
],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group"
],
"meta": {
"resourceType": "Group"
}
}
WhyLabs users can only have a single role within an organization. To maintain this constraint and work with automated provisioners, the SCIM API will automatically remove a user from one group and place them in another where needed.