The SCIM (System for Cross-domain Identity Management) API is an open RESTful specification that supports standard CRUD operations which can be used to synchronize identity resources across multiple independent systems or domains. These operations are typically performed using common HTTP methods such as POST, GET, PUT, PATCH, and DELETE.
However, the SCIM protocol doesn’t just define programmatic API endpoints but also specifies an interoperable JSON-based schema that any SCIM-compliant Client (identity providers) and cloud-based Service Provider (SaaS applications) can use to provision and de-provision user/employee accounts and attributes, ensuring identity data remains consistent and up-to-date across both systems.
Let’s consider a large enterprise organization that probably uses hundreds of SaaS applications for work and needs to manage different access levels and permissions for thousands or even millions of users and employees across these tools.
Without SCIM, the IT department would need to manually create and update user accounts in each application whenever there is a new hire, a role change, or a departure. The thing is, this kind of manual provisioning is time-consuming and almost always prone to errors and data inconsistencies.
In this article, you’ll learn about the SCIM API as defined by the IETF RFC 7644 standard specification. We’ll explore the SCIM schema and data model, and discuss all the REST endpoints and HTTP operations/methods that can be used to exchange data between SCIM clients and SaaS applications. As an enterprise SaaS provider, you’ll learn how to support SCIM without expending valuable engineering time on a custom SCIM setup that may take months or even years to implement.
Every SCIM setup relies on a bidirectional client-server architecture where an identity provider (IdP) typically serves as the SCIM Client and a SaaS application or intranet system serves as the SCIM Service Provider (or vice versa), depending on the data flow per request.
SCIM Clients are typically identity providers like Okta, Entra ID, or Google Workspace that centrally manage user/employee identities within an organization. They can connect to the SCIM protocol to synchronize these user identity attributes with the Service Providers (SPs) that require this data to provision new user accounts and manage access permissions.
SCIM Clients perform CRUD operations on user and group resources by sending HTTP requests to Service Providers via standardized SCIM API endpoints. However, in cases where a Service Provider needs to initiate a SCIM request to an IdP, it will act as the SCIM Client while the IdP functions as the SCIM server.
In a standard SCIM architecture, a Service Provider acts as the SCIM server because it’s responsible for exposing RESTful API endpoints and processing HTTP requests from the SCIM Client. Service Providers could be SaaS applications such as Vercel, Notion, GitHub, or Linear which are capable of consuming and responding to CRUD requests, ensuring users/employees have the appropriate account privileges within their respective systems.
The SCIM data model defines a standardized structure for representing core SCIM resources and their associated attributes.
SCIM resources are categorized into two main resource types such as "User" and "Group" which are maintained by service providers. These resource types define the resource name, endpoint URL, schema, and other metadata that describe where a resource is located and how it is managed.
These resource types, whether User, Group, or any custom/extended resource type, are represented by JSON objects that can be accessed and managed via the SCIM protocol, either individually or in bulk.
On the other hand, resource attributes are the individual pieces of information that describe the properties or characteristics of a resource in the SCIM data model. They can have a single value or contain multiple or complex values, depending on the attribute's definition and data type.
For example, the userName attribute of a User resource is typically a single string value representing the user's unique identifier. Other examples of single-valued attributes include displayName, externalId, and boolean flags like active.
However, some resource attributes are designed to hold multiple values which are represented as arrays or lists. These attributes are often used to store collections of related data. For example, the emails attribute of a User resource can contain multiple email addresses associated with a particular user. Similarly, the members attribute of a Group resource is a list of user IDs representing the group’s members.
Here's an example of how a multi-valued attribute might be represented in a SCIM resource:
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "john.doe",
"name": {
"givenName": "John",
"familyName": "Doe"
},
"emails": [
{
"value": "john.doe@example.com",
"type": "work"
},
{
"value": "jdoe@personal.com",
"type": "home"
}
]
}
In this example, the emails attribute is a multi-valued attribute, represented as an array of email objects, each containing a value and a type.
The SCIM data model is designed to be extensible, allowing service providers to define and use their custom resources or attributes, while maintaining interoperability with other SCIM-compliant systems. As such, service providers can define their custom resource attributes to extend the SCIM schema and include additional information relevant to their specific use cases.
While Users and Groups are resources within the SCIM data model, schemas are a collection of the attributes associated with these resources. In essence, the SCIM schema is a standardized JSON-based structure that represents the attributes and data types (e.g., string or boolean) that are associated with a resource. As we’ve seen thus far, the schema also specifies whether an attribute can hold a single value, multiple values, complex values, and other metadata.
The SCIM data model defines three sets of predefined schemas that describe the structure and attributes of user and group resources, such as the User schema, Group schema, and Enterprise User schema.
The User schema is a predefined schema that describes the standard set of attributes for representing a user resource across different systems. The Group schema is another core schema that describes the standard set of attributes for representing a group resource (collections of users).
// Sample JSON representation of a SCIM Group Schema
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "7f6a725e-1fd2-4fb3-a453-3d89f2a9bcf1",
"displayName": "Developers",
"members": [
{
"value": "a74c4e10-12f9-46e5-91e2-bc8f979c735f",
"$ref": "https://example.com/scim/v2/Users/a74c4e10-12f9-46e5-91e2-bc8f979c735f",
"display": "John Doe"
},
{
"value": "f45e6a2b-d9f1-4c23-b785-e291f6b0d9e1",
"$ref": "https://example.com/scim/v2/Users/f45e6a2b-d9f1-4c23-b785-e291f6b0d9e1",
"display": "Jane Smith"
}
],
"meta": {
"resourceType": "Group",
"created": "2024-06-19T12:00:00Z",
"lastModified": "2024-06-19T12:00:00Z",
"location": "https://example.com/scim/v2/Groups/7f6a725e-1fd2-4fb3-a453-3d89f2a9bcf1",
"version": "W\/\"8149y75g1uio207\""
}
}
On the other hand, the Enterprise User schema is an example of how the SCIM data model can be extended to include additional attributes that are relevant to specific use cases or environments. It’s an extension schema that builds upon the core User schema by including additional attributes commonly used in enterprise environments. It includes attributes related to organizational information, such as employeeNumber, costCenter, organization, division, and others.
// Sample JSON representation of an Enterprise User Schema
{
"schemas": ["urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],
"employeeNumber": "EMP12345",
"costCenter": "CC123",
"organization": "XYZ Corp",
"division": "Denver Office",
"department": "Engineering",
"manager": {
"value": "5a8e2f84-618b-4a79-a78c-abcde1234567",
"display": "Alice Johnson"
},
"meta": {
"resourceType": "EnterpriseUser",
"created": "2024-06-19T12:00:00Z",
"lastModified": "2024-06-19T12:00:00Z",
"location": "https://example.com/scim/v2/Users/abc123",
"version": "W/\"8149y75g1uio207\""
}
}
The use of standardized SCIM schemas promotes interoperability by providing a common language for describing and validating user and group data across different systems and domains. It allows SCIM clients and service providers to exchange and interpret identity data in a consistent manner while allowing for extensibility and customization as needed.
The SCIM protocol is a standardized set of RESTful APIs and associated specifications that define how SCIM clients and service providers communicate and exchange identity data based on the SCIM data model and schemas. The protocol is designed to be lightweight and easily consumable by different systems and programming languages.
It utilizes JSON payloads to share identity resources via SCIM messages that contain an HTTP header, schemas attribute, and URI. These components convey protocol-specific parameters that are related to any SCIM request or response.
According to the IETF RFC 7644 open specification, the SCIM protocol defines a set of RESTful endpoints (URLs) that support standard HTTP methods (GET, POST, PUT, PATCH, DELETE) for performing CRUD operations on user and group resources.
SCIM clients typically use GET requests to retrieve data from a service provider, while POST requests are used for creating resource objects or attributes, making bulk modifications to resources, and searching for resource types within a resource endpoint. PUT requests are used to replace attributes within resources, PATCH requests are used to update attributes, and DELETE requests are used to remove resources permanently.
We’ve compiled a comprehensive table that outlines the RESTful endpoints defined by the SCIM protocol and the kind of HTTP operations that can be performed against them. You can find the table below.
To create new resources via the SCIM protocol, such as users or groups, the SCIM client has to send an HTTP POST request to the appropriate resource endpoint (e.g., /Users or /Groups). The request body must contain a JSON representation of the resource according to the relevant SCIM schema.
POST /v2/Users HTTP/1.1
Accept: application/json
Host: example.com
Content-Type: application/json
Authorization: Bearer h480djs93hd8
{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"externalId":"jdoe",
"userName":"jdoe",
"name":{
"familyName":"John",
"givenName":"Doe"
}
}
When the service provider successfully creates the new resource, it has to return an HTTP 201 Created response with the newly created resource in the response body. The HTTP Location header typically contains the URI of the new resource and the service provider may include the JSON representation of the meta.location attribute in the response body.
To retrieve an existing resource, the SCIM client has to send an HTTP GET request to the specific resource endpoint (e.g., "/Users/{id}", "/Groups/{id}", or "/Schemas/{id}", where the portion after the resource name ("{id}") represents the resource’s unique identifier).
# Retrieve a specific user by ID
GET /Users/a74c4e10-12f9-46e5-91e2-bc8f979c735f HTTP/1.1
Host: api.example.com
Accept: application/scim+json
Authorization: Bearer k804jkg54ht9
If the resource is found, the service provider typically responds with an HTTP 200 OK status code and includes the JSON representation of the requested resource in the response body. By default, the service provider will only return resource attributes that have their “returned” setting as "always" or "default".
Response:
HTTP/1.1 200 OK
Content-Type: application/scim+json
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"id": "a74c4e10-12f9-46e5-91e2-bc8f979c735f",
"externalId": "ext-123456",
"userName": "jdoe",
"name": {
"formatted": "John Doe",
"familyName": "Doe",
"givenName": "John"
},
"emails": [
{
"value": "jdoe@example.com",
"type": "work",
"primary": true
}
],
"groups": [
{
"value": "c1e13b48-73fb-4be2-91c5-5ec6f7f3f7a1",
"$ref": "https://api.example.com/v2/Groups/c1e13b48-73fb-4be2-91c5-5ec6f7f3f7a1",
"displayName": "Engineering"
}
],
"meta": {
"resourceType": "User",
"created": "2023-03-15T11:23:45Z",
"lastModified": "2024-05-20T08:31:12Z",
"version": "W/\"2e711b5b26d0f64\"",
"location": "https://api.example.com/v2/Users/a74c4e10-12f9-46e5-91e2-bc8f979c735f"
}
}
To query resources, the SCIM client has to send an HTTP GET request to the appropriate resource endpoint, appending query parameters to the request URL to filter or search for specific resources.
Upon receiving the request, the service provider has to process the query parameters and return the matching resources in the response body. The response typically includes an HTTP 200 OK status code and a JSON representation of the filtered resource list, adhering to the relevant SCIM schema. However, if no resources match the specified query parameters in the request, the service provider will return an HTTP 200 OK response with an empty resource list in the response body.
You can also use query parameters to filter resources based on attribute values, resource metadata, or any other criteria supported by the ServiceProviderConfig endpoint. For example, the client can write a filter query parameter to retrieve all users with a specific email domain (e.g., /Users?filter=emails.value+sw+"%40example.com"), or to search for groups that contain a specific string in their display name (e.g., /Groups?filter=displayName+co+"Marketing").
# Retrieve all users with a specific email domain
GET /Users?filter=emails.value+sw+"%40example.com" HTTP/1.1
Host: api.example.com
Accept: application/scim+json
Authorization: Bearer k804jkg54ht9
# Retrieve groups containing "Marketing" in their display name
GET /Groups?filter=displayName+co+"Marketing" HTTP/1.1
Host: api.example.com
Accept: application/scim+json
Authorization: Bearer <token>
The security of a SCIM setup heavily depends on the specific implementation in question. While the SCIM protocol doesn’t inherently define standard security mechanisms, it provides guidelines and recommendations for securing the communication between SCIM clients and service providers.
In essence, the overall security of a SCIM implementation doesn’t necessarily depend on the protocol itself, but on the security practices and measures implemented by SCIM clients and service providers.
Implementing SCIM in-house vs using Stytch
Deciding to implement SCIM in-house or utilize a SCIM connector like Stytch depends on several factors such as your organization's specific security and compliance requirements, available engineering resources, and risk tolerance profile.
However, the reality is that building SCIM from scratch requires significant development effort, as you need to handle all aspects of implementing the protocol, including resource management, authentication, authorization, error handling, and more.
Your engineering team will be responsible for maintaining and scaling your SCIM setup as the protocol evolves or your requirements change, which can be resource-intensive. Mind you, your current and even prospective customers may be using different identity providers (SCIM clients) within their companies, and you must be prepared to handle the complexities of integrating with them.
As a SaaS provider, if you plan to offer support for IdPs like Okta, Microsoft Entra ID, Google Workspace, JumpCloud, and OneLogin, you'll need to deeply understand how each provider maps resource attributes and performs SCIM operations, and also ensure your system can handle each provider securely.
If you need a reliable, scalable, and quick-to-deploy solution with zero-to-minimal development and maintenance overhead, leveraging Stytch’s SCIM base connector is likely the better choice. Using Stytch's SCIM base connector URL, enterprise applications can easily connect their IdPs and service providers to exchange SCIM updates in real-time. We provide the relevant SCIM APIs and can process any scale of SCIM requests and responses without any failovers or data loss.
Ready to implement the SCIM protocol using Stytch? Check out our SCIM Docs and start building. If you want to learn more about our extensive auth APIs and SDKs you can check our B2B and B2C docs and sign up for a free developer account.
If you have any questions, please reach out to us at support@stytch.com or schedule a chat with a member of our Solutions Engineering team.