Configure SCIM Provisioning with Okta
This guide describes how to configure SCIM provisioning between Okta and AtScale using Keycloak's native SCIM API.
This configuration supports OAuth 2.0 Client Credentials authentication and provides the following user lifecycle operations:
- User provisioning
- User profile updates
- User deactivation and reactivation
- User import from Keycloak
- Core user attribute synchronization
Group creation is supported, but Okta group membership synchronization is not compatible with Keycloak's SCIM API. For more information, see Group provisioning limitations below.
Architecture
Okta acts as the SCIM client and Keycloak acts as the SCIM service provider.
Okta
|
| OAuth 2.0 Client Credentials
|
v
AtScale / Keycloak
|
+-- SCIM API
/auth/realms/atscale/scim/v2
The SCIM endpoint must be reachable from Okta over HTTPS. For the AtScale Keycloak image, the /auth context path is part of the URL and must not be omitted.
Prerequisites
Before configuring SCIM provisioning with Okta, verify that:
- You have administrator access for both Keycloak and Okta.
- AtScale is running Keycloak 26.7.x or later.
- HTTPS access to the SCIM endpoint is available from Okta.
The SCIM endpoint is https://<atscale-host>/auth/realms/atscale/scim/v2, and the OAuth token endpoint is https://<atscale-host>/auth/realms/atscale/protocol/openid-connect/token.
Enable and configure SCIM provisioning in Keycloak
First you must enable and configure SCIM provisioning in AtScale's Keycloak instance.
-
Enable the SCIM API in Keycloak. To do this, add the
scim-apito the Keycloak feature's startup arguments. For example:keycloak:
extraStartupArgs: --import-realm --features=token-exchange,admin-fine-grained-authz:v1,opentelemetry-logs,scim-api --log=console --hostname-backchannel-dynamic trueOnce this has been set, the Keycloak startup log should show:
Preview features enabled: scim-api:v1 -
Enable SCIM for the atscale realm in Keycloak:
-
Log in to Design Center and click Security in the sidebar. Keycloak opens.
-
In the sidebar, under Configure, click Realm settings.
-
On the General tab, enable the SCIM API option.
Ensure the realm representation contains:
{
"scimApiEnabled": true
}
-
-
Create a Keycloak User Profile attribute for the SCIM external ID. SCIM clients use
externalIdas an identifier for the user in the external identity provider. For example:{
"name": "myExternalId",
"displayName": "External ID",
"multivalued": false,
"permissions": {
"view": ["admin"],
"edit": ["admin"]
},
"annotations": {
"kc.scim.schema.attribute": "externalId"
}
}importantThe annotation key must be
kc.scim.schema.attribute. Usingscim.schema.attributewill not work. Keycloak may accept the SCIM request but silently discard theexternalId. -
Create the SCIM client:
-
In the sidebar, click Clients.
-
Click Create client.
-
On the General settings tab, complete the following fields:
- Client type: Leave this set to OpenID Connect.
- Client ID: Enter
scim-client.
-
Click Next.
-
On the Capability config tab, complete the following fields:
- Client authentication: Enable this option.
- Authentication flow: Disable Standard flow (if it is not required for this client), and enable Service accounts roles.
-
Click Next, then click Save.
-
-
Assign the
scim-clientthemanage-usersrole. This provides the permissions required for the SCIM user lifecycle.- Open the
scim-clientyou just created and go to the Service account roles tab. - Click Assign role.
- In the Assign roles to scim-client window, select the
manage-usersrole. - Click Assign.
- Open the
-
Configure the OAuth audience. The Keycloak access token used by the SCIM API must contain the SCIM endpoint as its audience. Okta's OAuth configuration does not provide a separate audience field, so this audience must be added by Keycloak.
To add an Audience protocol mapper to the
scim-client:-
Open the
scim-clientand go to the Client scopes tab. -
Click the
scim-client-dedicatedscope. -
Click Configure a new mapper and select Audience.
-
Complete the following fields:
- Name: Enter a name for the mapper.
- Included Custom Audience: Enter the SCIM base URL,
https://<atscale-host>/auth/realms/atscale/scim/v2. - Add to access token: Enable this option.
-
Click Next, then click Save.
The resulting access token should contain:
"aud": [
"https://<atscale-host>/auth/realms/atscale/scim/v2"
]NoteThe
/authportion of the URL must be included. If the audience does not exactly match the SCIM base URL, Keycloak will return401 Unauthorized. -
-
Obtain the client secret for the
scim-client. You will need this later when configuring Okta.-
Open the
scim-client. -
Go to the Credentials tab and copy the Client Secret.
ImportantDo not regenerate the Client Secret.
-
-
Verify that the SCIM client can obtain a token and access the SCIM API. For example:
TOKEN=$(curl -s -X POST \
https://<atscale-host>/auth/realms/atscale/protocol/openid-connect/token \
-d grant_type=client_credentials \
-d client_id=scim-client \
-d client_secret=<client-secret> |
jq -r .access_token)
curl \
https://<atscale-host>/auth/realms/atscale/scim/v2/ServiceProviderConfig \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/scim+json"The request should return the SCIM service provider configuration with HTTP
200. If it returns a401, verify that the following are configured as described above:- The client secret
- The
manage-usersrole - The Audience mapper
- The SCIM URL
- The
/authcontext path
Enable and configure SCIM provisioning in Okta
Once you have enabled SCIM in Keycloak, you can configure it in Okta.
Add and configure an Okta Application
First, you need to create a new application in Okta and enable SCIM provisioning for it.
- Open the Okta Admin Console.
- Go to Applications and Resources > Applications and click Create App Integration.
- Configure the application as needed and add it.
- On the General tab for the new application, under App Settings, click Edit.
- In the Provisioning field, enable the SCIM option.
Once SCIM is enabled, the Provisioning tab becomes available for the application.
Configure the SCIM connection
Next, you need to configure the SCIM connection for the application.
-
Go to the Provisioning tab.
-
Under Settings > Integration, click Edit.
-
Complete the following fields:
- SCIM connector base URL: Enter
https://<atscale-host>/auth/realms/atscale/scim/v2. - Unique identifier field for users: Enter
userName. - Authentication Mode: Set to OAuth 2.
- Grant Type: Set to Client Credentials.
- Access Token Endpoint: Enter
https://<atscale-host>/auth/realms/atscale/protocol/openid-connect/token. - Client ID: Enter
scim-client. - Client Secret: Enter the client secret you copied from Keycloak.
- SCIM connector base URL: Enter
-
Save your changes.
-
Click Authenticate with to authenticate the connection.
Okta may display a message of
Authenticate with to enable user import and provisioning featuresuntil the OAuth authentication has been completed. Do not proceed until the authentication succeeds.
Enable provisioning operations
After configuring the SCIM connection, you must enable provisioning operations for the application.
-
On the Provisioning tab, go to To App and click Edit.
-
Enable the following options:
- Create Users
- Update User Attributes
- Deactivate Users
-
(Optional) Depending on your organization's requirements, you can also enable the following:
- Import New Users
- Import Profile Updates
- Push Groups
-
Save the configuration.
Assign users to the application
Next, you must assign users to the application.
- On the Assignments tab, click Assign and select Assign to People
- Select the user that should be provisioned to AtScale.
- Save the assignment.
Okta should then create the corresponding Keycloak user through SCIM.
Recommended user mapping
Next, you should configure user attribute mappings in Okta. The following core attributes are handled by the Keycloak SCIM schema.
| SCIM Attribute | Recommended Okta Attribute |
|---|---|
userName | Login/Username |
name.givenName | First name |
name.familyName | Last name |
emails[type eq "work"].value | |
active | Active |
externalId1 | Okta user ID |
1 For externalId, ensure the Keycloak User Profile attribute is configured as described in step 3 of Enable and configure SCIM provisioning in Keycloak.
Additional attributes such as title, department, and jobTitle are not automatically persisted by Keycloak simply because Okta sends them through SCIM. If a non-core attribute needs to be synchronized, create a corresponding Keycloak User Profile attribute and map it to the appropriate SCIM schema attribute. Without the required User Profile configuration, the value may be silently dropped.
Working with provisioning in Okta
User lifecycle
Provisioning
Assign the user to the Okta application. This should have the following result:
Okta
> SCIM POST /Users
> Keycloak user created
The user should appear in Keycloak with the following attributes:
- Username
- First name
- Last name
externalId- Enabled/active state
Profile updates
When a supported profile attribute is changed in Okta, Okta sends the update through SCIM. The corresponding Keycloak user should receive the updated value.
Deprovisioning
When a user is unassigned from the Okta application, Okta sends a SCIM deactivation. Note that this disables the Keycloak user; it does not delete them.
Deactivation does not immediately terminate existing Keycloak sessions or already-issued tokens. Existing sessions remain valid until they expire unless they are explicitly terminated.
Import users from Keycloak
Okta can import users that already exist in Keycloak. On the Provisioning tab in Okta, enable To Okta and configure the required import operations.
Okta retrieves users through GET /Users. Keycloak supports SCIM pagination using startIndex, count, totalResults, and itemsPerPage.
Imported users appear in Okta's import/review flow, rather than automatically becoming active Okta users.
Group provisioning limitations
Empty groups
Okta can create an empty group in Keycloak.
Groups with members
Group membership synchronization with Okta Group Push is not supported with Keycloak SCIM. Okta sends the group together with its members during group create/update operations. Keycloak rejects those requests with the following error:
400 Bad Request
Managing members on updates are not supported
This behavior is caused by the Keycloak SCIM implementation, rather than a configuration issue in Okta. Keycloak accepts group membership changes through SCIM PATCH; for example, PATCH /Groups/{id}. However, Okta's group push flow sends the complete group resource with members, rather than using the PATCH operation expected by Keycloak.
AtScale therefore recommends against relying on Okta SCIM Group Push for AtScale group membership with Keycloak. The existing IdP claim to AtScale group mapping should remain in place where group membership is required.
Group operation support status
| Operation | Status |
|---|---|
| Create empty group | Supported |
| Create group with members | Not supported |
| Update group with members | Not supported |
| Membership synchronization through Okta Group Push | Not supported |
SCIM PATCH membership operation | Supported |
Private network/On-Premises Provisioning
Direct Okta SCIM provisioning requires the SCIM endpoint to be reachable from Okta Cloud. If you cannot expose the Keycloak SCIM endpoint publicly, you may consider using Okta On-Premises Provisioning (OPP).
Be aware, however, that the Keycloak SCIM API supports OAuth Bearer Token authentication, while the Okta Provisioning Agent supports Basic Authentication, HTTP Header authentication, or no authentication for the SCIM endpoint.
This means that Okta OPP with Keycloak SCIM has an authentication compatibility limitation and should not be considered a supported configuration without an additional authentication proxy or another validated solution.
Note that this is different from the direct cloud-to-cloud configuration documented above.
AtScale administrative accounts
SCIM-managed users should not include Keycloak/AtScale administrative accounts. Users with realm-management administrative roles are protected by Keycloak's SCIM implementation. For these users, SCIM GET responses may contain only limited user information. SCIM updates and deletion may return a 403. This can result in repeated provisioning failures in Okta.
Due to this, AtScale recommends you exclude administrative users from the Okta SCIM application assignment.
Recommended configuration
For a standard cloud deployment, AtScale recommends the following configuration:
Okta
|
| OAuth 2.0 Client Credentials
|
v
AtScale Keycloak
|
+-- Native SCIM API
+-- SCIM Client
+-- Audience Mapper
+-- External ID User Profile Attribute
Use the Keycloak's native scim-api implementation.
The custom keycloak-scim-server fork is not required for the standard Okta cloud integration because Okta supports OAuth 2.0 Client Credentials.
Validation checklist
After configuring SCIM provisioning with Okta, verify the following.
| Capability | Expected Result |
|---|---|
| OAuth Client Credentials | PASS |
| SCIM connection test | PASS |
| User provisioning | PASS |
| User profile update | PASS |
| User deprovisioning | PASS |
| User import | PASS |
| Empty group creation | PASS |
| Group membership push | Not supported |