文章 How Do I Setup User Provisioning Using SCIM?

SCIM 2.0 is a mechanism where users can be pushed, or provisioned from a third party SCIM client to a SCIM service provider, in this case your site.  In most circumstances this third party SCIM client acts as the authority for user management and registration in the site itself is generally disabled.   It is also designed to be used with single sign-on using OpenID connect, where the identity provider is providing both SCIM and OpenID connect services.  Note SCIM supports users being pushed from an identity provider to your site.  It does not support acting as a SCIM client where users would be pushed back to the identity provider.

Compatibility And Requirements

At this time it is only certified to work with the scim2-client.  The following article is written accounting for expanded support in the future.

Features

  • Push New Users
    • Users provisioned in the SCIM Client will be added as new users to your site
  • Push Profile Updates
    • User profile fields in the SCIM client can be mapped to custom user profile fields based on a JSON mapping format when configured.  See "Attribute Mapping" in the plugin configuration.   Note that even though profile fields can be updated from the user information, these fields are never returned to the client.
  • Push User Deactivation (Or Delete For Supported Clients)
    • When a SCIM client issues a deactivation action, the user will be disapproved in the site.
    • If the client supports deletes, site can react by disapproving the user(default), reassigning content and deleting, or deleting.  See "User Delete Action" in the SCIM plugin configuration.
  • Reactivate Users
    • Users that were previously deactivated can be reactivated(approved in the site).
  • Push Groups as Roles
    • Groups can be pushed to your site as new Site Roles.
  • Push Group Membership As Role Membership
    • Group Membership and removal can be updated in your site roles.
  • Import Users
    • Users can be imported into your SCIM client from your site
  • Import Groups(Roles)
    • Existing site roles can be imported into your SCIM client
      • NOTE:  Importing membership is not currently supported
  • Schema Discovery
    • You can learn more about the SCIM implementation through discovery URLs.
      • {{Limyee Site Url}}/scim/v2/ServiceProviderConfig -This URLwill describe the site SCIM capabilities
      • {{Limyee Site Url}}/scim/v2/ResourceTypes- Describes what resource types are supported by the site and URLs for additional information.
      • {{Limyee Site Url}}/scim/v2/Schemas - Describes the supported schemas for the resource types and URLs for additional information.

Add and Configure the SCIM Client Application

For most systems you must configure SCIM provisioning in the client application.   Consult the client's documentation on how to setup provisioning.  For SCIM clients currently certified to work with your site, you can consult one of the configuration guides below.  Note these are the only platforms currently fully supported.

Configure The SCIM Plugin

The SCIM plugin can be located in the Administration Area under Extensions, SCIM 2.0 Integration.

Options

Option Required Default Description
Email Address is Username No False If the SCIM client presents user name values as email addresses, this should be checked.   To prevent unwilling information disclosure of email addresses, usernames cannot be email addresses in the site.   Email addresses will be derived from the email address by removing the '@domain.com' value and ensuring the remainder is unique in the site by appending incremental numbers as needed.  When checked however, username value for the user will be presented back to the SCIM client with the username set as the email address.
User Delete Action Yes Disapprove User If a SCIM client issues a DELETE request to site, this value determines how the site will react.   You can choose to instead disapprove the user, permanently delete the user, or reassign the content then delete.  If reassign is chosen an additional option is presented to choose to what user which is by default 'Former Member'.

Advanced Profile Mapping

You can use the Mapping Options to map SCIM user attribute information to custom profile fields to a user when they are provisioned.  It is defined using a specific JSON format.   It is important to know that when using this feature, only common attributes and system field information is actually returned to the SCIM client.  Custom profile data is preserved in the site but is not communicated to the client.

Understand the JSON

The configuration object contains three properties defined below.

{
  "attributeMappings": [],
}
Option Description
attributeMappings An array of attribute mappings used to define how user attributes can be mapped to custom profile fields or system fields.

Attribute Mappings

There are two ways to map an attribute, a system field or a custom profile field.  A system field is a constant field in your site, as opposed to a profile field which can be configured specifically for your site.  You can map any field that is a simple value, such as a string, or an array of simple values such as a string list.

A field mapping consists of these fields:

{
    "mapsTo": {  },
    "attributes": [],
    "format": ""
}
Option Description
mapsTo A mapping object that identifies whether you are mapping to a system field or profile field.
claims An array of strings that defines the attribute names or paths to be used to set the value of the mapTo field.  When a format is not specified and multiple attributes are specified, they are concatenated together using a space, in the order defined.
format Defines how multiple attributes are joined, or adds additional data to an existing attribute. It is a single string where {attributeId} defines the claim to be used.

Mapping a System Field

The current system fields are supported:

  • displayName:  The display name of the site user.

