Skip to content

Metatavu/keycloak-scim-server

Repository files navigation

Keycloak SCIM 2.0 Extension

This project provides a SCIM 2.0-compliant extension for Keycloak, enabling SCIM-based user and group provisioning. It supports:

  • Realm-level SCIM APIs:
    /realms/{realm}/scim/v2
  • Organization-level SCIM APIs (Keycloak 26+ with Organizations):
    /realms/{realm}/scim/v2/organizations/{organizationId}

Prerequisites

  • Keycloak: This extension is developed for Keycloak 26.1.4. It may work with other versions, but compatibility is not guaranteed.
  • Java: Java 21 is required to build the project.

Installation

Option 1: Install from GitHub Packages (recommended)

Easiest way to use the extension is to download a JAR file from GitHub packages.

  1. Download the latest JAR from: GitHub Packages
  2. Copy it to your Keycloak instance:
   cp keycloak-scim-server-*.jar $KEYCLOAK_HOME/providers/
  1. Restart Keycloak.

Option 2: Build from Source

  1. Build the extension:
./gradlew build
  1. Copy the built JAR file from build/libs/keycloak-scim-server-<version>.jar to the Keycloak providers directory:
cp build/libs/keycloak-scim-server-*.jar $KEYCLOAK_HOME/providers/

Configuration

Configuration on Instance level

Configuration on instance level is done by defining environment variables in the Keycloak server.

The following environment variables are available:

Setting Value
SCIM_AUTHENTICATION_MODE Authentication mode for SCIM API. Possible values are KEYCLOAK and EXTERNAL. If the value is not set the server will respond unauthorzed for all requests.
SCIM_EXTERNAL_ISSUER Issuer for the external authentication. This is used to validate the JWT token.
SCIM_EXTERNAL_AUDIENCE JWKS URI for the external authentication. This is used to validate the JWT token.
SCIM_EXTERNAL_JWKS_URI Audience for the external authentication. This is used to validate the JWT token.
SCIM_EXTERNAL_SHARED_SECRET Shared secret value used for request authentication/validation.
SCIM_EXTERNAL_SHARED_SECRET_HASH_ALGORITHM PHC String Format representing hash algorithms and its parameters, used for request authentication/validation (must be on of the following).

Configuration on Realm level

The following REST call can be called through the Keycloak Admin API to store the settings under realm attributes.

PUT /admin/realms/{realm}

{
  "attributes": {
    "scim.authentication.mode": "EXTERNAL|INTERNAL",
    "scim.external.issuer": "string",
    "scim.external.jwks.uri": "string",
    "scim.external.audience": "string",
    "scim.external.shared.secret": "string",
    "scim.external.shared.secret.hash.algorithm": "string"
  }
}

Configuration on Organization level

Configuration on organization level is done by defining organization attributes in the Keycloak server. The following organization attributes are available:

Setting Value
SCIM_AUTHENTICATION_MODE Authentication mode for SCIM API. Possible values are KEYCLOAK and EXTERNAL. If the value is not set the server will respond unauthorzed for all requests. Currently on organization level only EXTERNAL is supported.
SCIM_EXTERNAL_ISSUER Issuer for the external authentication. This is used to validate the JWT token.
SCIM_EXTERNAL_AUDIENCE Audience for the external authentication. This is used to validate the JWT token.
SCIM_EXTERNAL_JWKS_URI JWKS URI for the external authentication. This is used to validate the JWT token.
SCIM_LINK_IDP Enables support for linking organization identity provider with user.
SCIM_EMAIL_AS_USERNAME Forces server to user email as username instead of actual username. When this setting is enabled username will be unaffected by any update operations. This setting is currently supported only in organization level configuration
SCIM_EXTERNAL_SHARED_SECRET Shared secret value used for request authentication/validation.
SCIM_EXTERNAL_SHARED_SECRET_HASH_ALGORITHM PHC String Format representing hash algorithms and its parameters, used for request authentication/validation (must be on of the following).

Azure Entra ID SCIM Configuration

This extension is compatible with Microsoft Entra ID SCIM provisioning.

Keycloak Configuration

Before Entra ID can provision users and groups to Keycloak via SCIM, you need to configure SCIM authentication settings.

These settings can be applied either:

  • At the realm level (for /realms/{realm}/scim/v2)
  • Or at the organization level (for /realms/organizations/scim/v2/organizations/{organizationId})

For more details, refer to the sections [Configuration on Realm Level] and [Configuration on Organization Level in this document].

SCIM Settings for Entra ID

When using Entra ID settings will be following:

Setting Value
SCIM_AUTHENTICATION_MODE EXTERNAL
SCIM_EXTERNAL_ISSUER https://sts.windows.net/<your-tenant-id>/
SCIM_EXTERNAL_AUDIENCE 8adf8e6e-67b2-4cf2-a259-e3dc5476c621
SCIM_EXTERNAL_JWKS_URI https://login.microsoftonline.com/<your-tenant-id>/discovery/v2.0/keys

Replace with your actual Azure tenant ID.

  • SCIM_AUTHENTICATION_MODE enables external authentication support for the SCIM server. In this case the external authentication source will be the Azure Entra ID.
  • SCIM_EXTERNAL_ISSUER ensures the JWT token was issued by your tenant.
  • SCIM_EXTERNAL_AUDIENCE must be exactly 8adf8e6e-67b2-4cf2-a259-e3dc5476c621 — this is the default audience used by Entra ID for non-gallery applications.
  • SCIM_EXTERNAL_JWKS_URI allows Keycloak to fetch public keys for token validation.

