Supported features

January 20, 2026 · View on GitHub

FeatureSinceDescription
Create clients1.0.0Create client configuration (inclusive protocolMappers) while creating or updating realms
Update clients1.0.0Update client configuration (inclusive protocolMappers) while updating realms
Manage fine-grained authorization of clients2.2.0Add and remove fine-grained authorization resources and policies of clients
Add roles1.0.0Add roles while creating or updating realms
Update roles1.0.0Update role properties while updating realms
Add composites to roles1.3.0Add role with realm-level and client-level composite roles while creating or updating realms
Add composites to roles1.3.0Add realm-level and client-level composite roles to existing role while creating or updating realms
Remove composites from roles1.3.0Remove realm-level and client-level composite roles from existing role while creating or updating realms
Add users1.0.0Add users (inclusive password!) while creating or updating realms
Add users with roles1.0.0Add users with realm-level and client-level roles while creating or updating realms
Update users1.0.0Update user properties (inclusive password!) while updating realms
Add role to user1.0.0Add realm-level and client-level roles to user while updating realm
Remove role from user1.0.0Remove realm-level or client-level roles from user while updating realm
Add groups to user2.0.0Add groups to user while updating realm
Remove groups from user2.0.0Remove groups from user while updating realm
Add authentication flows and executions1.0.0Add authentication flows and executions while creating or updating realms
Update authentication flows and executions1.0.0Update authentication flow properties and executions while updating realms
Remove authentication flows and executions2.0.0Remove existing authentication flow properties and executions while updating realms
Update builtin authentication flows and executions2.0.0Update builtin authentication flow properties and executions while updating realms
Add authentication configs1.0.0Add authentication configs while creating or updating realms
Update authentication configs2.0.0Update authentication configs while updating realms
Remove authentication configs2.0.0Remove existing authentication configs while updating realms
Add components1.0.0Add components while creating or updating realms
Update components1.0.0Update components properties while updating realms
Remove components2.0.0Remove existing sub-components while creating or updating realms
Update sub-components1.0.0Add sub-components properties while creating or updating realms
Remove sub-components2.0.0Remove existing sub-components while creating or updating realms
Add groups1.3.0Add groups (inclusive subgroups!) to realm while creating or updating realms
Update groups1.3.0Update existing group properties and attributes while creating or updating realms
Remove groups1.3.0Remove existing groups while updating realms
Add/Remove group attributes1.3.0Add or remove group attributes in existing groups while updating realms
Add/Remove group roles1.3.0Add or remove roles to/from existing groups while updating realms
Update/Remove subgroups1.3.0Like groups, subgroups may also be added/updated and removed while updating realms
Add scope-mappings1.0.0Add scope-mappings while creating or updating realms
Add roles to scope-mappings1.0.0Add roles to existing scope-mappings while updating realms
Remove roles from scope-mappings1.0.0Remove roles from existing scope-mappings while updating realms
Add required-actions1.0.0Add required-actions while creating or updating realms
Update required-actions1.0.0Update properties of existing required-actions while updating realms
Remove required-actions2.0.0Remove existing required-actions while updating realms
Add identity providers1.2.0Add identity providers while creating or updating realms
Update identity providers1.2.0Update identity providers while updating realms (improved with 2.0.0)
Remove identity providers2.0.0Remove identity providers while updating realms
Add identity provider mappers2.0.0Add identityProviderMappers while updating realms
Update identity provider mappers2.0.0Update identityProviderMappers while updating realms
Remove identity provider mappers2.0.0Remove identityProviderMappers while updating realms
Add clientScopes2.0.0Add clientScopes (inclusive protocolMappers) while creating or updating realms
Update clientScopes2.0.0Update existing (inclusive protocolMappers) clientScopes while creating or updating realms
Remove clientScopes2.0.0Remove existing clientScopes while creating or updating realms
Add clientScopeMappings2.5.0Add clientScopeMapping while creating or updating realms
Update clientScopeMappings2.5.0Update existing clientScopeMappings while creating or updating realms
Remove clientScopeMappings2.5.0Remove existing clientScopeMappings while creating or updating realms
Synchronize user federation3.5.0Synchronize the user federation defined on the realm configuration
Synchronize user profile5.4.0Synchronize the user profile configuration defined on the realm configuration
Synchronize client-policies5.6.0Synchronize the client-policies (clientProfiles and clientPolicies) while updating realms
Synchronize message bundles5.12.0Synchronize message bundles defined on the realm configuration
Normalize realm exportsx.x.xNormalize a full realm export to be more minimal
JavaScript Variable Substitutionx.x.xEvaluate JavaScript expressions in configuration files

Specificities

Client - authenticationFlowBindingOverrides

authenticationFlowBindingOverrides on client is configured by Keycloak like this,

{
  "authenticationFlowBindingOverrides": {
    "browser": "ad7d518c-4129-483a-8351-e1223cb8eead"
  }
}

In order to be able to configure this in keycloak-config-cli, we use authentication flow alias instead of id (which is not known)

keycloak-config-cli will automatically resolve the alias reference to its ids.

So if you need this, you have to configure it like :

{
  "authenticationFlowBindingOverrides": {
    "browser": "my awesome browser flow"
  }
}

User - initial password

To set an initial password that is only respect while the user is created, the userLabel must be named initial.

{
  "users": [
    {
      "username": "user",
      "email": "user@mail.de",
      "enabled": true,
      "credentials": [
        {
          "type": "password",
          "userLabel": "initial",
          "value": "start123"
        }
      ]
    }
  ]
}

Fine-grained permissions for Keycloak objects

Keycloak supports two versions of fine-grained admin permissions (FGAP):

FGAP V1 (Keycloak < 26.2) - realm-management client

The resources and policies are configured on the client named realm-management:

{
  "clients": [
    {
      "clientId": "realm-management",
      "authorizationSettings": {
        "allowRemoteResourceManagement": false,
        "policyEnforcementMode": "ENFORCING",
        "resources": [
          {
            "name": "idp.resource.1dcbfbe7-1cee-4d42-8c39-d8ed74b4cf22",
            "type": "IdentityProvider",
            "ownerManagedAccess": false,
            "scopes": [
              {
                "name": "token-exchange"
              }
            ]
          }
        ],
        "policies": [
          {
            "name": "token-exchange.permission.idp.1dcbfbe7-1cee-4d42-8c39-d8ed74b4cf22",
            "type": "scope",
            "logic": "POSITIVE",
            "decisionStrategy": "UNANIMOUS",
            "config": {
              "resources": "[\"idp.resource.1dcbfbe7-1cee-4d42-8c39-d8ed74b4cf22\"]",
              "scopes": "[\"token-exchange\"]"
            }
          }
        ]
      }
    }
  ],
  "identityProviders": [
    {
      "alias": "my-identity-provider",
      "providerId": "oidc",
      "enabled": true
    }
  ]
}

Both resources and policies are named in such a way that the name contains the UUID of the referenced entity (identity provider in the example). This is problematic, as the UUID is not known.

Therefore keycloak-config-cli will automatically resolve the object ids during import, using a special dollar syntax:

The following transformations are currently implemented:

ResourcePermissionResolution strategy
client.resource.$client-id<scope>.permission.client.$client-idFind a client by client id
idp.resource.$alias<scope>.permission.idp.$aliasFind an identity provider by alias
role.resource.$Realm Role Name<scope>.permission.$Realm Role Name (Note: No .role.)Find a realm role by name
group.resource.$/Full Path/To Group<scope>.permission.group.$/Full Path/To GroupFind a group by full path

The dollar only marks the name for substitution but is not part of it. It is an import failure when the referenced entity does not exist.

The example above should therefore be rewritten as:

{
  "clients": [
    {
      "clientId": "realm-management",
      "authorizationSettings": {
        "allowRemoteResourceManagement": false,
        "policyEnforcementMode": "ENFORCING",
        "resources": [
          {
            "name": "idp.resource.$my-identity-provider",
            "type": "IdentityProvider",
            "ownerManagedAccess": false,
            "scopes": [
              {
                "name": "token-exchange"
              }
            ]
          }
        ],
        "policies": [
          {
            "name": "token-exchange.permission.idp.$my-identity-provider",
            "type": "scope",
            "logic": "POSITIVE",
            "decisionStrategy": "UNANIMOUS",
            "config": {
              "resources": "[\"idp.resource.$my-identity-provider\"]",
              "scopes": "[\"token-exchange\"]"
            }
          }
        ]
      }
    }
  ],
  "identityProviders": [
    {
      "alias": "my-identity-provider",
      "providerId": "oidc",
      "enabled": true
    }
  ]
}

Migration Guide

FGAP V2 (Keycloak 26.2+) - admin-permissions client

Starting with Keycloak 26.2, FGAP V2 is the default. V2 introduces a cleaner permission model with improved manageability.

V2 permissions are configured on the admin-permissions client. Unlike V1, V2 uses authorizationSchema to define resource types and their available scopes.

Configuring V2 Permissions

To configure FGAP V2 permissions, enable admin permissions. Note that the admin-permissions client itself is system-managed and cannot be configured via import files. However, you can configure full authorization for your own clients:

realm: my-realm
adminPermissionsEnabled: true  # Enables FGAP V2 - creates admin-permissions client
enabled: true

# Note: Do NOT include admin-permissions client in your import configuration
# Authorization for this client is system-managed by Keycloak
# Manage permissions through Admin Console after realm import

clients:
  - clientId: test-client
    enabled: true
    authorizationServicesEnabled: true
    authorizationSettings:
      allowRemoteResourceManagement: true
      policyEnforcementMode: ENFORCING
      resources:
        - name: premium-resource
          type: urn:test-client:resources:premium
          ownerManagedAccess: false
          scopes: ["view", "delete"]
      policies:
        - name: only-client-admins
          type: role
          logic: POSITIVE
          decisionStrategy: UNANIMOUS
          config:
            roles: '[{"id":"client-admin","required":true}]'
        - name: premium-resource-permission
          type: resource
          logic: POSITIVE
          decisionStrategy: UNANIMOUS
          config:
            defaultResourceType: urn:test-client:resources:premium
            resources: '["premium-resource"]'
            applyPolicies: '["only-client-admins"]'
roles:
  realm:
    - name: client-admin
      description: Can manage specific clients

Key V2 concepts:

  1. authorizationSchema - Defines available resource types (Groups, Users, Clients, Roles) and their scopes. Required for V2.
  2. Permissions as scope policies - V2 permissions are type: "scope" policies with defaultResourceType config
  3. Resource references - Use client IDs, group paths, role names directly (or $placeholder syntax)
  4. Policy references - applyPolicies links permissions to access conditions

V2 Resource Types

V2 defines four resource types, each with specific scopes:

Resource TypeAvailable Scopes
Clientsview, manage, map-roles, map-roles-client-scope, map-roles-composite
Groupsmanage-members, manage-membership, view, manage, view-members, impersonate-members
Usersmanage-group-membership, view, map-roles, manage, impersonate
Rolesmap-role, map-role-composite, map-role-client-scope

Resource Reference Syntax

Both V1 and V2 support placeholder syntax for referencing resources in policy configurations. keycloak-config-cli automatically transforms these placeholders based on the active FGAP version.

Syntax options:

SyntaxV1 TransformationV2 TransformationWhen to Use
$client-id (bare)client.resource.<uuid><uuid>V2 with defaultResourceType: "Clients"
client.resource.$client-id (full)client.resource.<uuid><uuid>Both V1 and V2
idp.resource.$alias (full)idp.resource.<uuid><uuid>Both V1 and V2
group.resource.$/path (full)group.resource.<uuid><uuid>Both V1 and V2

V2 bare syntax example (recommended):

{
  "policies": [
    {
      "name": "manage-test-client-permission",
      "type": "scope",
      "config": {
        "defaultResourceType": "Clients",
        "resources": "[\"$test-client\"]",
        "scopes": "[\"manage\"]"
      }
    }
  ]
}

Full-path syntax example (works in both V1 and V2):

{
  "config": {
    "resources": "[\"client.resource.$test-client\"]"
  }
}

Supported resource types:

  • Clients - Client IDs (e.g., $my-client-id)
  • Groups - Group paths (e.g., $/my-group or $my-group-name)
  • IdentityProviders - IDP aliases (e.g., $my-idp-alias)
  • Roles - Role names (e.g., $my-role-name)
  • Users - User references (V2 only)

Important notes:

  • V2 bare syntax requires defaultResourceType in policy config
  • Full-path syntax works in both versions without defaultResourceType
  • keycloak-config-cli auto-detects the FGAP version and applies correct transformation
  • V2 requires authorizationSchema section - see example config

Troubleshooting: If "All Clients" is selected instead of a specific client, the resource reference wasn't transformed. Verify:

  1. You're using keycloak-config-cli with FGAP V2 support
  2. For bare syntax, defaultResourceType is specified
  3. The referenced resource exists in the realm

V2 Import Behavior

When importing V2 configs:

  • Authorization settings for admin-permissions client are skipped - This client is system-managed by Keycloak
  • Policies and permissions must be managed through Keycloak Admin Console or dedicated FGAP V2 REST APIs
  • The authorizationSchema section is processed but resource type definitions are auto-managed by Keycloak

Important: Do NOT include admin-permissions client with authorizationSettings in your import files.

When keycloak-config-cli detects admin-permissions client with authorization settings in FGAP V2:

Skipping authorization settings for 'admin-permissions' client in realm '[realm]' -
FGAP V2 manages this client internally and blocks API access.

Why this limitation exists:

Keycloak intentionally blocks standard Authorization Services API endpoints for the admin-permissions client in FGAP V2 (returns HTTP 400 with "unknown_error"). This is by design to prevent external modification of the system-managed authorization model. See Keycloak issue #43977 for details.

Correct approach:

  1. Set adminPermissionsEnabled: true at realm level
  2. Remove admin-permissions client from your import configuration
  3. Manage permissions post-import through:
    • Keycloak Admin Console → Realm Settings → Permissions
    • Direct FGAP V2 REST API calls (after realm creation)

Troubleshooting FGAP V2

Error: "Policy with name [PolicyName] already exists" (409 Conflict)

This occurs when trying to update policies in the admin-permissions client. The client is system-managed in FGAP V2 and cannot be modified via config files.

Solution: Remove the admin-permissions client from your import configuration and use adminPermissionsEnabled: true at the realm level instead.

Error: "unknown_error" (400 Bad Request)

Keycloak intentionally blocks API access to admin-permissions authorization settings in FGAP V2. This is expected behavior, not a bug.

Solution: Same as above - use realm-level flag and manage permissions through Admin Console.

V1 to V2 Migration

Automatic migration from V1 to V2 is not available per Keycloak documentation. V1 authorization on realm-management will be skipped with warnings on V2 realms.

To use V2: Enable adminPermissionsEnabled: true and configure permissions on admin-permissions client as shown above.

Keycloak Version 25.0.1

Basic Scope Handling

With the introduction of the dedicated "basic" scope in Keycloak, existing realm configurations with custom clients might not contain the sub claim anymore. This is because the new basic scope that emits those claims might be removed by an explicit defaultClientScopes configuration.

A workaround is to configure the basic scope explicitly via defaultClientScopes:

defaultClientScopes:
  - "basic"

Ensure that your client configurations include the basic scope to maintain the presence of the sub claim in access tokens.

Example Client Configuration

Here is an example of a previously working client definition, which will produce access tokens with the sub claim.

  - clientId: app-greetme
    protocol: openid-connect
    name: Acme Greet Me
    description: "App Greet Me Description"
    enabled: true
    publicClient: true
    standardFlowEnabled: true
    directAccessGrantsEnabled: false
    alwaysDisplayInConsole: true
    serviceAccountsEnabled: false
    fullScopeAllowed: false
    rootUrl: "$(env:APPS_FRONTEND_URL_GREETME:https://localhost:9443/apps/greet-me)"
    baseUrl: "/?realm=acme-internal&scope=openid"
    adminUrl: ""
    redirectUris:
      - "/*"
    webOrigins:
      - "+"
    defaultClientScopes:
      - "email"
    optionalClientScopes:
      - "phone"
      - "name"
      - "acme.api"
      - "address"
    attributes:
      "pkce.code.challenge.method": "S256"
      "post.logout.redirect.uris": "+"

To ensure the sub claim is present, update the defaultClientScopes to include the basic scope,

   - clientId: app-greetme
     protocol: openid-connect
     name: Acme Greet Me
     description: "App Greet Me Description"
     enabled: true
     publicClient: true
     standardFlowEnabled: true
     directAccessGrantsEnabled: false
     alwaysDisplayInConsole: true
     serviceAccountsEnabled: false
     fullScopeAllowed: false
     rootUrl: "$(env:APPS_FRONTEND_URL_GREETME:https://localhost:9443/apps/greet-me)"
     baseUrl: "/?realm=acme-internal&scope=openid"
     adminUrl: ""
     redirectUris:
       - "/*"
     webOrigins:
       - "+"
     defaultClientScopes:
       - "basic"
       - "email"
     optionalClientScopes:
       - "phone"
       - "name"
       - "acme.api"
       - "address"
     attributes:
       "pkce.code.challenge.method": "S256"
       "post.logout.redirect.uris": "+"