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.
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.
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.
The SCIM plugin can be located in the Administration Area under Extensions, SCIM 2.0 Integration.
| 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'. |
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.
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. |
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. |
The current system fields are supported:
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.
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 } }
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.
A simple type is simply a string or int value. It simply uses the attribute name.
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).
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":"," }]
Simple single-valued claim.
{ "name": "first_name" }
Claim that has a string array as a value.
{ "name": "groups","type":"array", "delimiter":","}
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}"
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)