OR

Setting Value
SCIM_AUTHENTICATION_MODE EXTERNAL
SCIM_EXTERNAL_SHARED_SECRET <token_hashed_value>

Replace <token_hashed_value> with your hashed token value (using SHA-512 Hex).

Azure Configuration

Step-by-step guide on the Azure:

  1. Sign in to the Azure portal
  2. Go to Identity → Applications → Enterprise applications
  3. Click + New application → + Create your own application
  4. Enter a name for your application (e.g., My Keycloak SCIM).
  5. Choose Integrate any other application you don't find in the gallery.
  6. Click Create to create the application. The application will open automatically in its management screen.
  7. In the application's left-hand menu, select Provisioning.
  8. Click + New configuration.
  9. Fill in the following:
  1. Click Test Connection to verify the SCIM endpoint.
  2. Click Create.
  3. Navigate to Attribute Mapping (Preview).
  4. Open Provision Microsoft Entra ID Groups.
  5. Set Enabled to No.
  6. Click Save.
  7. Go back → open Provision Microsoft Entra ID Users.
  8. Open Provision Microsoft Entra ID Users.
  9. Define mappings, following are required for Keycloak extension:
  • userName
  • active
  • emails[type eq "work"].value
  • name.givenName
  • name.familyName
  1. Click Save.
  2. Go back to Provisioning.
  3. Set Provisioning Status to On.
  4. Click Save.
  5. Reload the page to ensure the configuration was saved.
  6. Navigate to Manage > Users and groups > + Add user/group.
  7. Select the user you want to provision and click Assign.
  8. Navigate to Provision on demand.
  9. Find the user you just assigned.
  10. Click on the user and select Provision.
  11. Verify that the provisioning completes successfully.

For more information, refer to the following documents:

https://learn.microsoft.com/en-us/entra/identity/saas-apps/tutorial-list

Identity Provider Linking with Azure Entra ID

Identity Provider linking with Entra ID requires a few additional configuration steps on both the Entra and Keycloak sides.

Step 1: Add externalId

In the Keycloak admin console, ensure that you have externalId attribute defined in your Realm Settings > User Profile. This attribute is used to store user's external id in the Keycloak side and without it the Identity Provider linking will fail.

Step 2: Map externalId in SCIM provisioning

In the Entra Id, make sure that the objectId from Entra ID is mapped into the SCIM externalId field:

  1. Navigate to your Enterprise Application > Provisioning > Attribute Mapping (Preview) > Provision Microsoft Entra ID Users.
  2. Click Add New Mapping.
  3. Set:
  • Source attribute: objectId
  • Target attribute: externalId
  1. Click Save.

This ensures that during SCIM provisioning, the Entra objectId is stored in Keycloak as the user’s externalId, which will later be used for identity linking.

Step 3: Configure Keycloak Identity Provider to Use Object ID

Next, configure your Entra ID Identity Provider in Keycloak to use the oid claim from the login token instead of the default sub claim (which is app-specific).

  1. Navigate to Identity Providers > select your Entra ID provider.
  2. Go to the Mappers tab.
  3. Click Add Mapper.
  4. Fill in the mapper details:
    • Name: map_oid_as_brokerid (or any descriptive name)
    • Sync Mode: Force
    • Mapper Type: Username Template Importer
    • Template: ${CLAIM.oid}
    • Target: BROKER_ID
  5. Click Save.

This mapper tells Keycloak to use the Entra oid claim as the Broker ID, ensuring that the login user is matched correctly with the SCIM-provisioned user.

Step 4: Enable Identity Provider Linking in SCIM

Finally, instruct your SCIM server to automatically link users to the configured Identity Provider during provisioning:

Add the following attribute to your SCIM configuration (only supported by organization server currently):

SCIM_LINK_IDP=true

This will ensure that when a user is provisioned via SCIM, a corresponding Identity Provider link is also created automatically based on the externalId / oid.

SCIM-Managed Users

By default, the SCIM server only exposes users who are explicitly assigned the scim-managed role within the realm. This ensures that only users intended to be managed through SCIM are returned or modifiable via SCIM API operations.

This prevents accidental exposure or modification of users that were:

  • created manually via the Keycloak admin UI
  • imported from external identity providers
  • or otherwise not intended to be managed through SCIM

If you want to expose all users (i.e., bypass filtering), you can simply assign the scim-managed role to every user. This effectively disables the filter, making the SCIM behavior equivalent to an unfiltered list.

This role-based filtering applies to all SCIM operations, including:

  • GET /Users
  • PATCH /Users/{id}
  • DELETE /Users/{id}

Users without the scim-managed role will be invisible to SCIM clients — they won’t be listed, updated, or removed through SCIM.

This filtering mechanism is designed to improve safety, especially in complex deployments involving federated users, legacy accounts, or overlapping identity sources (such as Entra ID + local users).

This design does mean that provisioning a user through SCIM who previously existed without the role may cause conflicts or provisioning failures if role assignment isn’t handled correctly. However, this is a deliberate design choice to provide fine-grained control over which users are SCIM-visible.

License

Apache License, Version 2.0


About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages