SCIM#
The User Management Service is based on the SCIM 2.0 protocol which is a RESTful protocol for user and resource management.
Up to three resource types are currently exposed by Curity, depending on how the user management profile has been configured. Every resource is represented with a unique ID, and retrieving a resource is a simple GET operation.
Users#
After having configured a user account data source on your user management profile, the /Users endpoint will be made available under your user management endpoint.
Retrieving a user with GET#
GET /um/Users/VVNFUjowODM2Mjg5MGE4ZTQ0YTA3YTRlOWIzNjhhYmM5ZGNhYg HTTP/1.1
Host: login.example.com
Authorization: Bearer 21b652ed-5906-451a-a2a2-681bf099dba7
Accept: application/scim+json
{
"active": true,
"userName": "teddie",
"phoneNumbers": [
{
"value": "456-555-555",
"primary": true
}
],
"emails": [
{
"value": "teddie@example.com",
"primary": true
}
],
"meta": {
"resourceType": "User",
"created": "1970-01-01T00:02:03Z",
"lastModified": "1970-01-01T00:20:34Z",
"location": "https://login.example.com/um/Users/VVNFUjowODM2Mjg5MGE4ZTQ0YTA3YTRlOWIzNjhhYmM5ZGNhYg"
},
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"name": {
"familyName": "Bear",
"givenName": "Ted"
},
"id": "VVNFUjowODM2Mjg5MGE4ZTQ0YTA3YTRlOWIzNjhhYmM5ZGNhYg"
}
Searching for a user#
Each resource has a server assigned ID. For a user this is not necessarily the same ID as the username. Therefore, it may be required to search for the user instead of performing a GET directly. In SCIM 2.0, a search can be done directly on the Users endpoint as a query, or if sensitive data is sent as search parameters, the query can be posted to the .search endpoint under users.
Example of a search query towards the .search endpoint#
GET /um/Users?filter=userName+eq+\"teddie\" HTTP/1.1
Host: login.example.com
Accept: application/scim+json
Authorization: Bearer 6e6c3a1b-a12f-4451-b065-2441808c6cec
The same query can be done using a POST:
POST /um/Users/.search HTTP/1.1
Host: login.example.com
Accept: application/scim+json
Authorization: Bearer ec2979e4-f766-4c79-85f9-58f6c72e224f
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:SearchRequest"],
"filter": "userName eq \"teddie\""
}
Both queries will render a responds on the form:
{
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 50,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"id": "VVNFUjowODM2Mjg5MGE4ZTQ0YTA3YTRlOWIzNjhhYmM5ZGNhYg",
"userName": "teddie",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"name": {
"familyName": "Bear",
"givenName": "Ted"
},
"emails": [
{
"value": "teddie@example.com",
"primary": true
}
],
"phoneNumbers": [
{
"value": "456-555-555",
"primary": true
}
],
"active": true,
"meta": {
"resourceType": "User",
"created": "1970-01-01T00:02:03Z",
"lastModified": "1970-01-01T00:20:34Z",
"location": "https://login.example.com/um/Users/VVNFUjowODM2Mjg5MGE4ZTQ0YTA3YTRlOWIzNjhhYmM5ZGNhYg"
}
}
]
}
Searching for users matching criteria#
It is also possible to search for users and attributes matching certain criterias.
POST /um/Users/.search HTTP/1.1
Host: login.example.com
Accept: application/scim+json
Authorization: Bearer ec2979e4-f766-4c79-85f9-58f6c72e224f
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:SearchRequest"],
"filter": "active eq true",
"attributes" : ["userName", "emails.value"]
}
The query searched for all active users but added the attributes filter, asking for only userName and emails.value in the response.
{
"totalResults": 7,
"startIndex": 1,
"itemsPerPage": 50,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"id": "VVNFUjowODM2Mjg5MGE4ZTQ0YTA3YTRlOWIzNjhhYmM5ZGNhYg",
"userName": "teddie",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"emails": [
{
"value": "teddie@example.com"
}
]
},
{
"id": "VVNFUjozMGZlNDk5NzJmZDg0MDc2YjEzNWUxYjNkNjEzNTI4Ng",
"userName": "larsdoe",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User"
],
"emails": [
{
"value": "lars.doe@example.com"
}
]
}
]
}
Creating a user#
Passwords#
A user resource may contain a password. As shown this can be set when creating a new user, or updated when performing a PATCH on a user resource. However, it is not possible to retrieve a password back once it has been set. This is by design; all password parameters will be excluded in the response even if asked for.
To use passwords for authentication, the .search endpoint can be used with a filter query. When passing in a password to the filter, the server will use the configured credential manager, to validate the password. This means that appropriate hashing will be applied to the password.
It is not possible to perform advanced queries at the same time as the password parameter is presented in the filter statement. The filter is expected to ask for things like userName eq "teddie" and password eq "Password1".
This should be used when the SCIM server is used as backend for other services to authenticate user credentials.
POST /um/Users/.search HTTP/1.1
Host: login.example.com
Accept: application/scim+json
Authorization: Bearer ec2979e4-f766-4c79-85f9-58f6c72e224f
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:SearchRequest"],
"filter": "userName eq 'teddie' and password eq 'Password1'",
"attributes" : ["userName", "emails.value"]
}
Devices#
After having configured a device data source on your user management profile, the /Devices endpoint will be made available under your user management endpoint.
Listing devices#
GET /um/Devices HTTP/1.1
Host: login.example.com
Authorization: Bearer 21b652ed-5906-451a-a2a2-681bf099dba7
Accept: application/scim+json
{
"totalResults": 5,
"startIndex": 1,
"itemsPerPage": 50,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"id": "REVWSUNFOjE",
"deviceId": "device1",
"accountId": "VVNFUjo2DENDOTRDRTQ1NkE3MDEzRTA1MzAyMDAxMkFDNTM0NCAgICA",
"externalId": "12345",
"alias": "My tablet",
"formFactor": "ff1",
"deviceType": "tab",
"owner": "VVNFUjpqb2huZG9l",
"expiresAt": "2022-01-01T00:00:05Z",
"meta": {
"resourceType": "Device",
"created": "1999-11-30T18:22:30Z",
"lastModified": "1970-01-01T00:00:01Z",
"location": "https://login.example.com/um/Devices/REVWSUNFOjE"
},
"schemas": [
"urn:se:curity:scim:2.0:Devices"
]
}
]
}
Delegations#
After having configured a token data source on your user management profile, the /Delegations endpoint will be made available under your user management endpoint.
If enabled, it is highly recommended to configure the same token data source as the one used by the referenced OAuth profile.
Listing and searching delegations#
Depending on the authorization policies configured on the user management endpoint, an access token will either grant admin access or user access, the former listing all issued delegations and the latter those that belong to the subject present in the access token.
GET /um/Delegations HTTP/1.1
Host: login.example.com
Authorization: Bearer 21b652ed-5906-451a-a2a2-681bf099dba7
Accept: application/scim+json
{
"totalResults": 7,
"startIndex": 1,
"itemsPerPage": 50,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"sub": "johndoe",
"clientId": "client-one",
"active": true,
"externalId": "15dd2133-44e8-4e2f-a789-5f54d1ea28d9",
"userName": "johndoe",
"meta": {
"resourceType": "Delegation",
"created": "2018-06-04T11:27:11Z",
"lastModified": "2018-06-04T11:27:11Z"
},
"scope": "openid",
"schemas": [
"urn:se:curity:scim:2.0:Delegation"
],
"claims": {
"subject": {
"accountId": "6DCC94CE456A7013E053020012AC5344",
"userName": "johndoe",
"subject": "johndoe"
},
"context": {
"auth_time": 1528111631
}
},
"id": "REVMRUdBVElPTjoxNWRkMjEzMy00NGU4LTRlMmYtYTc4OS01ZjU0ZDFlYTI4ZDk",
"exp": 1528115231,
"iat": 1528111631,
"status": "issued"
}
]
}
For searching/filtering specific delegations the SCIM filter parameter may be used.
/um/Delegations?filter=status eq "revoked"
/um/Delegations?filter=scope co "openid"
/um/Delegations?filter=not(scope eq "write") and userName sw "my-company"
External ID#
externalId maps to the internal delegationId. delegationId is in tokens, so to find out what delegation a token stems from, find the delegationId claim, and use this filter:
/um/Delegations?filter=externalId eq "15dd2133-44e8-4e2f-a789-5f54d1ea28d9"
Custom claims#
Custom claims that are added to a token will be represented by the customClaims object.
{
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 50,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"sub": "johndoe",
"clientId": "client-one",
"active": true,
"externalId": "15dd2133-44e8-4e2f-a789-5f54d1ea28d9",
"userName": "johndoe",
"meta": {
"resourceType": "Delegation",
"created": "2018-06-04T11:27:11Z",
"lastModified": "2018-06-04T11:27:11Z"
},
"scope": "openid",
"schemas": [
"urn:se:curity:scim:2.0:Delegation"
],
"claims": {
"subject": {
"accountId": "6DCC94CE456A7013E053020012AC5344",
"userName": "johndoe",
"subject": "johndoe"
},
"context": {
"auth_time": 1528111631
}
},
"customClaims": {
"email": "john@doe.com",
"employeeNumber": 54321
},
"id": "REVMRUdBVElPTjoxNWRkMjEzMy00NGU4LTRlMmYtYTc4OS01ZjU0ZDFlYTI4ZDk",
"exp": 1528115231,
"iat": 1528111631,
"status": "issued"
}
]
}
Custom data#
Custom data added to a delegation, using a token procedure, will be represented by the customData object.
If sensitive data is added to the delegation using a token procedure, it will be returned in the customData object.
Consider using an attribute authorization manager to filter out sensitive data.
Given a token procedure adding custom data to a delegation:
function result(context) {
var responseData = {
state: context.providedState,
iss: context.issuer
};
var issuedAccessToken = null;
var issuedDelegation = null;
var accessTokenData = context.getDefaultAccessTokenData();
var delegationData = context.getDefaultDelegationData();
// Add a few custom data to the delegation.
delegationData.myProperty = "myValue";
delegationData.myMapProperty = {key1: "value1"};
issuedDelegation = context.delegationIssuer.issue(delegationData);
issuedAccessToken = context.accessTokenIssuer.issue(accessTokenData, issuedDelegation);
responseData.access_token = issuedAccessToken;
responseData.token_type = 'bearer';
responseData.expires_in = secondsUntil(accessTokenData.exp);
responseData.scope = accessTokenData.scope;
return responseData;
}
When retrieving the delegation using the SCIM delegation endpoint, the custom data is exposed through the customData object:
{
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 50,
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:ListResponse"
],
"Resources": [
{
"sub": "johndoe",
"clientId": "client-one",
"active": true,
"externalId": "15dd2133-44e8-4e2f-a789-5f54d1ea28d9",
"userName": "johndoe",
"meta": {
"resourceType": "Delegation",
"created": "2018-06-04T11:27:11Z",
"lastModified": "2018-06-04T11:27:11Z"
},
"scope": "openid",
"schemas": [
"urn:se:curity:scim:2.0:Delegation"
],
"claims": {
"subject": {
"accountId": "6DCC94CE456A7013E053020012AC5344",
"userName": "johndoe",
"subject": "johndoe"
},
"context": {
"auth_time": 1528111631
}
},
"customData": {
"myProperty": "myValue",
"myMapProperty": {
"key1": "value1"
}
},
"id": "REVMRUdBVElPTjoxNWRkMjEzMy00NGU4LTRlMmYtYTc4OS01ZjU0ZDFlYTI4ZDk",
"exp": 1528115231,
"iat": 1528111631,
"status": "issued"
}
]
}
It is highly recommended to configure a authorization manager when using the SCIM server to limit access to the API to clients with certain scopes enabled.
Groups#
The Curity Identity Server supports the SCIM 2.0 Groups endpoint, when groups are managed by an Entity Manager and not stored inside accounts.
Configuration#
To enable the SCIM 2.0 Groups endpoint support:
- The User Management profile needs to be configured with an Account Manager , instead of being configured to directly use a Data Source .
- The selected Account Manager needs to be configured with an Entity Manager with groups support.
- An Entity Manager has groups support when linked to a Entity Schema with group support.
- Finally, the
group-managementconfiguration setting must be enabled in the User Management profile.
Behavior and limitations#
The SCIM 2.0 Groups endpoint supports the following operations:
- Group creation.
- Group creation cannot include more than
100items in thememberslist. - To define a group with more than
100members, start by creating the group with100or fewer members and then apply multiple patches (see below) to add new members.
- Group creation cannot include more than
- Group retrieval by ID, which can include the
membersattribute in the group representation, including themembers.displaysub-attribute.- The
memberslist attribute is truncated to100items. The subattributemeta.warning.membersis present when such truncation happens.
- The
- Group listing via a query.
- Group listings never include the
membersattribute. Obtaining detailed group membership information requires retrieving a group by ID.
- Group listings never include the
- Group mutation via the
PATCHHTTP method.- Group mutation via the
PUTHTTP method is not yet supported. - A group patch is limited to
100member mutations. - The attribute configured in the Entity Schema to be the source of the group entity value (either
displayNameorexternalId) cannot be updated or removed.
- Group mutation via the
- Group deletion.
When the SCIM 2.0 Groups endpoint is enabled, meaning that groups are being managed by an Entity Manager , then the SCIM 2.0 Users endpoint is affected in the following ways:
- User retrieval by ID will include the groups managed by the Entity Manager .
- The
groupslist attribute is truncated to100items. The subattributemeta.warning.groupsis present when such truncation happens.
- The
- User listing will have an empty
groupsattribute. - User creation or mutation will ignore any value present in the
groupsattribute.- This follows the SCIM 2.0 defined behavior, where the User’s
groupsattribute is considered to be read-only.
- This follows the SCIM 2.0 defined behavior, where the User’s
- User deletion will be rejected if the user is in more than
50groups.- In order for the user to be successfully deleted, first remove the account from the groups, via patch requests to the Groups endpoint, and then remove the account.
Sorting#
Since Curity version 9.3.0, SCIM 2.0 Sorting parameters are supported. When using a JDBC Data Source, only attributes that are indexed by the Data Source can be used for sorting. Other Data Sources may have other limitations, or even not support sorting at all. For example, DynamoDB only supports sorting accounts by userName (any other sortBy values are ignored).
/um/Users?filter=userName sw "abc"&sortBy=userName&sortOrder=ascending
/um/Users?filter=userName sw "abc"&sortBy=meta.created