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.

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

Was this helpful?