An Introduction to System for Cross-domain Identity Management (SCIM)
What is SCIM?
SCIM stands for “System for Cross-domain Identity Management” and is firstly a standardized way of representing users, groups, and anything related. Secondly, SCIM helps to standardize methods for acting on this data, such as creating, querying, searching, updating, and deleting. In other words, it’s an API model.
But why do standards, such as SCIM, matter?
This image is from the blockbuster movie Jurassic Park (1993). You’re probably wondering how this is relevant. Well, in this movie the characters are chased by velociraptors into a room, but they unfortunately can’t lock the doors as they are controlled by a computer system. Everyone panics, until this girl discovers that the computer system controlling the doors is a UNIX system, which is a standard she is familiar with.
Thanks to this standard she managed to lock the doors and survive – and that’s why standards are so important! Code shouldn’t just work well, it should also be easy to maintain, add to and debug. Using open standards makes code understandable to all developers.
Standards can still be frightening, complex, over engineered, and/or boring. With SCIM, however, all data is represented as JSON and the protocol is built on REST. Also, you’re probably already handling users so there is a pretty good chance that you are familiar with some aspects of SCIM. By the end of this article, you’ll hopefully be able to look at SCIM and similarly say “I know this.”
How to Implement SCIM
SCIM is not meant to replace your existing systems for user management, but rather to act as a standard interface on top of them. These could be anything from SQL databases, LDAP, NoSQL data stores, SOAP, or REST APIs. SCIM has very few requirements as to what needs to be implemented. Therefore, it’s recommended to implement the base features and those that make sense for your company, and scale up as the need arises.
A huge plus of using a standard interface is that there is no need to document each system separately; if you have a unified way for user management, the documentation is in the specification itself. It’s important to note that the SCIM specification focuses on what is needed for user management, not security. Therefore, things like how to secure access to a system and the permissions to access a system are left to other standards like OAuth.
Schema – Also Known as “The Data”
Resource. In SCIM, everything extends from the resource type, and share a set of common attributes. You’re probably already familiar with these set of attributes, since they are common in pretty much all identity management systems. All SCIM types are identified by the schema in the payload, like the
User schema below:
id– Globally unique identifier
externalId– Identifies the source of the data. This could be an ID from your database or a Twitter handle – wherever you got the user or resource from originally
metadata, such as a timestamp for when the resource was created and
lastModified, as well as where you can find it, or the
location(URL) of the given resource.
Here is an example resource as represented in JSON:
Another benefit of SCIM is that you are free to extend these fields with your own schemas or resource types.
Users – As found in the /Users endpoint
Central in all identity management systems is the concept of users, and SCIM is naturally no exception. The core schema defines a set of attributes that should be common for most users, as well as some that may not be as common.
So what is as user?
Within almost all systems handling users, we find some common attributes. Amongst these are:
- Names (first name, last name, etc.)
- Contact (phone numbers, email addresses)
- Locales (time zone, location, etc.)
- Password (never visible in payload, i.e. a “write only” attribute)
Passwords are a bit special in SCIM. It’s an attribute handled in the standard, but you can never view a password when you request a user resource. You can still query and do authentication through SCIM, but you can’t get a list of passwords, or a password to a specific user.
Less common attributes are things like social media or instant messaging handles. For example, the specification even mentions ICQ!
Group – As found in the /Groups endpoint
Groups aren’t really needed for user management, but it’s pretty common so we’ll include it in this article. Groups in SCIM are not much more than a name and a list of members.
SCIM Protocol – Working with Resources
These parts of the SCIM Protocol should be pretty familiar too, since it’s all based on REST:
GET: Fetches an existing resource, either by ID or by search
POST: Sending a Post request to the user’s endpoint creates a new resource
PUT: Replace an existing resource
PATCH: Updates attributes on an existing resource
DELETE: Deletes a resource
Endpoints and Search
Each resource type is represented under an endpoint named after the recourse type: users under
/Users, groups under
/Groups, and so on.
GET request to one of those endpoints lists all resources for that resource type, but naturally you want to have some limitations on entries, pagination, and the current position. Browsing is as simple as passing in the “pagination” parameters (and optionally, sorting) in the request. It’s also possible to show (include/exclude) specific attributes of interest.
GET to retrieve information it’s often not ideal to show passwords or personal IDs in the URL. While
GET requests are RESTful, it exposes parameters in the URL. Adding
/.search to the URL makes it possible to search by
POST as well, which is ideal for sensitive data like credentials or other personal information.
Filtered Search, Querying Resources
One of the most powerful features of SCIM, and one of the most complex, is the ability to send filtered queries. For example, you can say
/Users?filter=username eq “teddy", or in English: show me all users filtered by the username equal to Teddy.
POST requests to
/Users?filter=userName eq "teddy"
/Users?filter=emails.value ew "curity.io" and meta.lastModified lt "2017-01-01T00:00:00Z"
/Users?filter=name.familyName co "O'Malley"
/Users?filter=filter=emails[type eq "work" and value co "@example.com"]
/Groups?filter=displayName eq "Curity" or displayName eq "Twobo"
/?filter=(meta.resourceType eq User) or (meta.resourceType eq Group)
"filter": "userName eq \"teddy\" and password eq \"F&1!b90t111!\""
A sort of meta thing of SCIM is that it also defines what you as a service provider support. You can choose yourself what you want to support. The
/ServiceProviderConfig endpoint is a way to advertise which features are supported by the service provider.
While features like this certainly add additional functionality within niche contexts, not all SCIM features makes sense for all implementations. For example, advertising specific service provider features is a great resource for anyone interacting with your SCIM API.
“I Know This”
Hopefully, you’ve found this article valuable and see that SCIM isn’t all that scary — at least not as scary as being chased by dinosaurs. In the future, the image above likely illustrates what you’ll say the next time you come across a SCIM system.