Using SCIM v1.1 as Data Source#
Examples are not URL encoded, but MUST be encoded according to RFC 3896 section 2.1.
Client Authentication#
The Curity Identity Server can authenticate to a SCIM server using either:
- Mutual TLS
- Basic authentication over one-way TLS
In the first case, the Curity Identity Server proves its identity using an X.509 certificate. This is the strongest means of authentication possible and is recommended. In the latter case, the SCIM server is authenticated to the Curity Identity Server using an X.509 SSL certificate. The Curity Identity Server authenticates to the SCIM server using a shared secret. To keep this credential secure, HTTPS is used to encrypt the traffic between the two entities.
Required SCIM operations#
Authenticating users#
Authenticating users is done using the “filter” option on the /Users resource
GET /Users?filter=userName+eq+"bjensen"+and+password+eq+a_plaintext_password HTTP/1.1
On a successful authentication the SCIM server should respond with a 200 OK a single entry in a list of User objects. This entry contains all the attributes for the User.
- Note that the
passwordattribute NEVER shall be returned from the server. - We assume that userName is a unique attribute for the User.
Example Request#
GET /Users?filter=userName+eq+"bjensen"+and+password+eq+a_plaintext_password+and+active+eq+true HTTP/1.1
Host: example.com
Accept: application/json
Example successful Response#
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Body
{
"totalResults":1,
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extensions:external-ids:1.0"
],
"Resources":[
{
"schemas":["urn:scim:schemas:core:1.0"],
"id":"2819c223-7f76-453a-919d-413861904646",
"externalId":"bjensen",
"meta":{
"created":"2015-08-01T21:32:44Z",
"lastModified":"2015-08-01T21:32:44Z",
"location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646",
"version":"W\/\"e180ee84f0671b1\""
},
"name":{
"formatted":"Ms. Barbara J Jensen III",
"familyName":"Jensen",
"givenName":"Barbara"
},
"userName":"bjensen",
"emails" : [
{"value" : "bjensen@example.com", "primary" : true}
],
"urn:scim:schemas:extensions:external-ids:1.0": {
"externalIds": [
{
"value": "bjensen@example.com",
"type": "domain1",
"description": "Some description"
},
{
"value": "ted@mail.com",
"type": "domain2"
}]
}
}]
}
Example failure to authenticate (incorrect username or password)#
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Body
{
"totalResults":0,
"schemas":["urn:scim:schemas:core:1.0"],
"Resources":[]
}
Responding with a 404 is accepted as long as the response body contains the above information.
Creating Users#
Creating a new User requires the following attributes to be possible to be set
- userName
- password
- email (primary)
- active (true or false, if account verficaction is used, this is set to false on create)
By default the following attributes are also included.
- name
- givenName
- familyName
- phoneNumber (primary but optional)
Other attributes are possible to add in the Create Account form, and will be forwarded according to the SCIM specification to the backend.
Verifying a User Account#
TBD
Fetching user data#
Fetching user data during authentication is done according to the section “Authenticating users”. But to support forgotten username or forgotten password, the ID Server needs to be able to query the Data Source with the following filtering options.
Filter by primary email#
GET /Users?filter=emails.value+eq+"bjensen@example.com"+and+emails.primary+eq+true HTTP/1.1
Host: example.com
Accept: application/json
Successful Response
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Body
{
"totalResults":1,
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extensions:external-ids:1.0"
],
"Resources":[
{
"schemas":["urn:scim:schemas:core:1.0"],
"id":"2819c223-7f76-453a-919d-413861904646",
"externalId":"bjensen",
"meta":{
"created":"2015-08-01T21:32:44Z",
"lastModified":"2015-08-01T21:32:44Z",
"location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646",
"version":"W\/\"e180ee84f0671b1\""
},
"name":{
"formatted":"Ms. Barbara J Jensen III",
"familyName":"Jensen",
"givenName":"Barbara"
},
"userName":"bjensen",
"emails" : [
{"value" : "bjensen@example.com", "primary" : true}
],
"urn:scim:schemas:extensions:external-ids:1.0": {
"externalIds": [
{
"value": "bjensen@example.com",
"type": "domain1",
"description": "Some description"
},
{
"value": "ted@mail.com",
"type": "domain2"
}]
}
}]
}
Failure Response (Not found)
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Body
{
"totalResults":0,
"schemas":["urn:scim:schemas:core:1.0"],
"Resources":[]
}
Responding with a 404 is accepted as long as the response body contains the above information.
If the SCIM Service Provider responds with more than one user matching the filter, the ID server will treat this as an error, and will assume that a user cannot be found based on email.
Filter by userName#
GET /Users?filter=userName+eq+"bjensen@example.com" HTTP/1.1
Host: example.com
Accept: application/json
Successful Response
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Body
{
"totalResults":1,
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extensions:external-ids:1.0"
],
"Resources":[
{
"schemas":["urn:scim:schemas:core:1.0"],
"id":"2819c223-7f76-453a-919d-413861904646",
"externalId":"bjensen",
"meta":{
"created":"2015-08-01T21:32:44Z",
"lastModified":"2015-08-01T21:32:44Z",
"location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646",
"version":"W\/\"e180ee84f0671b1\""
},
"name":{
"formatted":"Ms. Barbara J Jensen III",
"familyName":"Jensen",
"givenName":"Barbara"
},
"userName":"bjensen",
"emails" : [
{"value" : "bjensen@example.com", "primary" : true}
],
"urn:scim:schemas:extensions:external-ids:1.0": {
"externalIds": []
}
}]
}
Failure Response (Not found)
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Body
{
"totalResults":0,
"schemas":["urn:scim:schemas:core:1.0"],
"Resources":[]
}
Responding with a 404 is accepted as long as the response body contains the above information.
Required User Attributes#
To support the basic User model, the following attributes are assumed to exist with the following preconditions
| Attribute Name | Attribute Value | Pre condition |
|---|---|---|
| userName | The given Id of the user (given when logging in) | globally unique |
| password | The password for the user. Provided as plaintext when the account is created or the user resets the password | |
| emails | The email can be used to lookup usernames for users when their username is lost. | Optional. One globally unique email set with the attribute “primary” must exist per user if reset password and forgotten username should be supported. |
| phoneNumbers | If SMS authentication should be used, this attribute must be set for the user | Optional. One “primary” phoneNumber must exist for SMS functions to be available |
externalIds is also assumed to be supported if account linking is desired. See below.
Linking Accounts#
To link account, the service provider must support an extension to the SCIM protocol that allows the SCIM client (i.e., the Curity Identity Server) to set multiple related account IDs for a user. These related IDs will be the ones that are linked to the user’s identity. They can be from any domain or security realm. Therefore, the client will also store the name of the domain from which the linked ID resides.
In particular, the service provider must support an additional multi-valued attribute in the user model. This attribute is called externalIds and is in the urn:scim:schemas:extensions:external-ids:1.0 schema. Each of these attributes has a value, a type, and a description attribute. The value is the foreign user ID (i.e., the one being linked). This is the ID of the linkee in some other security realm. To know which domain the user ID is from, the type will contain the domain or realm of the user. This might be something like facebook, legacy_app_1, etc. Optionally, a description can also be included.
Typically, the user ID that is having these links added to it is the global or primary user ID in your organization, whereas the linked ones are secondary or auxiliary IDs. Linking can be bidirectional, however, and the user ID in the URI may actually be some secondary account ID whereas the linked on is a global account ID. Both use cases are viable.
A sample request and response is shown below:
Headers
PUT /Users/2819c223-7f76-453a-919d-413861904646 HTTP/1.1
Host: example.com
Accept: application/json
Content-Type: application/json
Body
{
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extensions:external-ids:1.0"
],
"id":"2819c223-7f76-453a-919d-413861904646",
"userName":"bjensen",
"externalId":"bjensen",
"name":{
"formatted":"Ms. Barbara J Jensen III",
"familyName":"Jensen",
"givenName":"Barbara",
"middleName":"Jane"
},
"emails" : [
{"value" : "bjensen@example.com", "primary" : true}
],
"urn:scim:schemas:extensions:external-ids:1.0": {
"externalIds": [
{
"value": "bjensen@domain1.com",
"type": "domain1",
"description": "Some description"
}]
}
}
Successful Response
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Location: https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646
Body
{
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extensions:external-ids:1.0"
],
"id":"2819c223-7f76-453a-919d-413861904646",
"userName":"bjensen",
"externalId":"bjensen",
"name":{
"formatted":"Ms. Barbara J Jensen III",
"familyName":"Jensen",
"givenName":"Barbara",
"middleName":"Jane"
},
"emails" : [
{"value" : "bjensen@example.com", "primary" : true}
],
"urn:scim:schemas:extensions:external-ids:1.0": {
"externalIds": [
{
"value": "bjensen@domain1.com",
"type": "domain1"
}]
}
"meta": {
"created":"2011-08-08T04:56:22Z",
"lastModified":"2011-08-08T08:00:12Z",
"location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646",
"version":"W\/\"b431af54f0671a2\""
}
}
Devices#
In many scenarios, devices need to be associated with a particular user account. This is usually the case when 2-factor authentication is deployed. To provide stronger authentication using something the user has, devices of different sorts and types need to be associated with a user account. Afterwards, the devices associated with a user account need to be queried, so that authentication using such devices can be performed. This association and retrieval of devices on a per user basis can be done using the SCIM credential backend with an Account Manager.
Neither version of the SCIM standard provides a way of storing a user’s devices like this. SCIM does provide a flexible extension mechanism that can be used for this purpose, however. Similarly to the schema extensions described in the previous subsection for account linking, a SCIM server must support the following extension if devices are to be stored with user accounts.
To provide these types of device storage capabilities, the SCIM service provide must support a complex type called devices which is in the urn:scim:schemas:extensions:devices:1.0 schema. This list will contain zero or more device objects that are connected with the enclosing user account. Each device will have the following attributes:
| Attribute Name | Required | Explanation and Meaning |
|---|---|---|
| id | Yes | A unique ID of the device for the given type |
| type | Yes | The device type (i.e., make, manufacturer, provider, class) |
| deviceName | Yes | The name of the device (e.g., “my iPad” or “blue key fob”) |
| externalId | No | The identifier or number used externally to recognize the device (e.g., a phone number or a company-provided asset tag) |
| owner | No | The owner of the device which may or may not be the same as the user to which the device is associated. If it is not provided, it is assumed that the associated user is the owner |
| formFactor | No | The form of the device (e.g., laptop, tablet, mobile phone, desktop, other) |
A device also contains various metadata, similarly to the user object itself. Unlike the standard metadata of a user, however, a device can also contain an expiresAt meta property that indicates when the device association to the user expires. This can be very helpful when implementing temporary connections between a user and a device. This sort of temporal association is common when the device is shared amongst a group of users (e.g., in a hospital ward or school).
A sample request and response containing a user’s devices is shown below:
Headers
GET /Users/2819c223-7f76-453a-919d-413861904646 HTTP/1.1
Host: example.com
Accept: application/json
Successful Response
Headers
HTTP/1.1 200 OK
Content-Type: application/json
Location: https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646
Body
{
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extensions:devices:1.0"
],
"meta": {
"created":"2011-08-08T04:56:22Z",
"lastModified":"2011-08-08T08:00:12Z",
"location":"https://example.com/v1/Users/2819c223-7f76-453a-919d-413861904646",
"version":"W\/\"b431af54f0671a2\""
},
"id":"2819c223-7f76-453a-919d-413861904646",
"userName":"bjensen",
"externalId":"bjensen",
"urn:scim:schemas:extensions:devices:1.0": {
"devices": [
{
"id": "456789",
"deviceName": "Blue NFC Yubikey",
"formFactor": "fob",
"type": "yubikey",
"meta": {
"created": "2010-01-23T04:56:22Z",
"lastModified": "2011-05-13T04:42:34Z",
"version": 1,
}
},
{
"id": "AE79F230-CDA0-4248-B85C-F3B43BE4715A",
"externalId": "+1-530-450-5565",
"deviceName": "iPhone",
"formFactor": "phone",
"type": "encapApp1",
"meta": {
"created": "2010-01-23T04:56:22Z",
"lastModified": "2011-05-13T04:42:34Z",
"version": 55,
"expiresAt": "2010-01-23T10:56:22Z"
}
},
{
"id": "4563456",
"deviceName": "MyGoodLaptop",
"formFactor": "laptop",
"type": "smartcardReader1",
"owner": "Acme, Inc.",
"meta": {
"created": "2010-01-23T04:56:22Z",
"lastModified": "2011-05-13T04:42:34Z",
"version": "v22"
}
}]
}
}