When defining a system field the following JSON format is added to the mapsTo field:

  • "mapsTo": { "systemField": "displayName" }
    

The "systemField" property is all that is required and must conform to an id of pre-defined system field as defined above.

Custom Profile Fields

When not using a system field, you can specify a custom profile field.   If the profile field exists, it's value will be managed by the OpenID Connect provider.  If it does not exist, it will be created the first time a value is attempted to be written.

"mapsTo": {"profileField":{"key": "profilrField_key", "label": "FieldLabel","fieldType": "Plain Text","searchable": true } }
  • key:  This value is used as a profile field key.  It will map to an existing field, or create one if it does not exist.
  • label:  The profile field label, used when creating a new field.   It is how the user interface will display the field.
  • fieldType:  The field type of the profile field.  'Palin Text; and 'Comma-separated List' are supported for array fields.
  • searchable: Defines whether the field will be searchable.

Attributes Property

You can specify one or more attributes for a 'mapsTo' field.  When more than one attributeis specified, the values are concatenated by a space in the order defined into the 'mapsTo' field if a format is not specified. An attribute can be a simple type, a complex type, or an array of simple values or complex types.  Depending on the type, the 'attribute' property value varies.   Refer to the user schema for more information on what fields are available, compared to what your SCIM client is configured to send.

Mapping a Simple Type

A simple type is simply a string or int value.  It simply uses the attribute name.

Mapping a ComplexType

A complex type is a single value presented as a JSON object.  It is identified using the main attribute name, then  a period, then the sub attribute name (main.subAttribute). 

Mapping a Complex Array Type

A simple array type is an array of simple values.  You must specify a single value by using a query

 "claims": [ {"name": "first_name" }, { "name": "emails, "type":"array","delimiter":"," }]
  • name:  The name of the claim as presented in the token.   It is always required.
  • type:  If the claim value is an array of string values, specify 'array'
  • delimiter:  Only for array types, this is the value used to concatenate the array values. By default it is a comma(',').

Simple single-valued claim.

{ "name": "first_name" }

Claim that has a string array as a value.

 { "name": "groups","type":"array", "delimiter":","}

Formatting

You can choose how the claim value(s) are presented using the format property.  It is a static string with tokens formatted as {claimName} where claim name is the name as defined in the claims area.  This is useful when multiple claims are specified. The value of the claim is substituted for the token as presented, with the exception of arrays which will be presented based on how the delineation is defined in the claim definition.

Single value format

"format":"My name is {first_name}"

Multiple attributes

"format":"{last_name}, {first_name}"

scim2-client Sample

import base64
import datetime

from httpx import Client
from httpx import Timeout
from scim2_client.engines.httpx import SyncSCIMClient
from scim2_models import SearchRequest
from scim2_models import PatchOp, PatchOperation
from scim2_client import SCIMResponseErrorObject

# API Token, format as {apiKey}:{username}
api_token = "s8bxe182l57t7ouugx21p:admin"

token_bytes = api_token.encode('utf-8')
encoded_bytes = base64.b64encode(token_bytes)
base64_token = encoded_bytes.decode('utf-8')

client = Client(
    base_url="https://your_site/scim/v2",
    headers={
        "Rest-Authorization-Method": "API",
        "Rest-User-Token": "{token}".format(token=base64_token)
        },
    timeout=Timeout(timeout=60.0)
)
scim = SyncSCIMClient(client)
scim.discover()
User = scim.get_resource_model("User")

new_username = "kitty"
new_user_password = "123456"
new_user_email = "samlj@example.com"
update_username = "mimi"

# Create resources
user = User(user_name=new_username, password=new_user_password, emails=[{"value":new_user_email,"primary":"true"}])
try:
    scim.create(user)
except SCIMResponseErrorObject as exc:
    error = exc.to_error()
    print(error.detail)

# Query resources, only support eq(equal) as operator, and userName as field in filter
response = scim.query(User, query_parameters=SearchRequest(filter='userName eq "{username}"'.format(username=new_username)))
for user in response.resources:
    print(user.user_name)

# Query resources
user = scim.query(User, user.id)
assert user.user_name == new_username
# assert user.meta.last_modified == datetime.datetime(
#     2026, 6, 22, 1, 8, 17, 610000, tzinfo=datetime.timezone.utc
# )


# Update resources
user.display_name = update_username
user = scim.replace(user)
assert user.display_name == update_username
# assert user.meta.last_modified == datetime.datetime(
#     2026, 6, 22, 1, 8, 17, 610000, tzinfo=datetime.timezone.utc
# )

# Modify resources, the value must defined as an object (array).
patch = PatchOp[User](operations=[
    PatchOperation(op=PatchOperation.Op.replace_, value={"active": False})
])
response = scim.modify(User, user.id, patch)

# Delete resources
scim.delete(User, user.id)