添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • Migrating to 24.0.4
  • Partial update to user attributes when updating users through the Admin User API is no longer supported
  • Migrating to 24.0.3
  • Changes in redirect URI verification when using wildcards
  • Changes to the org.keycloak.userprofile.UserProfileDecorator interface
  • Migrating to 24.0.2
  • Changes to Password Hashing
  • Migrating to 24.0.0
  • Changes to the Welcome theme
  • Changes to the Account Console theme customization
  • Keycloak JS imports might need to be updated
  • Features Changes
  • User Profile Changes
  • Truststore Changes
  • Deprecated --proxy option
  • Changes to the user representation in both Admin API and Account contexts
  • https-client-auth is a build time option
  • Sequential loading of offline sessions and remote sessions
  • Deprecated offline session preloading
  • Infinispan metrics use labels for cache manager and cache names
  • User attribute value length extension
  • The Admin send-verify-email API now uses the same email verification template
  • Removal of the deprecated mode for SAML encryption
  • Changes to Password Hashing
  • Operator Referenced Resource Polling
  • Renaming JPA provider configuration options for migration
  • Renaming model modules
  • Temporary lockout log replaced with event
  • Operator Customization Property Keys
  • Keycloak CR resources options
  • Updates to cookies
  • Internal algorithm changed from HS256 to HS512
  • Different JVM memory settings when running in a container
  • GELF log handler has been deprecated
  • Migrating to 23.0.5
  • Changes in jboss-logging event messages
  • Migrating to 23.0.4
  • Fix handling of Groups.getSubGroups briefRepresentation parameter
  • Migrating to 23.0.2
  • Valid redirect URIs for clients are always compared with exact string matching
  • Operator -secrets-store Secret
  • Migrating to 23.0.0
  • Added iss parameter to OAuth 2.0/OpenID Connect Authentication Response
  • Wildcard characters handling
  • Language files for themes default to UTF-8 encoding
  • Changes to the value format of claims mapped by the realm and client role mappers
  • Changes to password fields in Login UI
  • Default Keycloak CR Hostname
  • The deprecated auto-build CLI option was removed
  • kc.sh and shell metacharacters
  • Removed RegistrationProfile form action
  • Deprecated methods from data providers and models
  • GroupProvider changes
  • GroupRepresentation changes
  • New endpoint for Group Admin API
  • RESTEeasy Reactive
  • Partial export requires manage-realm permission
  • Removal of the options to trim the event’s details length
  • User Profile updates
  • Removal of the Map Store
  • Removed namespaces from our translations
  • Migrating to 22.0.4
  • A new parameter for specify max length of email local part
  • Migrating to 22.0.2
  • Never expires option removed from client advanced settings combos
  • New LinkedIn OpenID Connect social provider
  • Migrating to 22.0.0
  • Transition from Java EE to Jakarta EE
  • Upgrade to Quarkus 3
  • Upgrade to Hibernate ORM 6
  • Legacy Promise API removed from Keycloak JS adapter
  • Export and Import perform an automatic build
  • Renamed Keycloak Admin client artifacts
  • Passthrough proxy mode changes
  • Consistent fallback message resolving for all themes
  • UserQueryProvider changes
  • LDAPStorageProvider search changes
  • Deprecation of Keycloak OpenID Connect Adapters
  • Deprecation of Keycloak JEE SAML Adapter
  • Changes for openshift-integration feature
  • Removing thirdparty dependencies
  • Context and dependency injection no longer enabled to JAX-RS Resources
  • Upgrading your custom JAX-RS resources
  • Deprecated methods from data providers and models
  • Multiple Keycloak instances
  • k8s.keycloak.org/v2alpha1 changes
  • Keycloak supports IPv4/IPv6 dual stack
  • Migrating to 21.1.0
  • Javascript engine available by default on the classpath
  • Change of the default Client ID mapper of Service Account Client
  • Keycloak JS adapter must be instanciated with the new operator
  • Migrating to 21.0.2
  • Terms and Conditions user attribute migration
  • Migrating to 21.0.0
  • Keycloak uses Micrometer for metrics
  • Deprecated RSA_SHA1 and DSA_SHA1 algorithms for SAML
  • SAML SP metadata changes
  • Deprecated methods from user session provider were removed
  • Custom themes using old admin console won’t work
  • Curl has been removed from the container
  • Migrating to 20.0.0
  • RESTEasy Version Update
  • H2 Version Update
  • Breaking changes in the new version of Keycloak Operator
  • OLM channel was changed to fast
  • Deprecated methods from data providers and models were removed
  • Migrating to 19.0.2
  • OpenID Connect Logout Prompt
  • Deploying scripts through SAML javascript protocol mapper
  • UserInfo Endpoint Changes
  • Migrating to 19.0.0
  • New Admin Console is now the default console
  • Changes to the server configuration and startup
  • Potentially breaking changes to the health endpoints
  • Changes using GELF / centralized log management
  • Changes affecting developers
  • Deprecated podDisruptionBudget in the legacy Keycloak Operator
  • Deployment changes in the new Keycloak Operator
  • Migrating to 18.0.0
  • Step-up authentication
  • OpenID Connect Logout
  • Removal of the upload-scripts feature
  • Account console Patternfly upgrade
  • Quarkus distribution: Split metrics-enabled option into health-enabled and metrics-enabled
  • Migrating to 17.0.0
  • Default distribution is now powered by Quarkus
  • Migrating from the preview Quarkus distribution
  • Client Policies Migration : client-scopes
  • Liquibase upgraded to version 4.6.2
  • Migrating to 16.0.0
  • WildFly 25 upgrade
  • Proxy environment variables
  • Deprecated features in the Keycloak Operator
  • Keycloak Operator examples including unsupported Metrics extension
  • Migrating to 14.0.0
  • Client policies migration
  • Migrating to 13.0.0
  • Manual migration step needed
  • Upgrade to Wildfly 23
  • Upgrade to Wildfly 22
  • Migrating to 12.0.2
  • Read-only attributes
  • Valid Request URIs
  • Migrating to 13.0.0
  • Upgrade to Wildfly 22
  • Migrating to 12.0.0
  • Upgrade to Wildfly 21
  • Skip creation of user session for the Docker protocol authentication
  • Upgrade to PatternFly 4
  • Client Credentials Grant without refresh token by default
  • Migrating to 11.0.0
  • Upgrade to Wildfly 20
  • LDAP no-import bugfix
  • UserModel changes
  • Instagram IdP migrated to new the API
  • Non-standard token introspection endpoint removed
  • Migrating to 9.0.1
  • Legacy promise in JavaScript adapter
  • Duplicated top level groups
  • Migrating to 9.0.0
  • Improved handling of user locale
  • Deprecated methods in token representation Java classes
  • Migrating to 8.0.2
  • More authentication flows changes
  • Migrating to 8.0.0
  • New default Hostname provider
  • Upgrade to Wildfly 18
  • Deploying scripts to the server
  • Client credentials in the JavaScript adapter
  • Authentication flows changes
  • User credentials changes
  • Migrating to 7.0.0
  • Upgrade to Wildfly 17
  • Migrating to 6.0.0
  • Upgrade to Wildfly 16
  • New optional client scope
  • Ability to propagate prompt=none to default IDP
  • Migrating to 5.0.0
  • Upgrade to Wildfly 15
  • Migrating to 4.8.2
  • Google Identity Provider updated to use Google Sign-in authentication system
  • LinkedIn social broker updated to Version 2 of LinkedIn APIs
  • Migrating to 4.6.0
  • New default client scopes
  • JavaScript adapter promise
  • Microsoft Identity Provider updated to use the Microsoft Graph API
  • Upgrade to Wildfly 14
  • Migrating to 4.4.0
  • Upgrade to Wildfly 13
  • Migration to 4.3.0
  • Hostname configuration
  • Migrating to 4.0.0
  • Client Templates changed to Client Scopes
  • Changes to Authorization Services
  • Migrating to 3.4.2
  • Added session_state parameter to OpenID Connect Authentication Response
  • Migrating to 3.2.0
  • New password hashing algorithms
  • ID Token requires scope=openid
  • Authentication sessions and Action tokens
  • Migrating to 2.5.1
  • Migration of old offline tokens
  • Migrating to 2.5.0
  • Changes to the Infinispan caches
  • Migrating to 2.4.0
  • Server SPI split into Server SPI and Sever SPI Private
  • Key encryption algorithm in SAML assertions
  • Infinispan caches realms and users are always local
  • Migrating to 2.3.0
  • Default max results on paginated endpoints
  • realm-public-key adapter property not recommended
  • Added Infinispan cache keys
  • Migrating to 2.2.0
  • databaseSchema property deprecated
  • Changes in Client’s Valid Redirect URIs
  • Authenticate by default removed from Identity Providers
  • Migrating to 2.0.0
  • Upgrading from 1.0.0.Final no longer supported
  • Migrating to 1.9.5
  • Default password hashing interval increased to 20K
  • Migrating to 1.9.3
  • Add User script renamed
  • Migrating to 1.9.2
  • Adapter option auth-server-url-for-backend-requests removed
  • Migrating to 1.9.0
  • Themes and providers directory moved
  • Adapter subsystems only bring in dependencies if Keycloak is on
  • Client Registration service endpoints moved
  • Session state parameter in authentication response renamed
  • Deprecated OpenID Connect endpoints
  • Updates to theme templates
  • Module and source code reorganization
  • For adapters, session id changed after login
  • SAML SP Client adapter changes
  • Migrating to 1.8.0
  • Admin account
  • OAuth2 token introspection
  • Migrating to 1.7.0.CR1
  • Direct access grants disabled by default for clients
  • Option 'Update Profile On First Login' moved from Identity provider to Review Profile authenticator
  • Element 'form-error-page' in web.xml not supported anymore
  • IdentityProviderMapper changes
  • Migrating to 1.6.0.Final
  • Option that refresh tokens are not reusable anymore
  • Some packages renamed
  • Persisting user sessions
  • Migrating to 1.5.0.Final
  • Realm and User cache providers
  • Uses Session providers
  • Contact details removed from registration and account management
  • Migrating to 1.3.0.Final
  • Direct Grant API always enabled
  • Database changed
  • UserFederationProvider changed
  • WildFly 9.0.0.Final
  • WildFly, JBoss EAP and JBoss AS7 adapters
  • Migrating from 1.2.0.Beta1 to 1.2.0.RC1
  • Distribution changes
  • Database changed
  • Application and OAuth client merge
  • Migrating from 1.1.0.Final to 1.2.0.Beta1
  • Database changed
  • iss in access and id tokens
  • OpenID Connect endpoints
  • Theme changes
  • Claims changes
  • Social migration to identity brokering
  • Migrating from 1.1.0.Beta1 to 1.1.0.Beta2
  • Migrating from 1.0.x.Final to 1.1.0.Beta1
  • Migrating from 1.0 RC-1 to RC-2
  • Migrating from 1.0 Beta 4 to RC-1
  • Migrating from 1.0 Beta 1 to Beta 4
  • Migrating from 1.0 Alpha 4 to Beta 1
  • Migrating from 1.0 Alpha 2 to Alpha 3
  • Migrating from 1.0 Alpha 1 to Alpha 2
  • Upgrading the Keycloak server
  • Preparing for upgrading
  • Downloading the Keycloak server
  • Migrating the database
  • Automatic relational database migration
  • Manual relational database migration
  • Migrating themes
  • Migrating templates
  • Migrating messages
  • Migrating styles
  • Compatibility with older adapters
  • Upgrading the EAP adapter
  • Upgrading the JavaScript adapter
  • Upgrading the Node.js adapter
  • Upgrading the Keycloak Admin Client
  • Migrating to 24.0.4

    Partial update to user attributes when updating users through the Admin User API is no longer supported

    Edit this section Report an issue

    When updating user attributes through the Admin User API, you cannot execute partial updates when updating the user attributes, including the root attributes like username , email , firstName , and lastName .

    If you are updating user attributes through the Admin User API without passing all the attributes that the administrator has write permissions, the missing attributes will be removed. On the other hand, if an attribute is marked as read-only for administrators, not sending the attribute won’t remove it.

    See the User Profile Documentation for the details about the user profile settings.

    Because of security concerns, the redirect URI verification now performs a exact string matching (no wildcard involved) if the passed redirect uri contains a userinfo part or its path accesses parent directory ( /../ ).

    The full wildcard * can still be used as a valid redirect in development for http(s) URIs with those characteristics. In production environments a exact valid redirect URI without wildcard needs to be configured for any URI of that type.

    Please note that wildcard valid redirect URIs are not recommended for production and not covered by the OAuth 2.0 specification.

    Changes to the org.keycloak.userprofile.UserProfileDecorator interface

    To properly support multiple user storage providers within a realm, the org.keycloak.userprofile.UserProfileDecorator interface has changed.

    The decorateUserProfile method is no longer invoked when parsing the user profile configuration for the first time (and caching it), but everytime a user is being managed through the user profile provider. As a result, the method changed its contract to:

    List<AttributeMetadata> decorateUserProfile(String providerId, UserProfileMetadata metadata)

    Differently than the previous contract and behavior, this method is only invoked for the user storage provider from where the user was loaded from.

    The 'welcome' theme has has been updated to use a new layout and now uses PatternFly 5, rather than PatternFly 3. If you are extending the theme, or providing your own, you may need to update it as follows:

    Migrate from PatternFly 3 to PatternFly 5

    The welcome theme was one of the more outdated themes in Keycloak. It was originally based on PatternFly 3, but has now been updated to use PatternFly 5, skipping a major version in the process. If your custom theme extends the built-in theme, you will need to update it to use PatternFly 5 syntax. Consult the PatternFly 5 documentation for details.

    If you are still using PatternFly 3 in your own custom theme (not extending the built-in one), you can continue to use it, but PatternFly 3 support will be removed in a future release, so you should consider migrating to PatternFly 5 as soon as possible.

    Automatic redirect to the Admin Console

    If the Admin Console is enabled, the welcome page will automatically redirect to it if the administrative user already exists. This behavior can be modified by setting the redirectToAdmin in your theme.properties file. By default, the property is set to false , unless you are extending the built-in theme, in which case, the property is set to true .

    These properties were previously used for navigational elements that are now no longer present. If you are extending the built-in theme, you will need to remove these properties from your theme.properties file, as they no longer have any effect.

    Assets are now loaded from 'common' resources

    Images such as the background, logo and favicon are now loaded from the 'common' resources, rather than the theme resources. This change means that if you are extending the built-in theme, and are overwriting these images, you will need to move them to the 'common' resources of your theme, and update your theme.properties file to include the new paths:

    # This defaults to 'common/keycloak' if not set.
    import=common/your-theme-name

    Changes to the Account Console theme customization

    If you were previously extending the now deprecated version 2 of the Account Console theme, you will need to update your theme to use the new version 3 of the Account Console theme. The new version of the Account Console theme comes with some changes in regards to how it is customized. To start with a clean slate, you can follow the new customization quickstart .

    To move your custom theme start by changing the parent to the new theme:

    # Before
    parent=keycloak.v2
    # After
    parent=keycloak.v3

    If you have any custom React components, you will import React directly, rather than using a relative path:

    // Before
    import * as React from "../../../../common/keycloak/web_modules/react.js";
    // After
    import React from "react";

    If you are using content.json to customize the theme there are some changes to the structure of the file, specifically:

    Keycloak JS imports might need to be updated

    If you are loading Keycloak JS directly from the Keycloak server, this section can be safely ignored. If you are loading Keycloak JS from the NPM package and are using a bundler like Webpack, Vite, and so on, you might need to make some changes to your code. The Keycloak JS package now uses the exports field in the package.json file. This means that you might have to change your imports:

    // Before
    import Keycloak from 'keycloak-js/dist/keycloak.js';
    import AuthZ from 'keycloak-js/dist/keycloak-authz.js';
    // After
    import Keycloak from 'keycloak-js';
    import AuthZ from 'keycloak-js/authz';

    Features Changes

    It is no longer allowed to have the same feature in both the --features and --features-disabled list. The feature should appear in only one list.

    The usage of unversioned feature names, such as docker , in the --features list will allow for the most supported / latest feature version to be enabled for you. If you need more predictable behavior across releases, reference the particular version you want instead, such as docker:v1 .

    User Profile Changes

    User profile enabled by default

    The user profile feature is now enabled by default. The `declarative-user-profile`feature is no longer available, because the user profile is assumed to be enabled. Therefore, the User Profile Enabled switch is removed from the Realm Settings and replaced by Unmanaged attributes . When migrating from previous version, the behavior is as follows:

    For the deployments where User Profile Enabled was set to ON , Unmanaged attributes will be set to OFF after the upgrade. As a result, only user attributes supported explicitly by user profile will be allowed.

    For the deployments where the User Profile Enabled was set to OFF (which was also the default settings for the deployments with declarative-user-profile feature disabled, which was the default), Unmanaged attributes will be set to ON ` after the upgrade. As a result, the behavior should be basically the same as in previous versions with the user profile disabled. The Attributes tab will remain in the user details part of the Admin Console. Also users can now set arbitrary attributes through UI pages such as the registration page and update profile page as long as a particular custom theme supports it. The custom themes should work as before as well. However, consider updating your themes to use the user-profile and maybe even remove your custom themes if those themes were need to add custom attributes. See the subsequent section on themes. Also, consider toggling Unmanaged attributes to OFF or enable this switch only for administrators so that you can rely on mainly on using managed attributes.

    Default validations

    Default user profile configuration comes with a set of default validations for the basic predefined fields. Those validations were not present in previous versions when the declarative-user-profile feature was disabled by default. If you have issues due to backward compatibility, you can change the default validators according to your needs. The default validators are as follows:

    The`username`, email , firstName and lastName attributes have a maximum length of 255 characters. These validations were indirectly present in previous versions as well because of the database constraint on the table USER_ENTITY for those fields with a maximum length of 255 characters. However, when using user storage providers, it might be possible before to use longer values.

    The username attribute has a minimum length of three characters. Username has also username-prohibited-characters and up-username-not-idn-homograph validator by default, which were not present in previous versions. See the Validation section of the User Profile Documentation for the details about those attributes. Note that username is not editable by default unless you have the realm switch Edit username enabled . This change means that existing users with incorrect usernames should still work and they will not be enforced to update their usernames. But new users will be enforced to use correct usernames during their registration or creation by the admin REST API.

    The firstName and lastName attributes have the person-name-prohibited-characters validator on them, which were not present in previous versions. See the Validation section of the User Profile Documentation for the details about those attributes. Note that both first name and last name are editable by default, so users, who already have such incorrect first/last name from a previous version will be forced to update them when updating their user profiles.

    User attribute names with strange characters

    In previous versions, you could create a user with attribute names such as some:attribute or some/attribute . The user profile intentionally does not allow you to create attributes with such strange names in the user profile configuration. So you may need to configure Unmanaged attributes for your realm and enable unmanaged attributes for administrators (ideally) or for end users (if really needed). Although it is strongly preferred to avoid using such attribute names.

    Verify Profile required action enabled by default

    The verify-profile required action is enabled by default for new realms. However, when you migrate from a previous version, your existing realms will have the same state of this verify-profile action as before, which usually means disabled as it was disabled by default in previous versions. For the details about this required action, see the User Profile Documentation .

    Breaking changes to the User Profile SPI

    If you are using the User Profile SPI in your extension, you might be impacted by the API changes introduced in this release.

    The org.keycloak.userprofile.Attributes interface includes the following changes:

    Method getValues was renamed to get to make it more aligned with the same operation from a regular Java Map

    Method isRootAttribute was moved to the utility class org.keycloak.userprofile.UserProfileUtil.isRootAttribute

    Method getFirstValue was renamed to getFirst to make it less verbose

    Method getReadable(boolean) was removed and now all attributes (including root attributes) are returned whenever they have read rights.

    Changes to Freemarker templates to render pages based on the user profile and realm

    In this release, the following templates were updated to make it possible to dynamically render attributes based on the user profile configuration set to a realm:

    These templates are responsible for rendering the update profile (when the Update Profile required action is enabled for a user), the registration, and the update email (when the UPDATE_EMAIL feature is enabled) pages, respectively.

    If you use a custom theme to change these templates, they will function as expected because only the content is updated. However, we recommend you to take a look at how to configure a {declarative user profile} and possibly avoid changing the built-in templates by using all the capabilities provided by this feature.

    Also, the templates used by the declarative-user-profile feature to render the pages for the same flows are longer necessary and removed in this release:

    If you were using the declarative-user-profile feature in a previous release with customizations to the above templates, update the login-update-profile.ftl and register.ftl accordingly.

    New Freemarker template for the update profile page at first login through a broker

    In this release, the server will render the update profile page when the user is authenticating through a broker for the first time using the idp-review-user-profile.ftl template.

    In previous releases, the template used to update the profile during the first broker login flow was the login-update-profile.ftl , the same used to update the profile when users are authenticating to a realm.

    By using separate templates for each flow, a more clear distinction exist as to which flow a template is actually used rather than sharing a same template, and potentially introduce unexpected changes and behavior that should only affect pages for a specific flow.

    If you have customizations to the login-update-profile.ftl template to customize how users update their profiles when authenticating through a broker, make sure to move your changes to the new template.

    Truststore Changes

    The spi-truststore-file-* options and the truststore related options https-trust-store-* are deprecated. Therefore, use the new default location for truststore material, conf/truststores , or specify your desired paths by using the truststore-paths option. For details, see the relevant guide .

    The tls-hostname-verifier property should be used instead of the spi-truststore-file-hostname-verification-policy property.

    A collateral effect of the changes is that now the truststore provider is always configured with some certificates (at least the default java trusted certificates are present). This new behavior can affect other parts of Keycloak.

    For example, webauthn registration can fail if attestation conveyance was configured to Direct validation. Previously, if the truststore provider was not configured the incoming certificate was not validated. But now this validation is always performed. The registration fails with invalid cert path error as the certificate chain sent by the dongle is not trusted by Keycloak. The Certificate Authorities of the authenticator need to be present in the truststore provider to correctly perform the attestation.

    Deprecated --proxy option

    The --proxy option has been deprecated and will be removed in a future release. The following table explains how the deprecated option maps to supported options.

    For hardened security, the --proxy-headers option does not allow selecting both forwarded and xforwarded values at the same time (as it was the case before for --proxy edge and --proxy reencrypt ). When using the proxy headers option, make sure your reverse proxy properly sets and overwrites the Forwarded or X-Forwarded-* headers respectively. To set these headers, consult the documentation for your reverse proxy. Misconfiguration will leave Keycloak exposed to security vulnerabilities. If the proxy.headers field is not specified, the Operator falls back to the previous behavior by implicitly setting proxy=passthrough by default. This results in deprecation warnings in the server log. This fallback will be removed in a future release.

    Changes to the user representation in both Admin API and Account contexts

    Both org.keycloak.representations.idm.UserRepresentation and org.keycloak.representations.account.UserRepresentation representation classes have changed so that the root user attributes (such as username , email , firstName , lastName , and locale ) have a consistent representation when fetching or sending the representation payload to the Admin and Account APIS, respectively.

    The username , email , firstName , lastName , and locale attributes were moved to a new org.keycloak.representations.idm.AbstractUserRepresentation base class.

    Also the getAttributes method is targeted for representing only custom attributes, so you should not expect any root attribute in the map returned by this method. This method is mainly targeted for clients when updating or fetching any custom attribute for a give user.

    In order to resolve all the attributes including the root attributes, a new getRawAttributes method was added so that the resulting map also includes the root attributes. However, this method is not available from the representation payload and it is targeted to be used by the server when managing user profiles.

    https-client-auth is a build time option

    Option https-client-auth had been treated as a run time option, however this is not supported by Quarkus. The option needs to be handled at build time instead.

    Sequential loading of offline sessions and remote sessions

    Starting with this release, the first member of a Keycloak cluster will load remote sessions sequentially instead of in parallel. If offline session preloading is enabled, those will be loaded sequentially as well.

    The previous code led to high resource-consumption across the cluster at startup and was challenging to analyze in production environments and could lead to complex failure scenarios if a node was restarted during loading. Therefore, it was changed to sequential session loading.

    For offline sessions, the default in this and previous versions of Keycloak is to load those sessions on demand, which scales better with a lot of offline sessions than the attempt to preload them in parallel. Setups that use this default setup are not affected by the change of the loading strategy for offline sessions. Setups that have offline session preloading enabled should migrate to a setup where offline-session preloading is disabled.

    Deprecated offline session preloading

    The default behavior of Keycloak is to load offline sessions on demand. The old behavior to preload them at startup is now deprecated, as preloading them at startup does not scale well with a growing number of sessions, and increases Keycloak memory usage. The old behavior will be removed in a future release.

    To re-enable old behavior while it is deprecated and not removed yet, use the feature flag and the SPI option as shown below:

    bin/kc.[sh|bat] start --features-enabled offline-session-preloading --spi-user-sessions-infinispan-preload-offline-sessions-from-database=true

    The API of UserSessionProvider deprecated the method getOfflineUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId) . Instead of this method, use getOfflineUserSessionByBrokerUserIdStream(RealmModel, String brokerUserId) to first get the sessions of a user, and then filter by the broker session ID as needed.

    Infinispan metrics use labels for cache manager and cache names

    When enabling metrics for Keycloak’s embedded caches, the metrics now use labels for the cache manager and the cache names.

    Old metric example without labels
    vendor_cache_manager_keycloak_cache_sessions_statistics_approximate_entries_in_memory{cache="sessions",node="..."}
    New metric example with labels
    vendor_statistics_approximate_entries_in_memory{cache="sessions",cache_manager="keycloak",node="..."}

    To revert the change for an installation, use a custom Infinispan XML configuration and change the configuration as follows:

    <metrics names-as-tags="false" />

    User attribute value length extension

    As of this release, Keycloak supports storing and searching by user attribute values longer than 255 characters, which was previously a limitation.

    In setups where users are allowed to update attributes, for example, via the account console, prevent denial of service attacks by adding validations. Ensure that no unmanaged attributes are allowed and all editable attributes have a validation that limits the input length.

    For unmanaged attributes, the maximum length is 2048 characters. For managed attributes, the default maximum length is 2048 characters. Administrator can change this by adding a validator of type length .

    Keycloak caches user-related objects in its internal caches. Using longer attributes increases the memory that is consumed by the cache. Therefore, limiting the size of the length attributes is recommended. Consider storing large objects outside Keycloak and reference them by ID or URL.

    This change adds new indexes on the tables USER_ATTRIBUTE and FED_USER_ATTRIBUTE . If those tables contain more than 300000 entries, Keycloak will skip the index creation by default during the automatic schema migration and instead log the SQL statement on the console during migration to be applied manually after Keycloak’s startup. See the Upgrading Guide for details on how to configure a different limit.

    Additional migration steps for LDAP

    This is for installations that match all the following criteria:

    User attributes in the LDAP directory are larger than 2048 characters or binary attributes that are larger than 1500 bytes.

    The attributes are changed by admins or users via the admin console, the APIs or the account console.

    Declare the attributes identified above as managed attributes in the user profile of the realm.

    Define a length validator for each attribute added in the previous step specifying the desired minimum and maximum length of the attribute value. For binary values, add 33 percent to the expected binary length to count in the overhead for Keycloak’s internal base64 encoding of binary values.

    Entries in table FED_USER_ATTRIBUTE with contents in the VALUE column that are larger than 2048 characters. This table is used for custom user providers which have federation enabled.

    The long attributes are changed by admins or users via the admin console or the account console.

    Declare the attributes identified above as managed attributes in the user profile of the realm.

    Define a length validator for each attribute added in the previous step specifying the desired minimum and maximum length of the attribute value.

    In this release, the API will use the email-verification.ftl template instead of executeActions.ftl .

    Before upgrading
    Perform the following action(s): Verify Email
    After upgrading
    Confirm validity of e-mail address [email protected].

    If you have customized the executeActions.ftl template to modify how users verify their email using this API, ensure that you transfer your modifications to the new template.

    A new parameter called lifespan will be introduced to allow overriding of the default lifespan value (12 hours).

    If you prefer the previous behavior, use the execute-actions-email API as follows.

    PUT /admin/realms/{realm}/users/{id}/execute-actions-email
    ["VERIFY_EMAIL"]

    Changes to Password Hashing

    In this release, we adapted the password hashing defaults to match the OWASP recommendations for Password Storage .

    As part of this change, the default password hashing provider has changed from pbkdf2-sha256 to pbkdf2-sha512 . Also, the number of default hash iterations for pbkdf2 based password hashing algorithms changed as follows:

    If a realm does not explicitly configure a password policy with hashAlgorithm and hashIterations , then the new configuration will take effect on the next password based login, or when a user password is created or updated.

    Performance of new password hashing configuration

    Tests on a machine with an Intel i9-8950HK CPU (12) @ 4.800GHz yielded the following ⌀ time differences for hashing 1000 passwords (averages from 3 runs). Note that the average duration for the PBKDF2WithHmacSHA1 was computed with a lower number of passwords due to the long runtime.

    Users of the pbkdf2 provider might need to explicitly reduce the number of hash iterations to regain acceptable performance. This can be done by configuring the hash iterations explicitly in the password policy of the realm.

    Expected increased overall CPU usage and temporary increased database activity

    The Concepts for sizing CPU and memory resources in the Keycloak High Availability guide have been updated to reflect the new hashing defaults. The CPU usage per password-based login in our tests increased by the factor of five, which includes both the changed password hashing and unchanged TLS connection handling. The overall CPU increase should be around the factor of two to three due to the averaging effect of Keycloak’s other activities like refreshing access tokens and client credential grants. Still, this depends on the unique workload of an installation.

    After the upgrade, during a password-based login, the user’s passwords will be re-hashed with the new hash algorithm and hash iterations as a one-off activity and updated in the database. As this clears the user from Keycloak’s internal cache, you will also see an increased read activity on the database level. This increased database activity will decrease over time as more and more user’s passwords have been re-hashed.

    How to keep using the old pbkdf2-sha256 password hashing?

    To keep the old password hashing for a realm, specify hashAlgorithm and hashIterations explicitly in the realm password policy.

    Operator Referenced Resource Polling

    Secrets and ConfigMaps referenced via the Keycloak CR will now be polled for changes, rather than watched via the api server. It may take around 1 minute for changes to be detected.

    This was done so to not require label manipulation on those resources. After upgrading if any Secret still has the operator.keycloak.org/component label, it may be removed or ignored.

    Renaming JPA provider configuration options for migration

    After removal of the Map Store the following configuration options were renamed:

    spi-connections-jpa-legacy-initialize-empty to spi-connections-jpa-quarkus-initialize-empty

    spi-connections-jpa-legacy-migration-export to spi-connections-jpa-quarkus-migration-export

    spi-connections-jpa-legacy-migration-strategy to spi-connections-jpa-quarkus-migration-strategy

    org.keycloak:keycloak-model-legacy-private to org.keycloak:keycloak-model-storage-private

    org.keycloak:keycloak-model-legacy-services to org.keycloak:keycloak-model-storage-services

    Temporary lockout log replaced with event

    There is now a new event USER_DISABLED_BY_TEMPORARY_LOCKOUT when a user is temporarily locked out by the brute force protector. The log with ID KC-SERVICES0053 has been removed as the new event offers the information in a structured form.

    As it is a success event, the new event is logged by default at the DEBUG level. Use the setting spi-events-listener-jboss-logging-success-level as described in the Event listener chapter in the Server Administration Guide to change the log level of all success events.

    To trigger custom actions or custom log entries, write a custom event listener as described in the Event Listener SPI in the Server Developer Guide .

    Operator Customization Property Keys

    The property keys used by the operator for advanced configuration have changed from operator.keycloak to kc.operator.keycloak .

    Keycloak CR resources options

    When no resources options are specified in the Keycloak CR and KeycloakRealmImport CR, default values are used. The default requests memory for Keycloak deployment and the realm import Job is set to 1700MiB , and the limits memory is set to 2GiB .

    Updates to cookies

    As part of refactoring cookie handling in Keycloak there are some changes to how cookies are set:

    All cookies will now have the secure attribute set if the request is through a secure context

    WELCOME_STATE_CHECKER cookies now set SameSite=Strict

    LocaleSelectorProvider.KEYCLOAK_LOCALE is deprecated as cookies are now managed through the CookieProvider

    HttpResponse.setWriteCookiesOnTransactionComplete has been removed

    HttpCookie is deprecated, please use NewCookie.Builder instead

    ServerCookie is deprecated, please use NewCookie.Builder instead

    Internal algorithm changed from HS256 to HS512

    The algorithm that Keycloak uses to sign internal tokens (a JWT which is consumed by Keycloak itself, for example a refresh or action token) is being changed from HS256 to the more secure HS512 . A new key provider named hmac-generated-hs512 is now added for realms. Note that in migrated realms the old hmac-generated provider and the old HS256 key are maintained and still validate tokens issued before the upgrade. The HS256 provider can be manually deleted when no more old tokens exist following the rotating keys guidelines .

    Different JVM memory settings when running in a container

    The JVM options -Xms and -Xmx were replaced by -XX:InitialRAMPercentage and -XX:MaxRAMPercentage when running in a container. Instead of the static maximum heap size settings, Keycloak specifies the maximum as 70% of the total container memory.

    As the heap size is dynamically calculated based on the total container memory, you should always set the memory limit for the container.

    GELF log handler has been deprecated

    With sunsetting of the underlying library providing integration with GELF, Keycloak will no longer support the GELF log handler out-of-the-box. This feature will be removed in a future release. If you require an external log management, consider using file log parsing.

    Because of issue #25078 , the jboss-logging message values are now quoted (character " by default) and sanitized to prevent any line break. There are two new options in the provider ( spi-events-listener-jboss-logging-sanitize and spi-events-listener-jboss-logging-quotes ) that allow you to customize the new behavior. For example, to avoid both sanitization and quoting, the server can be started in this manner:

    ./kc.sh start --spi-events-listener-jboss-logging-sanitize=false --spi-events-listener-jboss-logging-quotes=none ...

    For more information about the options, see all provider configuration guide .

    Migrating to 23.0.2

    Valid redirect URIs for clients are always compared with exact string matching

    Edit this section Report an issue

    Version 1.8.0 introduced a lower-case for the hostname and scheme when comparing a redirect URI with the specified valid redirects for a client. Unfortunately it did not fully work in all the protocols, and, for example, the host was lower-cased for http but not for https . As OAuth 2.0 Security Best Current Practice advises to compare URIs using exact string matching, Keycloak will follow the recommendation and for now on valid redirects are compared with exact case even for the hostname and scheme.

    For realms relying on the old behavior, the valid redirect URIs for their clients should now hold separate entries for each URI that should be recognized by the server.

    Although it introduces more steps and verbosity when configuring clients, the new behavior enables more secure deployments as pattern-based checks are frequently the cause of security issues. These issues are due to how they are implemented and how they are configured.

    Operator -secrets-store Secret

    Older versions of the operator created a Secret to track watched Secrets. Newer versions of the operator no longer use the -secrets-store Secret, so it may be deleted.

    If you are on 23.0.0 or 23.0.1 and see "org.keycloak.operator.controllers.KeycloakAdminSecretDependentResource → java.lang.IllegalStateException: More than 1 secondary resource related to primary" in the operator log then either delete the -secrets-store Secret, or upgrade to 23.0.2 where this is no longer an issue.

    Migrating to 23.0.0

    Added iss parameter to OAuth 2.0/OpenID Connect Authentication Response

    Edit this section Report an issue

    RFC 9207 OAuth 2.0 Authorization Server Issuer Identification specification adds the parameter iss in the OAuth 2.0/OpenID Connect Authentication Response for realizing secure authorization responses.

    In past releases, we did not have this parameter, but now Keycloak adds this parameter by default, as required by the specification.

    However, some OpenID Connect / OAuth2 adapters, and especially older Keycloak adapters, may have issues with this new parameter.

    For example, the parameter will be always present in the browser URL after successful authentication to the client application. In these cases, it may be useful to disable adding the iss parameter to the authentication response. This can be done for the particular client in the Keycloak Admin Console, in client details in the section with OpenID Connect Compatibility Modes , described in Compatibility with older adapters . Dedicated Exclude Issuer From Authentication Response switch exists, which can be turned on to prevent adding the iss parameter to the authentication response.

    Wildcard characters handling

    JPA allows wildcards % and _ when searching, while other providers like LDAP allow only * . As * is a natural wildcard character in LDAP, it works in all places, while with JPA it only worked at the beginning and the end of the search string. Starting with this release the only wildcard character is * which work consistently across all providers in all places in the search string. All special characters in a specific provider like % and _ for JPA are escaped. For exact search, with added quotes such as "w*ord" , the behavior remains the same as in previous releases.

    Language files for themes default to UTF-8 encoding

    This release now follows the standard mechanisms of Java and later, which assumes resource bundle files to be encoded in UTF-8.

    Previous versions of Keycloak supported specifying the encoding in the first line with a comment like # encoding: UTF-8 , which is no longer supported and is ignored.

    Message properties files for themes are now read in UTF-8 encoding, with an automatic fallback to ISO-8859-1 encoding. If you are using a different encoding, convert the files to UTF-8.

    Changes to the value format of claims mapped by the realm and client role mappers

    Before this release, both realm ( User Realm Role ) and client ( User Client Role ) protocol mappers were mapping a stringfied JSON array when the Multivalued setting was disabled.

    However, the Multivalued setting indicates whether the claim should be mapped as a list or, if disabled, only a single value from the same list of values.

    In this release, the role and client mappers now map to a single value from the effective roles of a user when they are marked as single-valued ( Multivalued disabled).

    Changes to password fields in Login UI

    In this version we want to introduce a toggle to hide/show password inputs.

    Affected pages:

    login.ftl

    login-password.ftl

    login-update-password.ftl

    register.ftl

    register-user-profile.ftl

    In general all <input type="password" name="password" /> are encapsulated within a div now. The input element is followed by a button which toggles the visibility of the password input.

    Old code example:

    <input type="password" id="password" name="password" autocomplete="current-password" style="display:none;"/>

    New code example:

    <div class="${properties.kcInputGroup!}">
        <input type="password" id="password" name="password" autocomplete="current-password" style="display:none;"/>
        <button class="pf-c-button pf-m-control" type="button" aria-label="${msg('showPassword')}"
                aria-controls="password" data-password-toggle
                data-label-show="${msg('showPassword')}" data-label-hide="${msg('hidePassword')}">
            <i class="fa fa-eye" aria-hidden="true"></i>
        </button>
    

    Default Keycloak CR Hostname

    When running on OpenShift, with ingress enabled, and with the spec.ingress.classname set to openshift-default, you may leave the spec.hostname.hostname unpopulated in the Keycloak CR. The operator will assign a default hostname to the stored version of the CR similar to what would be created by an OpenShift Route without an explicit host - that is ingress-namespace.appsDomain If the appsDomain changes, or should you need a different hostname for any reason, then update the Keycloak CR.

    The deprecated auto-build CLI option was removed

    The auto-build CLI option has been marked as deprecated for a long time. In this release, it was completely removed, and it is no longer supported.

    When executing the start command, the server is automatically built based on the configuration. In order to prevent this behavior, set the --optimized flag.

    kc.sh and shell metacharacters

    The kc.sh no longer uses an additional shell eval on parameters and the environment variables JAVA_OPTS_APPEND and JAVA_ADD_OPENS, thus the continued use of double escaping/quoting will result in the parameter being misunderstood. For example instead of

    bin/kc.sh start --db postgres --db-username keycloak --db-url "\"jdbc:postgresql://localhost:5432/keycloak?ssl=false&connectTimeout=30\"" --db-password keycloak --hostname localhost

    Use a single escape:

    bin/kc.sh start --db postgres --db-username keycloak --db-url "jdbc:postgresql://localhost:5432/keycloak?ssl=false&connectTimeout=30" --db-password keycloak --hostname localhost

    This change also means you cannot invoke kc.sh using a single quoted value of all arguments. For example you can no longer use

    bin/kc.sh "start --help"

    it must instead be individual arguments

    bin/kc.sh start --help

    Similarly instead of

    bin/kc.sh build "--db postgres"

    it must instead be individual arguments

    bin/kc.sh build --db postgres

    The usage of individual arguments is also required in Dockerfile run commands.

    Removed RegistrationProfile form action

    The form action RegistrationProfile (displayed in the UI of authentication flows as Profile Validation) was removed from the codebase and also from all authentication flows. By default, it was in the built-in registration flow of every realm. The validation of user attributes as well as creation of the user including all that user’s attributes is handled by RegistrationUserCreation form action and hence RegistrationProfile is not needed anymore. There is usually no further action needed in relation to this change, unless you used RegistrationProfile class in your own providers.

    Deprecated methods from data providers and models

    RealmModel#getTopLevelGroupsStream() and overloaded methods are now deprecated

    GroupProvider changes

    A new method has been added to allow for searching and paging through top level groups. If you implement this interface you will need to implement the following method:

    Stream<GroupModel> getTopLevelGroupsStream(RealmModel realm,
                                               String search,
                                               Boolean exact,
                                               Integer firstResult,
                                               Integer maxResults)

    Partial export requires manage-realm permission

    The endpoint POST {keycloak server}/realms/{realm}/partial-export and the corresponding action in the admin console now require manage-realm permission for execution instead of view-realm. This endpoint exports the realm configuration into a JSON file and the new permission is more appropriate. The parameters exportGroupsAndRoles and exportClients, which include the realm groups/roles and clients in the export respectively, continue managing the same permissions (query-groups and view-clients).

    Removal of the options to trim the event’s details length

    Since this release, Keycloak supports long value for EventEntity details column. Therefore, it no longer supports options for trimming event detail length --spi-events-store-jpa-max-detail-length and --spi-events-store-jpa-max-field-length.

    User Profile updates

    This release includes many fixes and updates that are related to user profile as we are working on promoting this feature from preview to officially supported. Minor changes exist for the SPI such as the newly added method boolean isEnabled(RealmModel realm) on UserProfileProvider interface. Also some user profile classes and some validator related classes (but not builtin validator implementations) were moved from keycloak-server-spi-private to keycloak-server-spi module. However, the packages for java classes remain the same. You might be affected in some corner cases, such as when you are overriding the built-in implementation with your own UserProfileProvider implementation. However, note that UserProfileProvider is an unsupported SPI.

    Removal of the Map Store

    The Map Store has been an experimental feature in previous releases. Starting with this release, it is removed and users should continue to use the current JPA store.

    Since this release, it is no longer possible to use --storage related CLI options. The modules keycloak-model-map* have been removed.

    Removed namespaces from our translations

    All translations are moved into one file for the Admin Console. If you have made your own translations or extended the Admin Console you will need to migrate them to this new format. Also if you have "overrides" in your database, you will have to remove the namespace from the keys. Some keys are the same only in different namespaces, this is most obvious to help. In these cases we have postfix the key with Help.

    If you want you can use this node script to help with the migration. It will take all the single files and put them into a new one and also take care of some of the mapping:

    import { readFileSync, writeFileSync, appendFileSync } from "node:fs";
    const ns = [
      "common",
      "common-help",
      "dashboard",
      "clients",
      "clients-help",
      "client-scopes",
      "client-scopes-help",
      "groups",
      "realm",
      "roles",
      "users",
      "users-help",
      "sessions",
      "events",
      "realm-settings",
      "realm-settings-help",
      "authentication",
      "authentication-help",
      "user-federation",
      "user-federation-help",
      "identity-providers",
      "identity-providers-help",
      "dynamic",
    const map = new Map();
    const dup = [];
    ns.forEach((n) => {
      const rawData = readFileSync(n + ".json");
      const translation = JSON.parse(rawData);
      Object.entries(translation).map((e) => {
        const name = e[0];
        const value = e[1];
        if (map.has(name) && map.get(name) !== value) {
          if (n.includes("help")) {
            map.set(name + "Help", value);
          } else {
            map.set(name, value);
            dup.push({
              name: name,
              value: map.get(name),
              dup: { ns: n, value: value },
        } else {
          map.set(name, value);
    writeFileSync(
      "translation.json",
      JSON.stringify(Object.fromEntries(map.entries()), undefined, 2),
    const mapping = [
      ["common:clientScope", "clientScopeType"],
      ["identity-providers:createSuccess", "createIdentityProviderSuccess"],
      ["identity-providers:createError", "createIdentityProviderError"],
      ["clients:createError", "createClientError"],
      ["clients:createSuccess", "createClientSuccess"],
      ["user-federation:createSuccess", "createUserProviderSuccess"],
      ["user-federation:createError", "createUserProviderError"],
      ["authentication-help:name", "flowNameHelp"],
      ["authentication-help:description", "flowDescriptionHelp"],
      ["clientScopes:noRoles", "noRoles-clientScope"],
      ["clientScopes:noRolesInstructions", "noRolesInstructions-clientScope"],
      ["users:noRoles", "noRoles-user"],
      ["users:noRolesInstructions", "noRolesInstructions-user"],
      ["clients:noRoles", "noRoles-client"],
      ["clients:noRolesInstructions", "noRolesInstructions-client"],
      ["groups:noRoles", "noRoles-group"],
      ["groups:noRolesInstructions", "noRolesInstructions-group"],
      ["roles:noRoles", "noRoles-roles"],
      ["roles:noRolesInstructions", "noRolesInstructions-roles"],
      ["realm:realmName:", "realmNameField"],
      ["client-scopes:searchFor", "searchForClientScope"],
      ["roles:searchFor", "searchForRoles"],
      ["authentication:title", "titleAuthentication"],
      ["events:title", "titleEvents"],
      ["roles:title", "titleRoles"],
      ["users:title", "titleUsers"],
      ["sessions:title", "titleSessions"],
      ["client-scopes:deleteConfirm", "deleteConfirmClientScopes"],
      ["users:deleteConfirm", "deleteConfirmUsers"],
      ["groups:deleteConfirm_one", "deleteConfirmGroup_one"],
      ["groups:deleteConfirm_other", "deleteConfirmGroup_other"],
      ["identity-providers:deleteConfirm", "deleteConfirmIdentityProvider"],
      ["realm-settings:deleteConfirm", "deleteConfirmRealmSetting"],
      ["roles:whoWillAppearLinkText", "whoWillAppearLinkTextRoles"],
      ["users:whoWillAppearLinkText", "whoWillAppearLinkTextUsers"],
      ["roles:whoWillAppearPopoverText", "whoWillAppearPopoverTextRoles"],
      ["users:whoWillAppearPopoverText", "whoWillAppearPopoverTextUsers"],
      ["client-scopes:deletedSuccess", "deletedSuccessClientScope"],
      ["identity-providers:deletedSuccess", "deletedSuccessIdentityProvider"],
      ["realm-settings:deleteSuccess", "deletedSuccessRealmSetting"],
      ["client-scopes:deleteError", "deletedErrorClientScope"],
      ["identity-providers:deleteError", "deletedErrorIdentityProvider"],
      ["realm-settings:deleteError", "deletedErrorRealmSetting"],
      ["realm-settings:saveSuccess", "realmSaveSuccess"],
      ["user-federation:saveSuccess", "userProviderSaveSuccess"],
      ["realm-settings:saveError", "realmSaveError"],
      ["user-federation:saveError", "userProviderSaveError"],
      ["realm-settings:validateName", "validateAttributeName"],
      ["identity-providers:disableConfirm", "disableConfirmIdentityProvider"],
      ["realm-settings:disableConfirm", "disableConfirmRealm"],
      ["client-scopes:updateSuccess", "updateSuccessClientScope"],
      ["client-scopes:updateError", "updateErrorClientScope"],
      ["identity-providers:updateSuccess", "updateSuccessIdentityProvider"],
      ["identity-providers:updateError", "updateErrorIdentityProvider"],
      ["user-federation:orderChangeSuccess", "orderChangeSuccessUserFed"],
      ["user-federation:orderChangeError", "orderChangeErrorUserFed"],
      ["authentication-help:alias", "authenticationAliasHelp"],
      ["authentication-help:flowType", "authenticationFlowTypeHelp"],
      ["authentication:createFlow", "authenticationCreateFlowHelp"],
      ["client-scopes-help:rolesScope", "clientScopesRolesScope"],
      ["client-scopes-help:name", "scopeNameHelp"],
      ["client-scopes-help:description", "scopeDescriptionHelp"],
      ["client-scopes-help:type", "scopeTypeHelp"],
      ["clients-help:description", "clientDescriptionHelp"],
      ["clients-help:clientType", "clientsClientTypeHelp"],
      ["clients-help:scopes", "clientsClientScopesHelp"],
      ["common:clientScope", "clientScopeTypes"],
      ["dashboard:realmName", "realmNameTitle"],
      ["common:description", "description"],
    mapping.forEach((m) => {
      const key = m[0].split(":");
      try {
        const data = readFileSync(key[0] + ".json");
        const translation = JSON.parse(data);
        const value = translation[key[1]];
        if (value) {
          appendFileSync(
            "translation.json",
            '"' + m[1] + '": ' + JSON.stringify(value) + ',\n',
      } catch (error) {
        console.error("skipping namespace key: " + key);
    

    Save this into a file called transform.mjs in your public/locale/<language> folder and run it with:

    node ./transform.mjs

    A new parameter --spi-user-profile-declarative-user-profile-max-email-local-part-length is added to set max email local part length taking backwards compatibility into consideration. The default value is 64. Example of usage:

    kc.[sh|bat] start --spi-user-profile-declarative-user-profile-max-email-local-part-length=100 ...

    The option Never expires is now removed from all the combos of the Advanced Settings client tab. This option was misleading because the different lifespans or idle timeouts were never infinite, but limited by the general user session or realm values. Therefore, this option is removed in favor of the other two remaining options: Inherits from the realm settings (the client uses general realm timeouts) and Expires in (the value is overriden for the client). Internally the Never expires was represented by -1. Now that value is shown with a warning in the Admin Console and cannot be set directly by the administrator.

    New LinkedIn OpenID Connect social provider

    A new social identity provider called LinkedIn OpenID Connect has been introduced for the business and employment-focused platform. LinkedIn released recently a new product for developers called Sign In with LinkedIn using OpenID Connect. The product provides a new way to authenticate members using OpenID Connect, but the default OpenID Connect v1.0 identity provider does not work with it at present time. For that reason, Keycloak adds this new identity provider as the specific social provider for the new product.

    The old LinkedIn way based on OAuth seems to be completely removed from the developer portal. How the existing LinkedIn social provider is working with current applications is not clear. Keycloak maintains the old provider renamed to LinkedIn (deprecated), but in a deprecated feature called linkedin-oauth which is disabled by default. It will be removed in future versions. Please enable it again at startup if needed:

    kc.[sh|bat] start --features linkedin-oauth ...

    Keycloak migrated its codebase from Java EE (Enterprise Edition) to its successor Jakarta EE, which brings various changes into Keycloak.

    We have upgraded all Jakarta EE specifications in order to support Jakarta EE 10, such as:

    Jakarta EE 10 provides a modernized, simplified, lightweight approach to building cloud-native Java applications. The main changes provided within this initiative are changing the namespace from javax.* to jakarta.*. It does not apply for javax.* packages provided directly in the JDK, such as javax.security, javax.net, javax.crypto, etc.

    You can be affected by these changes in your custom extensions, providers or JPA entities.

    Upgrade to Quarkus 3

    Keycloak upgraded to version 3 of the Quarkus Java framework. Quarkus 3 continues the tradition of propelling Java development by moving fast and providing a cutting-edge user experience with the latest technologies. It continues to improve overall performance and efficiency.

    Quarkus 3 is based on Jakarta EE 10, the same as Keycloak, creating smooth interoperability between them. In addition, it contains Eclipse MicroProfile 6, which aligns with Jakarta EE 10 Core Profile. The central part of the Quarkus 3 upgrade is built-in support for JPA 3.1 and Hibernate ORM 6.

    quarkus.hibernate-orm.* properties no longer working

    For Quarkus 3, Hibernate ORM configurations must be specified in either the persistence.xml file or in Quarkus properties, but not in both places. Keycloak uses a persistence.xml file, therefore, it is no longer possible to override Keycloak’s JPA store configurations via Quarkus’ configuration properties for the default persistence unit whose names start with quarkus.hibernate-orm.

    Upgrade to Hibernate ORM 6

    Keycloak now benefits from the upgrade to Hibernate ORM 6.2, which includes improved performance, better SQL, modern JDK support, and support for modern RDBMS features. The performance improvements primarily affect JDBC, HQL Translation, and Criteria Translation.

    If you have custom providers or JPA entities, these changes may affect you.

    We recommend reviewing the Quarkus migration guide or the Hibernate release notes for more information.

    Legacy Promise API removed from Keycloak JS adapter

    The legacy Promise API methods have been removed from the Keycloak JS adapter. This means that calling .success() and .error() on promises returned from the adapter is no longer possible. Instead standardized Promise methods such as .then() and .catch() should be used.

    Before migration:
    const keycloak = new Keycloak();
    keycloak.init()
      .success(function(authenticated) {
        alert(authenticated ? 'authenticated' : 'not authenticated');
      }).error(function() {
        alert('failed to initialize');
    
    After migration:
    const keycloak = new Keycloak();
    keycloak.init()
      .then(function(authenticated) {
        alert(authenticated ? 'authenticated' : 'not authenticated');
      }).catch(function() {
        alert('failed to initialize');
    
    Or alternatively, when using the await keyword to unwrap these promises:
    const keycloak = new Keycloak();
    try {
      const authenticated = await keycloak.init();
      alert(authenticated ? 'authenticated' : 'not authenticated');
    } catch (error) {
      alert('failed to initialize');
    

    Export and Import perform an automatic build

    In previous releases, the export and import commands required a build command to be run first. Starting with this release, the export and import commands perform an automatic rebuild of Keycloak if a build time configuration has changed.

    When migrating existing scripts that run a build command first, migrate by adding the --optimized command line option to the export and import command to avoid Keycloak automatically re-building the image. Not adding the --optimized option in this might make Keycloak trigger a rebuild and revert to the default values, and then connecting to the database for export and import will not work.

    The following examples assume that runtime parameters like a database password are provided via a configuration file or an environment variable.

    Before migration: Running the build command before running the export command
    bin/kc.[sh|bat] build --db=postgres ...
    bin/kc.[sh|bat] export --dir <dir>
    After migration: Adding --optimized to the export command
    bin/kc.[sh|bat] build --db=postgres ...
    bin/kc.[sh|bat] export --optimized --dir <dir>
    After migration: Leveraging the auto-build functionality
    bin/kc.[sh|bat] export --dir <dir> --db=postgres ...

    In previous releases the export and import commands allowed runtime parameters such as a database URL only in configuration files or environment variables. Starting with this release, those runtime parameters are now available on the command line as well. Use the --help option to find out about the supported parameters.

    Renamed Keycloak Admin client artifacts

    After the upgrade to Jakarta EE, artifacts for Keycloak Admin clients were renamed to more descriptive names with consideration for long-term maintainability. We still provide two separate Keycloak Admin clients, one with Jakarta EE and the other with Java EE support.

    We stopped releasing the org.keycloak:keycloak-admin-client-jakarta artifact. The default one for the Keycloak Admin client with Jakarta EE support is org.keycloak:keycloak-admin-client (since version 22.0.0).

    The new artifact with Java EE support is org.keycloak:keycloak-admin-client-jee.

    Jakarta EE support
    Before migration:
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-admin-client-jakarta</artifactId>
        <version>21.0.0</version>
    </dependency>
    After migration:
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-admin-client</artifactId>
        <version>22.0.0</version>
    </dependency>
    <groupId>org.keycloak</groupId> <artifactId>keycloak-admin-client</artifactId> <version>21.0.0</version> </dependency>
    After migration:
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-admin-client-jee</artifactId>
        <version>22.0.0</version>
    </dependency>

    Passthrough proxy mode changes

    Keycloak’s proxy configuration setting for mode passthrough no longer parses HTTP forwarding headers in the request, as when a proxy forwards an HTTPS connection in passthrough mode, a proxy is unable to add, remove or update HTTP headers.

    Installations that want the HTTP headers in the client’s request to be parsed should use the edge or reencrypt setting.

    See Using a reverse proxy for details.

    Consistent fallback message resolving for all themes

    This change only may affect you when you are using realm localization messages.

    Up to this version, the resolving of fallback messages was inconsistent across themes, when realm localization messages were used. More information can be found in the following issue.

    The implementation has now been unified for all themes. In general, the message for the most specific matching language tag has the highest priority. If there are both a realm localization message and a Theme 18n message, the realm localization message has the higher priority. Summarized, the priority of the messages is as follows (RL = realm localization, T = Theme i18n files): RL <variant> > T <variant> > RL <region> > T <region> > RL <language> > T <language> > RL en > T en.

    Probably this can be better explained with an example: When the variant de-CH-1996 is requested and there is a realm localization message for the variant, this message will be used. If such a realm localization message does not exist, the Theme i18n files are searched for a corresponding message for that variant. If such a message does not exist, a realm localization message for the region (de-CH) will be searched. If such a realm localization message does not exist, the Theme i18n files are searched for a message for that region. If still no message is found, a realm localization message for the language (de) will be searched. If there is no matching realm localization message, the Theme i18n files are be searched for a message for that language. As last fallback, the English (en) translation is used: First, an English realm localization will be searched - if not found, the Theme 18n files are searched for an English message.

    UserQueryProvider changes

    UserQueryProvider interface was split into two. One is UserQueryMethodsProvider providing capabilities for querying users. Second one is UserCountMethodsProvider which provides capability for counting number of users in particular storage.

    Keycloak now has the ability to differentiate between user storage providers that can efficiently execute count queries and those that cannot. The UserQueryProvider interface still exists and extends both new interfaces. Therefore, there is no need for any modifications in the existing implementations of UserQueryProvider since it retains the same methods.

    LDAPStorageProvider search changes

    Starting with this release Keycloak uses a pagination mechanism when querying federated LDAP database. Searching for users should be consistent with search in local database.

    Since this release LDAPStorageProvider implements only UserQueryMethodsProvider, not UserQueryProvider.

    Deprecation of Keycloak OpenID Connect Adapters

    Starting with this release, we no longer will invest our time on the following Keycloak OpenID Connect Adapters:

    This move is already reflected in our documentation and in our quickstart repository. Please, consider looking at the following references for more information:

    Deprecation of Keycloak JEE SAML Adapter

    The Keycloak JEE SAML Adapter has been discontinued, and we will no longer invest our time on its development following this release.

    The official adapter is now based on Jakarta and should be used as soon as you switch your applications to this technology.

    This change is already in our documentation and in our quickstart repository. For more information, please consider looking at the following references:

    If you cannot migrate your applications to Jakarta, you can still use the "legacy" SAML JEE adapter and still be able to integrate with future releases of the server. However, consider upgrading your applications as soon as possible because we are no longer providing support to JEE.

    Changes for openshift-integration feature

    The preview feature openshift-integration was removed from Keycloak codebase and moved into separate extension. This includes moving of related providers such as custom client storage provider and token review endpoint for Openshift integration.

    If you used this feature, you should not use the openshift-integration feature anymore when starting Keycloak server and instead you need to deploy the JAR file from custom extension. You can check the Openshift extension and the instructions in it’s README file for how to deploy the extension to your Keycloak server.

    Http Challenge flow removed

    The built-in authentication flow http challenge was removed along with the authenticator implementations no-cookie-redirect, basic-auth, and basic-auth-otp. The http challenge authentication flow was also intended for Openshift integration and therefore it was removed along with other related capabilities as described above. Authenticator implementations were moved to the Openshift extension described in the previous paragraph.

    If you use the http challenge flow as a realm flow or as First Broker Login or Post Broker Login flow for any of your identity providers, the migration is not possible. Be sure to update your realm configuration to eliminate the use of the http challenge flow before migration. If you use the http challenge flow as Authentication Flow Binding Override for any client, the migration would complete, but you could no longer log in to that client. After the migration, you would need to re-create the flow and update the configuration of your clients to use the new/differentJson flow.

    Removing thirdparty dependencies

    The removal of openshift-integration allows us to remove few thirdparty dependencies from Keycloak distribution. This includes openshift-rest-client, okio-jvm, okhttp, commons-lang, commons-compress, jboss-dmr and kotlin-stdlib. This means that if you use any of these libraries as dependencies of your own providers deployed to Keycloak server, you may also need to copy those jar files explicitly to the Keycloak distribution providers directory as well.

    Context and dependency injection no longer enabled to JAX-RS Resources

    In order to provide a better runtime and leverage as much as possible the underlying stack, all injection points for contextual data using the javax.ws.rs.core.Context annotation were removed. The expected improvement in performance involves no longer creating proxies instances multiple times during the request lifecycle, and drastically reducing the amount of reflection code at runtime.

    If you are extending one of the following SPIs:

    If you need access to the current request and response objects, you can now obtain their instances directly from the KeycloakSession:

    @Context
    org.jboss.resteasy.spi.HttpRequest request;
    @Context
    org.jboss.resteasy.spi.HttpResponse response;

    was replaced by:

    KeycloakSession session = // obtain the session, which is usually available when creating a custom provider from a factory
    KeycloakContext context = session.getContext();
    HttpRequest request = context.getHttpRequest();
    HttpResponse response = context.getHttpResponse();

    In case you have no access to a KeycloakSession instance when invoking a JAX-RS resource method, you can obtain contextual data from the JAX-RS runtime as follows:

    KeycloakSession session = org.keycloak.common.util.Resteasy.getContextData(KeycloakSession.class);

    Additional contextual data can be obtained from the runtime through the KeycloakContext instance:

    KeycloakSession session = // obtain the session
    KeycloakContext context = session.getContext();
    MyContextualObject myContextualObject = context.getContextObject(MyContextualObject.class);

    You need to add an empty META-INF/beans.xml to the JAR file where your custom providers are packaged. Otherwise, they are not recognized by the server at runtime.

    If you are using RealmResourceSPI or AdminRealmResourceSpi, you have the choice between adding an empty file named beans.xml under META-INF or annotating the JAX-RS resource classes with the jakarta.ws.rs.ext.Provider annotation.

    You should also make sure your JAX-RS methods are declaring the expected media types for input and output by marking them with the @Consumes and @Produces annotations, respectively.

    Deprecated methods from data providers and models

    In earlier versions of Keycloak, provider and model interfaces underwent a cleanup process that involved deprecating certain methods. In this release the methods were removed and some additional methods were deprecated. The Javadoc for these methods from Keycloak 21 included information about their corresponding replacements.

    UserSessionPersisterProvider#loadUserSessions(int, int, boolean, int, String) was removed.

    Interfaces added for Streamification work were removed. Such as RoleMapperModel.Streams and similar.

    Streams interfaces in federated storage provider classes were deprecated.

    KeycloakModelUtils#getClientScopeMappings was removed.

    Deprecated methods from KeycloakSession were removed.

    UserQueryProvider#getUsersStream methods were removed.

    Multiple Keycloak instances

    Multiple Keycloak CRs may be created in the same namespace and will be managed independently by the operator. To allow for this StatefulSets created by older versions of the operator must be re-created. This will happen automatically when the operator is upgraded and lead to small amount of downtime.

    k8s.keycloak.org/v2alpha1 changes

    The condition status field was changed from a boolean to a string for conformance with standard Kubernetes conditions. In the CRD it will temporarily be represented as accepting any content, but it will only ever be a string. Please make sure any of your usage of this field is updated to expect the values "True", "False", or "Unknown", rather than true or false.

    Keycloak supports IPv4/IPv6 dual stack

    Keycloak supports the IPv4/IPv6 dual stack and can be accessible by default via the IPv4 and IPv6 addresses. In the older versions of Keycloak, the default approach was to use only IPv4 addresses.

    For more details, see Configure Keycloak Server with IPv4 or IPv6.

    In the previous version, when Keycloak was used on Java 17 with Javascript providers (Script authenticator, Javascript authorization policy or Script protocol mappers for OIDC and SAML clients), it was needed to copy javascript engine to the distribution. This is no longer needed as Nashorn javascript engine is available in Keycloak server by default. When you deploy script providers, it is recommended to not copy the nashorn script engine and it’s dependencies into the Keycloak distribution.

    Change of the default Client ID mapper of Service Account Client

    Default Client ID mapper of Service Account Client has been changed. Token Claim Name field value has been changed from clientId to client_id. client_id claim is compliant with OAuth2 specifications:

    The terms_and_conditions user attribute was accidentally changed in 21.0.0 to uppercase. This version reverts the user attribute back to lowercase. The value of the attribute is set when accepting Terms and Conditions page.

    If any of your custom extensions relies on this attribute, you may need to adjust your code to check both attributes terms_and_conditions and TERMS_AND_CONDITIONS.

    Keycloak provides an optional a metrics endpoint which exports metrics in the Prometheus format. In this release the implementation to provide this data switched from SmallRye to Micrometer, which is the recommended metrics library for Quarkus.

    Due to this change, metrics have been renamed. The following table shows some examples.

    Before upgrading it is recommended to review all metrics returned from the endpoint before and after the change, and update their usage in dashboards and alerts.

    Table 1. Examples of changed metrics names

    Deprecated RSA_SHA1 and DSA_SHA1 algorithms for SAML

    Algorithms RSA_SHA1 and DSA_SHA1, which can be configured as Signature algorithms on SAML adapters, clients and identity providers are deprecated. We recommend to use safer alternatives based on SHA256 or SHA512. Also, verifying signatures on signed SAML documents or assertions with these algorithms do not work on Java 17 or higher. If you use this algorithm and the other party consuming your SAML documents is running on Java 17 or higher, verifying signatures will not work.

    The possible workaround is to remove algorithms such as http://www.w3.org/2000/09/xmldsig#rsa-sha1 or http://www.w3.org/2000/09/xmldsig#dsa-sha1 from the list of "disallowed algorithms" configured on property jdk.xml.dsig.secureValidationPolicy in the file $JAVA_HOME/conf/security/java.security.

    SAML SP metadata changes

    In this version, Keycloak will refuse to decrypt assertions encrypted using a realm key generated for signing purpose. This change means all encrypted communication from IDP to SP (where Keycloak acts as the SP) will stop working.

    There are two ways to make this work:

    either update the IDP configuration with the metadata generated by a newer version of Keycloak,

    or run Keycloak in backward compatibility mode that will make Keycloak work with the metadata generated by older Keycloak versions. This mode can be enabled using -Dkeycloak.saml.deprecated.encryption=true flag. Note this backward compatibility mode is planned to be removed in Keycloak 24.

    Deprecated methods from user session provider were removed

    In Keycloak 13 there was introduced UserLoginFailureProvider and some methods from UserSessionProvider were moved there. The methods in UserSessionProvider were deprecated and now has been removed. Javadoc of these methods contained a corresponding replacement (see Javadoc of Keycloak 20 release).

    Custom themes using old admin console won’t work

    The old admin console, which was deprecated in previous versions, was finally removed. This also means that your custom themes, which were using it as parent theme or importing from it, won’t work. It is highly recommended to not deploy such themes at all as extending old admin console is not applicable anymore and there can be issues in Keycloak (at least warnings or errors in the logs) with such themes deployed.

    Curl has been removed from the container

    The Keycloak Container Image has been modified to enhance security. As a result, curl and other CLI tools have been removed, which you may have been using in your customized image. See the updated container guide for information on how to handle this change.

    Keycloak ships for development purposes with an H2 database driver. As it is intended for development purposes only, it should never be used in a production environment.

    In this release, the H2 driver has been upgraded from version 1.x to version 2.x. This change might require changes to the H2 JDBC URL or migration of the H2 database files in an existing Keycloak setup.

    Changes to the H2 JDBC URL

    For Keycloak to run with its JPA legacy store with H2 version 2.x, the JDBC URL requires the attribute NON_KEYWORDS=VALUE.

    In a setup where H2 is initialized by Keycloak without extra parameters, Keycloak will append the attribute automatically. This is the default for development setups.

    If an H2 JDBC URL is provided on the command line or in a configuration file, and it already contains the NON_KEYWORDS= attribute in the JDBC URL, this attribute needs to be amended with the VALUE keyword.

    If the connection factory for the H2 database is initialized outside Keycloak, that initialization needs to take care of adding the NON_KEYWORDS attribute.

    See the H2 documentation on the NON_KEYWORDS attribute for details.

    Upgrade of H2 database files

    H2 database base files created with H2 version 1.x should not be used with version 2.x.

    Purge existing H2 database files to start with an empty database, export and import the realms using Keycloak’s export and import functionality, or refer to the migration notes on the H2 database project’s website for details on how to migrate H2 database contents.

    serverConfiguration free-form field was renamed

    From now on it’s called additionalOptions. The idea behind this decision is to align it more with the Keycloak Quarkus distribution and achieve/preserve a naming consistency. serverConfiguration can be still used for configuring options that haven’t got a declared alternative in Keycloak custom resources (CRs). A good example of such use can be service providers.

    Ingress options were refined

    In the past, it used to be defined via the disableDefaultIngress property. We decided to clarify it a bit, thus from now on you can use the following structure to control your ingress settings:

    spec:
        ingress:
          enabled: false
    hostname: [keycloak-server-hostname] admin: [admin-console-hostname] adminUrl: [admin-console-base-url] strict: [true|false] strictBackchannel: [true|false]
    Some fields are no longer required

    The hostname and tlsSecret fields are now optional to align with the Quarkus distribution configuration. With that we also removed the possibility to set INSECURE-DISABLE special value to those fields. In order to disable hostname checks and enable HTTP, please follow the same approach as with the Quarkus distribution, i.e. set strict: false, strictBackchannel: false and httpEnabled: true fields.

    Deprecated methods from data providers and models were removed

    Prior to Keycloak 15, there was a clean-up of provider and model interfaces where we deprecated some methods. Javadoc of these methods contained a corresponding replacement method (see Javadoc of Keycloak 19 release). In this release the methods were removed. The following is a list of all changed classes.

    The most common patterns for deprecating and removing the methods are the following.

    Consistent parameter ordering - methods now have strict parameter ordering where RealmModel is always the first parameter.

    For example in UserLookupProvider interface

    @Deprecated
    UserModel getUserById(String id, RealmModel realm);

    was replaced by

    UserModel getUserById(RealmModel realm, String id)

    At Keycloak 18.0.0, the logout is now compatible with the new OIDC specification, which changed the handling for the url parameters. However, to also remain compatible with earlier versions, a compatibility flag is introduced. See the Upgrading Guide for further information for the backwards compatibility option, which allows your application to still use the old format for the url parameters.

    While the url parameters can now be configured to be compatible, there was still one incompatibility with keycloak 17 and earlier releases. If the user does not provide a valid idTokenHint, a logout prompt appears instead of a successful logout redirect. Therefore, a new compatibility flag suppress-logout-confirmation-screen is introduced to suppress the logout screen.

    You can enable this parameter when you start the server by entering the following command:

    bin/kc.[sh|bat] --spi-login-protocol-openid-connect-suppress-logout-confirmation-screen=true start

    With this configuration, you can still use the logout endpoint without a user prompt.

    Deploying scripts through SAML javascript protocol mapper

    Until now, administrators, which used SAML javascript protocol mapper on their SAML clients or client scopes, were allowed to upload scripts to the server through the Keycloak Administration Console as well as through the RESTful Admin API.

    For now on, this capability is disabled and users should deploy scripts directly to the server. This behaviour is aligned with other script based providers. For more details, please take a look at JavaScript Providers.

    UserInfo Endpoint Changes

    Error response changes

    The UserInfo endpoint is now returning error responses fully compliant with RFC 6750 (The OAuth 2.0 Authorization Framework: Bearer Token Usage). Error code and description (if available) are provided as WWW-Authenticate challenge attributes rather than JSON object fields. The responses will be the following, depending on the error condition:

    In case no access token is provided:

    401 Unauthorized
    WWW-Authenticate: Bearer realm="myrealm"

    In case several methods are used simultaneously to provide an access token (for example, Authorization header + POST access_token parameter), or POST parameters are duplicated:

    400 Bad Request
    WWW-Authenticate: Bearer realm="myrealm", error="invalid_request", error_description="..."

    In case of inability to resolve cryptographic keys for UserInfo response signing/encryption:

    500 Internal Server Error

    In case of a token validation error, a 401 Unauthorized is returned in combination with the invalid_token error code. This error includes user and client related checks and actually captures all the remaining error cases:

    401 Unauthorized
    WWW-Authenticate: Bearer realm="myrealm", error="invalid_token", error_description="..."

    It is now required for access tokens to have the openid scope, which is stipulated by UserInfo being a feature specific to OpenID Connect and not OAuth 2.0. If the openid scope is missing from the token, the request will be denied with a 403 Forbidden (see above).

    UserInfo now checks the user status, and returns the invalid_token response if the user is disabled.

    An alternative approach to continue using the old admin console is to set the theme for the master realm or any other realm to keycloak.

    As the new admin console is significantly different to the old admin console, is now based on React and uses a newer version of PatternFly, any custom themes will most likely have to be re-implemented from scratch. To create a custom theme for the new admin console the theme should extend keycloak.v2 instead of keycloak.

    If you have explicitly set the admin console theme to keycloak for the master realm or any other realm, it will continue to use the old admin console. To update to the new admin console you need to change the theme to keycloak.v2.

    The old admin console will be removed in Keycloak 21.

    Changes to the server configuration and startup

    Before this release, you would use the --auto-build when running the start command to tell the server to conditionally run a build if any build option has changed prior to starting the server.

    In this release, the --auto-build flag is deprecated and you no longer need to use it to indicate that you want to set build options when starting the server. Instead, the server is always going to run a build by default prior to starting the server if any build option has changed. The new behavior improves the overall experience when configuring and starting the server by making it optional, although highly recommended, to run a build command beforehand in order to achieve the best startup time and memory footprint.

    Now, in order to achieve the best startup time and memory footprint, set the --optimized option to disable the new default behavior. The --optimized flag tells the server that checking for and running a build directly as part of the startup is not needed:

    kc.sh start --optimized

    If you are already using a custom image to set build options and run an optimized Keycloak container, make sure you set the --optimized option when invoking the start command.

    For more details, please take a look at the Configuration Guide and the Containers Guide.

    Potentially breaking changes to the health endpoints

    Before Keycloak 19.0.0, the quarkus based Keycloak distribution always enabled the following non-application endpoints unintentionally:

    Starting in Keycloak 19.0.0, these endpoints are disabled and a request will result in a 404 HTTP status-code. If you are using the /q/…​ endpoints, make sure to change your probes and monitoring systems to use the intended health endpoints instead when upgrading to Keycloak 19.0.0.

    The intended health endpoints are:

    The health/live endpoint used for liveness probes is now decoupled from the database connections health, to match current good practices and to not have the same behaviour as the health/ready endpoint. As a result, the database check is not shown in the checks: array anymore when calling /health/live, so when there is a database hiccup, the liveness probe will still return HTTP status-code 200 and a status of UP, so no pod restart may be triggered.

    The health/ready endpoint used for readiness probes still checks for a working database connection. Make sure you have not only health-enabled=true but also metrics-enabled=true set in your configuration, to enable the database check, resulting in an effective readiness probe. It will return HTTP status-code 503 and a status of DOWN when the database connection is not in a healthy state.

    Changes using GELF / centralized log management

    As stated in the release notes, Keycloak now supports gelf logging for centralized logging systems out of the box.

    When you added the gelf related quarkus jars yourself in a prior version, make sure to switch to the supported configuration options in the logging guide and remove your jars from the providers folder.

    Changes affecting developers

    Keycloak undergoes large refactoring, which impacts existing code. Some of these changes require updates to existing code. These are in more detailed described below.

    Rationale for changes

    Keycloak has several limitations; for example, downtime is needed for upgrading a Keycloak cluster. To address the limitations, an in-depth refactor has been initiated.

    The changes in this version are mostly attached to storage refactoring and a preparation of a new storage, called map storage. This storage will eventually replace the current storage, which will be called a legacy store with this version. The legacy store will still be available in Keycloak for several more versions.

    The new store imposes a strict separation of responsibility between the service and storage layers. For that reason, the service layer’s visibility of an object’s origin will be restricted, so it will not be able to discriminate between cached or non-cached objects, or objects originating from local or federated storage.

    User storage SPI will become deprecated. It will be supported for several more versions, but will be eventually replaced by the Map Storage SPI, which will offer the ability to create custom storages for any recognized area, such as users, roles, clients, or groups.

    Extensions that rely on the level of detail available to services in the legacy store will need adjustment to retain this ability for the full deprecation period of the legacy store. The following section describes how that adjustment is accomplished.

    Using a legacy and map store is mutually exclusive; one store cannot be used while the other is active.

    Changes in the module structure

    As part of introducing the new storage functionality, several public APIs around storage functionality in KeycloakSession have been consolidated, and some have been deprecated and will be removed in one of the next versions. Three new modules have been introduced, and data-oriented code from server-spi, server-spi-private, and services modules have been moved there:

    org.keycloak:keycloak-model-legacy

    Contains all public facing APIs from the legacy store, such as the User Storage API.

    org.keycloak:keycloak-model-legacy-private

    Contains private implementations that relate to user storage management, such as storage *Manager classes.

    org.keycloak:keycloak-model-legacy-services

    Contains all REST endpoints that directly operate on the legacy store, and have no meaning in the new store.

    These modules will be available as long as legacy stores will be supported. After that period, they will be removed.

    This change impacts deployments of existing user storage providers in the Wildfly distribution. If your user storage provider is deployed as a WAR archive, you need to add the META-INF/jboss-deployment-structure.xml file into that archive stating the modified dependencies as shown below:

    <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
        <deployment>
            <dependencies>
                <module name="org.keycloak.keycloak-model-legacy" meta-inf="import"/>
            </dependencies>
        </deployment>
    </jboss-deployment-structure>

    KeycloakSession has been simplified. Several methods have been deprecated in KeycloakSession and will be removed in a future version.

    KeycloakSession session contains several methods for obtaining a provider for a particular object type, such as for a UserProvider there are users(), userLocalStorage(), userCache(), userStorageManager(), and userFederatedStorage(). This situation may be confusing for the developer who has to understand the exact meaning of each method, and depends on current store layout. The new store does not distinguish federated from local storage.

    For those reasons, only the users() method will be kept in KeycloakSession, and should replace all other calls listed above. The rest of the methods are deprecated, and will eventually be removed. The same pattern of deprecation applies to methods of other object areas, such as clients() or groups(). All methods ending in *StorageManager() and *LocalStorage() now throw an exception when being called, as there is no direct replacement in the new store. The next section describes how to migrate those calls to the new API or use the legacy API while using the old store.

    The deprecated methods in KeycloakSession will be removed in a future release. The keycloak-model-legacy-* modules will be available for a longer time and will eventually be removed.

    Migrating existing providers that do not depend on the legacy store

    The existing providers need no migration if they do not call a deprecated method, which should be the case for most providers.

    If the provider uses deprecated methods, but does not rely on local versus non-local storage, changing a call from the now deprecated userLocalStorage() to the method users() is the best option. Be aware that the semantics change here as the new method involves a cache if that has been enabled in the local setup.

    Before migration: accessing a deprecated API that now throws an exception
    session.userLocalStorage();
    After migration: accessing the new API caller does not depend on the legacy storage API
    session.users();
    Migrating existing providers that depend on the legacy store

    In the rare case when a custom provider needs to distinguish between the mode of a particular provider, access to the deprecated objects is provided by using the LegacyStoreManagers data store provider. This option will be available only if the legacy modules are part of the deployment.

    Before migration: accessing a deprecated API that now throws an exception
    session.userLocalStorage();
    After migration: accessing the old functionality via the LegacyStoreManagers API
    ((LegacyDatastoreProvider) session.getProvider(DatastoreProvider.class)).userLocalStorage();

    Some user storage related APIs have been wrapped in org.keycloak.storage.UserStorageUtil for convenience.

    Creating custom storage providers

    The API for creating a custom storage provider has not been fully stabilized yet, though it is available as a tech preview. See the MapStorageProvider SPI and its Javadoc for details. The availability of the new API is a priority for the next Keycloak version.

    Changes to RealmModel

    The methods getUserStorageProviders`, getUserStorageProvidersStream, getClientStorageProviders, getClientStorageProvidersStream, getRoleStorageProviders and getRoleStorageProvidersStream have been removed. Code which depends on these methods and runs with the legacy storage enabled should cast the instance as follows:

    Before migration: code will not compile due to the changed API
    realm.getClientStorageProvidersStream()...;
    After migration: cast the instance to the legacy interface
    ((LegacyRealmModel) realm).getClientStorageProvidersStream()...;

    Similarly, code that used to implement the interface RealmModel and wants to provide these methods should implement the new interface LegacyRealmModel. This interface is a sub-interface of RealmModel and includes the old methods:

    Before migration: code implements the old interface
    public class MyClass extends RealmModel {
        /* might not compile due to @Override annotations for methods no longer present
           in the interface RealmModel. /
        / ... */
    
    After migration: code implements the new interface
    public class MyClass extends LegacyRealmModel {
        /* ... */
    
    Interface UserCache moved to the legacy module

    As the caching status of objects will be transparent to services, the interface UserCache has been moved to the module keycloak-legacy. Calls to session.userCache() will therefore return only a UserProvider, which is a breaking change.

    Code that depends on the legacy implementation should access the UserCache directly. While such calls might be necessary while caching with the legacy store is used, it will not be necessary when using the new map store, as that one handles caching transparently.

    Before migration: code will not compile due to a changed return type
    // session.userCache() might return null, null-check omitted for brevity.
    session.userCache().evict(realm, user);
    After migration: use the API directly
    // session.getProvider(UserCache.class) might return null, null-check omitted for brevity.
    session.getProvider(UserCache.class).evict(realm, user);

    To trigger the invalidation of a realm, instead of using the UserCache API, consider triggering an event:

    Before migration: code will not compile due to a changed return type
    UserCache cache = session.getProvider(UserCache.class);
    if (cache != null) cache.clear();
    After migration: use the invalidation API
    session.invalidate(InvalidationHandler.ObjectType.REALM, realm.getId());
    Credential management for users

    Credentials for users were previously managed using session.userCredentialManager().method(realm, user, ...). The new way is to leverage user.credentialManager().method(...). This form gets the credential functionality closer to the API of users, and does not rely on prior knowledge of the user credential’s location in regard to realm and storage.

    The old APIs have been deprecated, and will only work when the legacy storage is enabled in the deployment. The new APIs will work with both old and new storages.

    Before migration: accessing a deprecated API
    session.userCredentialManager().createCredential(realm, user, credentialModel)
    After migration: accessing the new API
    user.credentialManager().createStoredCredential(credentialModel)

    For a custom UserStorageProvider, there is a new method credentialManager() that needs to be implemented when returning a UserModel. As those providers run in an environment with the legacy storage enabled, those must return an instance of the LegacyUserCredentialManager:

    Before migration: code will not compile due to the new method credentialManager() required by UserModel
    public class MyUserStorageProvider implements UserLookupProvider, ... {
        /* ... */
        protected UserModel createAdapter(RealmModel realm, String username) {
            return new AbstractUserAdapter(session, realm, model) {
                @Override
                public String getUsername() {
                    return username;
    
    After migration: implementation of the API UserModel.credentialManager() for the legacy store.
    public class MyUserStorageProvider implements UserLookupProvider, ... {
        /* ... */
        protected UserModel createAdapter(RealmModel realm, String username) {
            return new AbstractUserAdapter(session, realm, model) {
                @Override
                public String getUsername() {
                    return username;
                @Override
                public SubjectCredentialManager credentialManager() {
                    return new LegacyUserCredentialManager(session, realm, this);
    

    Deprecated podDisruptionBudget in the legacy Keycloak Operator

    With this release, we have deprecated podDisruptionBudget field in the Keycloak CR of the legacy Keycloak Operator. This optional field will be ignored when the Operator is deployed on Kubernetes version 1.25 and higher.

    As a workaround, you can manually create the Pod Disruption Budget in your cluster, for example:

    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      labels:
        app: keycloak
      name: keycloak
    spec:
      maxUnavailable: 1
      selector:
        matchLabels:
          component: keycloak

    See also the Kubernetes Documentation.

    Deployment changes in the new Keycloak Operator

    The new Keycloak Operator now uses StatefulSet instead of Deployment for Keycloak deployments. There’s no automated migration in place given the Operator is a tech preview in this release. If you are using the new Operator with 18.0.z, please make sure to back up, delete and recreate your Keycloak CR after the upgrade to 19.0.0.

    Step-up authentication is a new feature. This feature provides the acr client scope, which contains a protocol mapper that is supposed to add the acr claim in the token. The acr claim is not added automatically now as it was before this version, but it is added with the usage of this client scope and protocol mapper.

    The client scope is added as a realm "default" client scope and hence will be added to all newly created clients. For performance reasons, the client scope is not automatically added to all existing clients during migration. The clients will not have an acr claim by default after the migration. Consider these possible actions:

    If you do not plan to use step-up authentication feature, but you rely on the acr claim in the token, you can disable step_up_authentication feature. The claim will be added with the value 1 in case of normal authentication and 0 in case of SSO authentication.

    Add acr client scope to your clients manually by admin REST API or admin console. This is needed especially if you want to use step-up authentication. If you have a large number of clients in the realm and want to use acr claim for all of them, you can trigger some SQL similar to this against your DB. However, remember to clear the cache or restart the server if Keycloak is already started:

    insert into CLIENT_SCOPE_CLIENT (CLIENT_ID, SCOPE_ID, DEFAULT_SCOPE) select CLIENT.ID as CLIENT_ID, CLIENT_SCOPE.ID as SCOPE_ID, true as DEFAULT_SCOPE
    from CLIENT_SCOPE, CLIENT where CLIENT_SCOPE.REALM_ID='test' and CLIENT_SCOPE.NAME='acr' and CLIENT.REALM_ID='test' and CLIENT.PROTOCOL='openid-connect';

    OpenID Connect Logout

    Previous versions of Keycloak had supported automatic logout of the user and redirecting to the application by opening logout endpoint URL such as http(s)://example-host/auth/realms/my-realm-name/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri. While that implementation was easy to use, it had potentially negative impact on performance and security. The new version has better support for logout based on the OpenID Connect RP-Initiated Logout specification. The parameter redirect_uri is no longer supported; also, in the new version, the user needs to confirm the logout. It is possible to omit the confirmation and do automatic redirect to the application when you include parameter post_logout_redirect_uri together with the parameter id_token_hint with the ID Token used for login.

    The existing deployments are affected in the following ways:

    If your application directly uses links to logout endpoint with the redirect_uri parameter, you may be required to change this as described above. Consider either removing the redirect_uri parameter entirely or replacing it with the id_token_hint and post_logout_redirect_uri parameters.

    If you use java adapters and your application does logout by call httpServletRequest.logout(), you are not affected because this call uses the backchannel variant of the logout endpoint and that one was not changed.

    If you use the latest javascript adapter, you are also not affected. However if your application uses an older version of the JavaScript adapter, you are affected as this adapter uses the variant of the logout endpoint with the deprecated redirect_uri parameter. In this case, you may need to upgrade to the latest version of the JavaScript adapter.

    For the Node.js adapter, the same guideline applies as for the JavaScript adapter. You are encouraged to update to the latest version as the older version of the adapter uses the deprecated redirect_uri parameter. With the latest Node.js adapter, you are not affected as long as you use the logout based on the /logout URL as described in the documentation or in the Node.js adapter example. However, in the case when your application directly uses the method keycloak.logoutUrl, you can consider adding idTokenHint as the second argument to this method. The possibility to add idTokenHint as second argument was newly added in this version. The idTokenHint needs to be a valid ID Token that was obtained during the login. Adding idTokenHint is optional, but if you omit it, your users will need to confirm the logout screen as described earlier. Also they will not be redirected back to the application after logout.

    There is a backwards compatibility option, which allows your application to still use the old format of the redirect_uri parameter.

    You can enable this parameter when you start the server by entering the following command:

    bin/kc.[sh|bat] --spi-login-protocol-openid-connect-legacy-logout-redirect-uri=true start

    With this configuration, you can still use the format with the redirect_uri parameter. Note the confirmation screen will be needed if the id_token_hint is omitted.

    The backwards compatibility switch will be removed in some future version - probably Keycloak 23. You are encouraged to update your clients as soon as possible as described above rather than rely on this switch.

    Removal of the upload-scripts feature

    Previous versions of Keycloak had supported managing JavaScript code through the management interfaces like the administrations console and REST API. Starting from this version this is no longer possible, and you should now deploy your scripts to the server in order to configure the following providers:

    More details about how to deploy scripts to the server are available in the documentation. Note that to use scripts, you are still required to enable the scripts technology preview feature.

    kc.[sh|bat] start --auto-build --features=preview

    When deploying scripts, the server is going to automatically create their corresponding providers so that you can select them when configuring authentication flows, mappers, and authorization policies.

    In general, the steps to update your realms are the following:

    Account console Patternfly upgrade

    The Patternfly (PF) React libraries have been updated, @patternfly/react-core from v3.153.3 to v4.147.0, @patternfly/react-icons from v3.15.16 to v 4.11.8, and @patternfly/react-styles from v3.7.14 to v4.11.8. Several minor UI updates were made to bring the account console into alignment with PF design standards.

    Custom developed account UIs might not be compatible with these updates due to the breaking changes in PF. Most breaking changes should be resolvable by updating props on PF components.

    Resources:

    sizing control changed from, e.g. isLarge, to use ModalVariant, e.g. variant={ModalVariant.large}

    Select

    ariaLabelTypeAhead to typeAheadAriaLabel

    isExpanded to isOpen

    ariaLabelledBy to aria-labelledby

    DataListContent

    noPadding to hasNoPadding

    Quarkus distribution: Split metrics-enabled option into health-enabled and metrics-enabled

    The metrics-enabled option now only enables the metrics for Keycloak. To enable the readiness and liveness health endpoints, there’s a new boolean option health-enabled. This allows more fine-grained usage of these options, e.g. enabling metrics but not enabling readiness/liveness probes for on-premise use cases. In order to keep the same behaviour as before when metrics-enabled=true was set, you need to additionally set health-enabled=true when building Keycloak.

    The default distribution of Keycloak is now powered by Quarkus, which brings a number of breaking changes to you configure Keycloak and deploy custom providers. For more information check out the Quarkus Migration Guide.

    The WildFly distribution of Keycloak is now deprecated, with support ending June 2022. We recommend migrating to the Quarkus distribution as soon as possible. However, if you need to remain on the legacy WildFly distribution for some time, there are some changes to consider:

    Container images for the legacy distribution tags have changed. To use the legacy distribution use the tags legacy or 17.0.0-legacy.

    Download on the website for the legacy distribution has changed to keycloak-legacy-17.0.0.[zip|tar.gz].

    Container now published to quay.io/keycloak/keycloak:latest and quay.io/keycloak/keycloak:17.0.0

    Download on website renamed to keycloak-17.0.0.[zip|tar.gz].

    conf/keycloak.properties changed to conf/keycloak.conf, which unifies configuration keys between the config file and CLI arguments.

    Clearer separation between build options and runtime configuration.

    Custom Quarkus configuration is done through conf/quarkus.properties.

    h2-mem and h2-file databases renamed to dev-mem and dev-file.

    Features are now enabled/disabled with --features and --features-disabled replacing the previous approach that had a separate config key for each feature.

    Runtime configuration can no longer be passed to kc.[sh|bat] build and is no longer persisted in the build

    Logging level and format is now configured with --log-level and --log-format, while in the past these had to be configured using unsupported Quarkus properties.

    Liquibase upgraded to version 4.6.2

    Liquibase was updated from version 3.5.5 to 4.6.2, which includes, among other things, several bug fixes, and a new way of registering custom extensions using ServiceLoader.

    Migration from previous Keycloak versions to Keycloak 17.0.0 has been extensively tested with all currently supported databases, but we would like to stress the importance of closely following the Upgrading Guide, specifically of backing up existing database before upgrade. While we did our best to test the consequences of the Liquibase upgrade, some installations could be using specific setup unknown to us.

    WildFly 25 deprecates the legacy security subsystem that among other things was used to configure TLS. Due to the amount of changes we are not able to provide migration scripts as we have done in the past.

    We recommend that rather than copying configuration files from previous versions of Keycloak that you start with the default configuration files provided in Keycloak 16 and apply the relevant changes.

    Configuration for the Keycloak subsystem can be copied directly.

    For more information around the Elytron subsystem refer to the WildFly documentation.

    We are really sorry for this inconvenience and understand this will make it significantly harder for everyone to upgrade to Keycloak 16, but we simply have not been able to find an alternative approach.

    One thing worth pointing out is the switch to Quarkus distribution, which we plan to make fully supported in Keycloak 17, will make it significantly easier to configure and upgrade Keycloak.

    For more information on WildFly 25 refer to the WildFly 25 release notes.

    Proxy environment variables

    Keycloak now respects the standard HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables for outgoing HTTP requests. This change could lead to unexpected use of a proxy server if you have for example the HTTP_PROXY variable defined but have no explicit proxy mappings specified in your SPI configuration. To prevent Keycloak from using those environment variables, you can explicitly create a no proxy route for all requests as .*;NO_PROXY.

    Deprecated features in the Keycloak Operator

    With this release, we have deprecated and/or marked as unsupported some features in the Keycloak Operator. This concerns the Backup CRD and the operator managed Postgres Database.

    Keycloak Operator examples including unsupported Metrics extension

    Previously, an unsupported metrics extension was added in the example for the creation of the Keycloak CR by the Keycloak Operator. This has been removed.

    Client policies migration

    The Client policies feature was a preview feature since Keycloak 12 and did not have proper support. If you tried this feature and configured some client policies or client profiles in Keycloak 12 or Keycloak 13, then you will need to configure your client policies and client profiles again in the new version. The format of the configuration changed significantly as it was only a preview and hence we do not provide automatic migration of client policies and client profiles created in Keycloak 12 or Keycloak 13.

    Manual migration step needed

    Manual change is required when the standalone.xml contains references to any of the SmallRye modules. SmallRye modules were removed from the underlying WildFly distribution, and the server does not start if the configuration references them. Thus if the configuration in the standalone.xml refers to these modules, the server configuration migration via migrate-standalone.cli fails before any changes are made to the configuration. In such case, to perform server configuration migration, you have to manually remove all the lines that refer to SmallRye modules. In the default configuration, you need to remove specifically the following lines:

    <extension module="org.wildfly.extension.microprofile.config-smallrye"/>
    <extension module="org.wildfly.extension.microprofile.health-smallrye"/>
    <extension module="org.wildfly.extension.microprofile.metrics-smallrye"/>
    <subsystem xmlns="urn:wildfly:microprofile-config-smallrye:1.0"/>
    <subsystem xmlns="urn:wildfly:microprofile-health-smallrye:2.0" security-enabled="false" empty-liveness-checks-status="${env.MP_HEALTH_EMPTY_LIVENESS_CHECKS_STATUS:UP}" empty-readiness-checks-status="${env.MP_HEALTH_EMPTY_READINESS_CHECKS_STATUS:UP}"/>
    <subsystem xmlns="urn:wildfly:microprofile-metrics-smallrye:2.0" security-enabled="false" exposed-subsystems="*" prefix="${wildfly.metrics.prefix:wildfly}"/>

    Upgrade to Wildfly 23

    The Keycloak server was upgraded to use Wildfly 23 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 23 server. For example, Infinispan is now 11.0.9.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically. However, here are the most important changes, which you may need if you made your own configuration changes:

    The module attribute of Infinispan cache containers is now deprecated (unused) and is replaced with the modules attribute, representing the set of modules associated with this cache container’s configuration. Moreover, there were also additional changes to attributes of various elements, originating from the use of Wildfly 23 as the underlying container. For example, the managed-executor-service and managed-scheduled-executor-service elements now recognize the new hung-task-termination-period attribute. See the Wildfly 23 full model reference for details.

    Upgrade to Wildfly 22

    The Keycloak server was upgraded to use Wildfly 22 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 22 server. For example, Infinispan is now 11.0.8.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically. However, here are the most important changes, which you may need if you made your own configuration changes:

    The Eclipse MicroProfile Config, Eclipse MicroProfile Health, and Eclipse MicroProfile Metrics subsystems are replaced with WildFly subsystem for health and WildFly subsystem for base metrics.

    The default Wildfly configuration now uses the ability to make use of an automatically generated self-signed certificate with Elytron. Refer to a dedicated applicationSSC server SSL context section for details.

    Read-only attributes

    There was added support for the read-only user attributes. This includes the user attributes, which are not supposed to be edited by the user or by the administrator when updating user with REST API or with the Keycloak user interfaces. It can be important especially if you

    Custom JavaScript authorization policies, which establish authorization based on some user attribute

    X.509 authenticator with custom attribute for mapping the X.509 certificate to the user identity

    Any other custom functionality, where some of the user attributes are used as the metadata for storing authentication/authorization/identity context rather than simple user profile information.

    Valid Request URIs

    If you use the OpenID Connect parameter request_uri, a requirement exists that your client needs to have Valid Request URIs configured. This can be configured through the admin console on the client details page or through the admin REST API or client registration API. Valid Request URIs need to contain the list of Request URI values, which are permitted for the particular client. This is to avoid SSRF attacks. There is possibility to use wildcards or relative paths similarly such as the Valid Redirect URIs option, however for security purposes, we typically recommend to use as specific value as possible.

    Upgrade to Wildfly 22

    The Keycloak server was upgraded to use Wildfly 22 as the underlying container. This does not directly involve any specific Keycloak server functionality, but a few changes related to the migration, which are worth mentioning.

    Dependency updates

    The dependencies were updated to the versions used by Wildfly 22 server. For example, Infinispan is now 11.0.8.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically. If more detail is needed, because, for example, you did some configuration changes on your own, the list of the most important changes follows:

    The Eclipse MicroProfile Config, Eclipse MicroProfile Health, and Eclipse MicroProfile Metrics subsystems were replaced by WildFly subsystem for health and WildFly subsystem for base metrics.

    The default Wildfly configuration now utilizes the ability to make use of an automatically generated self-signed certificate with Elytron. Refer to a dedicated applicationSSC server SSL context section for details.

    Upgrade to Wildfly 21

    The Keycloak server was upgraded to use Wildfly 21 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 21 server. For example, Infinispan is now 11.0.4.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically. However, here are the most important changes, which you may need if you made your own configuration changes:

    The object-memory element of Infinispan caches is now deprecated (unused) and is replaced with the heap-memory element.

    Upgrade to PatternFly 4

    The Keycloak login theme components have been upgraded to PatternFly 4. The old PatternFly 3 runs simultaneously with the new one, so it’s possible to keep PF3 components. However, some changes to the design of the login theme were performed. Please upgrade your custom login theme due them. An example with the necessary changes can be found in the keycloak/examples/themes/theme/sunrise directory. No additional setup is required.

    Client Credentials Grant without refresh token by default

    From this Keycloak version, the OAuth2 Client Credentials Grant endpoint does not issue refresh tokens by default. This behavior is aligned with the OAuth2 specification. As a side effect of this change, no user session is created on the Keycloak server side after successful Client Credentials authentication, which results in improved performance and memory consumption. Clients that use Client Credentials Grant are encouraged to stop using refresh tokens and instead always authenticate at every request with grant_type=client_credentials instead of using refresh_token as grant type. In relation to this, Keycloak has support for revocation of access tokens in the OAuth2 Revocation Endpoint, hence clients are allowed to revoke individual access tokens if needed.

    For backwards compatibility, a possibility to stick to the behavior of old versions exists. When this is used, the refresh token will be still issued after a successful authentication with the Client Credentials Grant and also the user session will be created. This can be enabled for the particular client in the Keycloak admin console, in client details in the section with OpenID Connect Compatibility Modes with the switch Use Refresh Tokens For Client Credentials Grant.

    Upgrade to Wildfly 20

    The Keycloak server was upgraded to use Wildfly 20 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 20 server. For example, Infinispan is now 10.1.8.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically.

    Cross-Datacenter Replication changes

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as they are not tested anymore.

    It is recommended to use the protocolVersion property added to the remote-store element when configuring Infinispan caches. When connecting to the Infinispan server 9.4.18, the recommended version of the hotrod protocol version is 2.9 as the Infinispan library version differs among Keycloak server and Infinispan server. For more details, see the Cross-Datacenter documentation.

    It is recommended to use remoteStoreSecurityEnabled property under connectionsInfinispan subsystem. For more details, see the Cross-Datacenter documentation.

    LDAP no-import bugfix

    In the previous Keycloak version, when the LDAP provider was configured with Import Users OFF, it was possible to update the user even if some of non-LDAP mapped attributes were changed. This situation resulted in confusing behavior, when the attribute appeared to be updated, but it was not. In the current version, the update is not allowed to be performed at all if any non-LDAP mapped attributes are changed.

    This should not affect most of the deployments, but some can be affected under some rare circumstances. For example if you previously tried to update a user with the admin REST API and the user had some incorrect attribute changes, the update was possible. With the current version, the update is not possible and you will be immediately informed about the reason.

    UserModel changes

    The fields username, email, firstName and lastName in the UserModel are migrated to custom attributes as a preparation for adding more sophisticated user profiles to Keycloak in an upcoming version. If a database contains users with custom attributes of that exact name, the custom attributes will need to be migrated before upgrading. This migration does not occur automatically. Otherwise, they will not be read from the database anymore and possibly deleted. This situation implies that the username can now also be accessed and set via UserModel.getFirstAttribute(UserModel.USERNAME). Similar implications exist for other fields. Implementors of SPIs subclassing the UserModel directly or indirectly should ensure that the behavior between setUsername and setSingleAttribute(UserModel.USERNAME, …​) (and similar for the other fields) is consistent. Users of the policy evaluation feature have to adapt their policies if they use the number of attributes in their evaluations since every user will now have four new attributes by default.

    The public API of UserModel did not change. No changes to frontend resources or SPIs accessing user data are necessary. Also, the database did not change yet.

    Instagram IdP migrated to new the API

    Instagram IdP now uses new API as the old legacy API was deprecated. This requires getting new API credentials. For details, please refer to the Server Administration Guide.

    Special attention is required for existing users that use Instagram IdP, specially the ones for whom it is the only authentication option. Such users have to log in to Keycloak using Instagram IdP before September 30th, 2020. After that day they’ll have to use a different authentication method (like password) to log in to manually update their Instagram social link, or create a new account in Keycloak. This is because Instagram user IDs are not compatible between the old and new API, however the new API temporarily returns both new and old user IDs to allow migration. Keycloak automatically migrates the ID once user logs in.

    Non-standard token introspection endpoint removed

    In previous versions, Keycloak advertised two introspection endpoints: token_introspection_endpoint and introspection_endpoint. The latter is the one defined by RFC-8414. The former, previously deprecated, has now been removed.

    Legacy promise in JavaScript adapter

    It is no longer necessary to set promiseType in the JavaScript adapter, and both are available at the same time. It is recommended to update applications to use native promise API (then and catch) as soon as possible, as the legacy API (success and error) will be removed at some point.

    Duplicated top level groups

    Version 9.0.1 fixes a problem which could create duplicated top level groups in the realm. Nevertheless the existence of previous duplicated groups makes the upgrade process fail. The Keycloak server can be affected by this issue if it is using an H2, MariaDB, MySQL or PostgreSQL database. Before launching the upgrade, check if the server contains duplicated top level groups. For example the following SQL query can be executed at database level to list them:

    SELECT REALM_ID, NAME, COUNT(*) FROM KEYCLOAK_GROUP WHERE PARENT_GROUP is NULL GROUP BY REALM_ID, NAME HAVING COUNT(*) > 1;

    Only one top level group can exist in each realm with the same name. Duplicates should be reviewed and deleted before the upgrade. The error in the upgrade contains the message Change Set META-INF/jpa-changelog-9.0.1.xml::9.0.1- KEYCLOAK-12579-add-not-null-constraint::keycloak failed.

    Improved handling of user locale

    A number of improvements have been made to how the locale for the login page is selected, as well as when the locale is updated for a user.

    See the Server Administration Guide for more details.

    Deprecated methods in token representation Java classes

    In the year 2038 an int is no longer able to hold the value of seconds since 1970, as such we are working on updating these to long values. Moreover, another issue related with processing of int values exists in token representation. An int will by default result into 0 in the JSON representation, while it should not be included.

    See JavaDocs for further details on exact methods that have been deprecated and replacement methods.

    REQUIRED and ALTERNATIVE executions not supported at same flow

    In previous version, it was possible to have REQUIRED and ALTERNATIVE executions in the same authentication flow at the same level. There were some issues with this approach and we did the refactoring in the Authentication SPI, which means that this is not considered valid anymore. If ALTERNATIVE and REQUIRED executions are configured at the same level, the ALTERNATIVE executions are considered disabled. So when migrating to the newest version, your existing authentication flows will be automatically migrated preserved the same behavior as existed in the previous version. If they contain ALTERNATIVE executions at the same level as some REQUIRED executions, then the ALTERNATIVE executions will be added to the separate REQUIRED subflow. This should ensure same/similar behavior of the particular authentication flow as in the previous version. We always recommend to double-check the configuration of your authentication flow and test it to double-check that everything works as expected. This recommendation is true in particular if you have some more customized authentication flows with custom authenticator implementations.

    New default Hostname provider

    The old request and fixed hostname providers are replaced with a new default hostname provider. The request and fixed hostname providers are now deprecated and it is recommended to switch to the default hostname provider as soon as possible.

    Upgrade to Wildfly 18

    The Keycloak server was upgraded to use Wildfly 18 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 18 server. For example, Infinispan is now 9.4.16.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically.

    Cross-Datacenter Replication changes

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as we don’t test it anymore.

    Deploying scripts to the server

    Until now, administrators were allowed to upload scripts to the server through the Keycloak Administration Console as well as through the RESTful Admin API.

    For now on, this capability is disabled by default and users should prefer to deploy scripts directly to the server. For more details, please take a look at JavaScript Providers.

    Client credentials in the JavaScript adapter

    In the previous releases, developers were allowed to provide client credentials to the JavaScript adapter. For now on, this capability was removed, because client-side apps are not safe to keep secrets.

    Authentication flows changes

    We did some refactoring and improvements related to the authentication flows, which requires some attention during migration.

    OPTIONAL execution requirement removed

    Regarding migration, the most important change is removing the support for the OPTIONAL requirement from authentication executions and replacing it with the CONDITIONAL requirement, which allows more flexibility. The existing OPTIONAL authenticators configured in the previous version are replaced with the CONDITIONAL subflows. These subflows have the Condition - User Configured condition configured as first execution, and the previously OPTIONAL authenticator (for example OTP Form) as second execution. From the user’s point of view, the behavior during authentication is the same as in the previous version.

    Changes in the Java SPI

    Some changes exist in the Java Authentication SPI and Credential Provider SPI. The interface Authenticator is not changed, but you may be affected if you’re developing more advanced authenticators, which introduce some new credential types (subclasses of CredentialModel). There are changes on the CredentialProvider interface and introduction of some new interfaces like CredentialValidator. Also you may be affected if your authenticator supported the OPTIONAL execution requirement. It is recommended to double-check the latest authentication examples in the server development guide for more details.

    Freemarker template changes

    Some changes in the freemarker templates exist. You may be affected if you have your own theme with custom freemarker templates for login forms or some account forms, especially for the forms related to OTP. It is recommended to double-check changes in the Freemarker templates in the latest Keycloak and align your templates according to it.

    User credentials changes

    We added more flexibility around storing of user credentials. Among other things, every user can have multiple credentials of the same type, for example multiple OTP credentials. As a result, some changes to the database schema were performed. However the credentials from the previous version should be automatically updated to the new format and users should be still able to login with their passwords or OTP credentials set in the previous version.

    Upgrade to Wildfly 17

    The Keycloak server was upgraded to use Wildfly 17 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 17 server. For example, Infinispan is now 9.4.14.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically.

    Cross-Datacenter Replication changes

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as we don’t test it anymore.

    Upgrade to Wildfly 16

    The Keycloak server was upgraded to use Wildfly 16 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 16 server. For example, Infinispan is now 9.4.8.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically.

    Cross-Datacenter Replication changes

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as we don’t test it anymore.

    New optional client scope

    We have added a new microprofile-jwt optional client scope to handle the claims defined in the MicroProfile/JWT Auth Specification. This new client scope defines protocol mappers to set the username of the authenticated user to the upn claim and to set the realm roles to the groups claim.

    Ability to propagate prompt=none to default IDP

    We have added a new switch in the OIDC identity provider configuration named Accepts prompt=none forward from client to identify IDPs that are able to handle forwarded requests that include the prompt=none query parameter.

    Until now, when receiving an auth request with prompt=none a realm would return a login_required error if the user is not authenticated in the realm without checking if the user has been authenticated by an IDP. From now on, if a default IDP can be determined for the auth request (either by the use of the kc_idp_hint query param or by setting up a default IDP for the realm) and if the Accepts prompt=none forward from client switch has been enabled for the IDP, the auth request is forwarded to the IDP to check if the user has been authenticated there.

    It is important to note that this switch is only taken into account if a default IDP is specified, in which case we know where to forward the auth request without having to prompt the user to select an IDP. If a default IDP cannot be determined we cannot assume which one will be used to fulfill the auth request so the request forwarding is not performed.

    Upgrade to Wildfly 15

    The Keycloak server was upgraded to use Wildfly 15 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 15 server. For example, Infinispan is now 9.4.3.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically.

    Cross-Datacenter Replication changes

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as we don’t test it anymore.

    Migrating to 4.8.2

    Google Identity Provider updated to use Google Sign-in authentication system

    The Google Identity Provider implementation in Keycloak up to version 4.8.1 relies on the Google+ API endpoints for authorization and obtaining the user profile. From March 2019 onwards, Google is removing support for the Google+ API in favor of the new Google Sign-in authentication system. The Keycloak identity provider has been updated to use the new endpoints so if this integration is in use make sure you upgrade to Keycloak version 4.8.2 or later.

    If you run into an error saying that the application identifier was not found in the directory, you will have to register the client application again in the Google API Console portal to obtain a new application id and secret.

    It is possible that you will need to adjust custom mappers for non-standard claims that were provided by Google+ user information endpoint and are provided under different name by Google Sign-in API. Please consult Google documentation for the most up-to-date information on available claims.

    LinkedIn social broker updated to Version 2 of LinkedIn APIs

    Accordingly with LinkedIn, all developers need to migrate to version 2.0 of their APIs and OAuth 2.0. As such, we have updated our LinkedIn Social Broker.

    Existing deployments using this broker may start experiencing errors when fetching user’s profile using version 2 of LinkedIn APIs. This error may be related with the lack of permissions granted to the client application used to configure the broker which may not be authorized to access the Profile API or request specific OAuth2 scopes during the authentication process.

    Even for newly created LinkedIn client applications, you need to make sure that the client is able to request the r_liteprofile and r_emailaddress OAuth2 scopes, at least, as well that the client application can fetch current member’s profile from the https://api.linkedin.com/v2/me endpoint.

    Due to these privacy restrictions imposed by LinkedIn in regards to access to member’s information and the limited set of claims returned by the current member’s Profile API, the LinkedIn Social Broker is now using the member’s email address as the default username. That means that the r_emailaddress is always set when sending authorization requests during the authentication.

    New default client scopes

    We have added new realm default client scopes roles and web-origins. These client scopes contain protocol mappers to add the roles of the user and allowed web origins to the token. During migration, these client scopes should be automatically added to all the OpenID Connect clients as default client scopes. Hence no setup should be required after database migration is finished.

    Protocol mapper SPI addition

    Related to this, a small addition to the (unsupported) Protocol Mappers SPI exists. You can be affected only if you implemented a custom ProtocolMapper. A new getPriority() method on the ProtocolMapper interface got introduced. The method has the default implementation set to return 0. If your protocol mapper implementation relies on the roles in the access token realmAccess or resourceAccess properties, you may need to increase the priority of your mapper.

    Audience resolving

    Audiences of all the clients, for which authenticated user has at least one client role in the token, are automatically added to the aud claim in the access token now. On the other hand, an access token may not automatically contain the audience of the frontend client, for which it was issued. Read the Server Administration Guide for more details.

    JavaScript adapter promise

    To use native JavaScript promise with the JavaScript adapter it is now required to set promiseType to native in the init options.

    In the past if native promise was available a wrapper was returned that provided both the legacy Keycloak promise and the native promise. This was causing issues as the error handler was not always set prior to the native error event, which resulted in Uncaught (in promise) error.

    Microsoft Identity Provider updated to use the Microsoft Graph API

    The Microsoft Identity Provider implementation in Keycloak up to version 4.5.0 relies on the Live SDK endpoints for authorization and obtaining the user profile. From November 2018 onwards, Microsoft is removing support for the Live SDK API in favor of the new Microsoft Graph API. The Keycloak identity provider has been updated to use the new endpoints so if this integration is in use make sure you upgrade to Keycloak version 4.6.0 or later.

    Legacy client applications registered under "Live SDK applications" won’t work with the Microsoft Graph endpoints due to changes in the id format of the applications. If you run into an error saying that the application identifier was not found in the directory, you will have to register the client application again in the Microsoft Application Registration portal to obtain a new application id.

    Upgrade to Wildfly 14

    The Keycloak server was upgraded to use Wildfly 14 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 14 server. For example, Infinispan is now 9.3.1.Final.

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically.

    Cross-Datacenter Replication changes

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as we don’t test it anymore.

    Upgrade to Wildfly 13

    The Keycloak server was upgraded to use Wildfly 13 as the underlying container. This does not directly involve any specific Keycloak server functionality, however, note these changes related to migration:

    Dependency updates

    The dependencies were updated to the versions used by the Wildfly 13 server. For example, Infinispan is now 9.2.4.Final and Undertow is 2.0.9.Final

    Configuration changes

    A few configuration changes exist in the standalone(-ha).xml and domain.xml files. You should follow the Downloading the Keycloak server section to handle the migration of configuration files automatically. However, here are the most important changes, which you may need if you made your own configuration changes:

    Element eviction on infinispan caches is now deprecated (unused) and is replaced with element object-memory

    The cache-container element in Infinispan subsystem does not recognize the jndi-attribute anymore.

    You will need to upgrade Infinispan server to version 9.4.19. The older version may still work, but it is not guaranteed as we don’t test it anymore.

    You don’t need to configure security anymore in the Infinispan server configuration file.

    The transaction element needs to be removed from the configuration of replicated caches in the Infinispan server configuration file. This is needed because of the infinispan bug https://issues.redhat.com/browse/ISPN-9323.

    Hostname configuration

    In previous versions it was recommended to use a filter to specify permitted hostnames. It is now possible to set a fixed hostname which makes it easier to make sure the valid hostname is used and also allows internal applications to invoke Keycloak through an alternative URL, for example an internal IP address. It is recommended that you switch to this approach in production.

    Client Templates changed to Client Scopes

    Client Templates were changed to Client Scopes. If you had any Client Templates, their protocol mappers and role scope mappings will be preserved.

    Spaces replaced in the names

    Client templates with the space character in the name were renamed by replacing spaces with an underscore, because spaces are not allowed in the name of client scopes. For example, a client template my template will be changed to client scope my_template.

    Linking Client Scopes to Clients

    For clients which had the client template, the corresponding client scope is now added as Default Client Scope to the client. So protocol mappers and role scope mappings will be preserved on the client.

    Realm Default Client Scopes not linked with existing clients

    During the migration, the list of built-in client scopes is added to each realm as well as list of Realm Default Client Scopes. However, existing clients are NOT upgraded and new client scopes are NOT automatically added to them. Also all the protocol mappers and role scope mappings are kept on existing clients. In the new version, when you create a new client, it automatically has Realm Default Client Scopes attached to it and it does not have any protocol mappers attached to it. We did not change existing clients during migration as it would be impossible to properly detect customizations, which you will have for protocol mappers of the clients, for example. If you want to update existing clients (remove protocol mappers from them and link them with client scopes), you will need to do it manually.

    Consents need to be confirmed again

    The client scopes change required the refactoring of consents. Consents now point to client scopes, not to roles or protocol mappers. Because of this change, the previously confirmed persistent consents by users are not valid anymore and users need to confirm the consent page again after the migration.

    Some configuration switches removed

    The switch Scope Param Required was removed from Role Detail. The switches Consent Required and Consent Text were removed from the Protocol Mapper details. Those switches are replaced with the Client Scope feature.

    Changes to Authorization Services

    We added support for UMA 2.0. This version of the UMA specification introduced some important changes on how permissions are obtained from the server.

    Here are the main changes introduced by UMA 2.0 support. See Authorization Services Guide for details.

    Authorization API was removed

    Prior to UMA 2.0 (UMA 1.0), client applications were using the Authorization API to obtain permissions from the server in the format of an RPT. The new version of UMA specification has removed the Authorization API which was also removed from Keycloak. In UMA 2.0, RPTs can now be obtained from the token endpoint by using a specific grant type. See Authorization Services Guide for details.

    Entitlement API was removed

    With the introduction of UMA 2.0, we decided to leverage the token endpoint and UMA grant type to allow obtaining RPTs from Keycloak and avoid having different APIs. The functionality provided by the Entitlement API was kept the same and is still possible to obtain permissions for a set of one or more resources and scopes or all permissions from the server in case no resource or scope is provided. See Authorization Services Guide for details.

    Changes to UMA Discovery Endpoint

    UMA Discovery document changed, see Authorization Services Guide for details.

    Changes to Keycloak Authorization JavaScript adapter

    The Keycloak Authorization JavaScript adapter (keycloak-authz.js) changed in order to comply with the changes introduced by UMA 2.0 while keeping the same behavior as before. The main change is on how you invoke both authorization and entitlement methods which now expect a specific object type representing an authorization request. This new object type provides more flexibility on how permissions can be obtained from the server by supporting the different parameters supported by the UMA grant type. See Authorization Services Guide for details.

    One of the main changes introduced by this release is that you are no longer required to exchange access tokens with RPTs in
    order to access resources protected by a resource server (when not using UMA). Depending on how the policy enforcer is configured on the resource server side, you can just send regular
    access tokens as a bearer token and permissions will still be enforced.
    Changes to Keycloak Authorization Client Java API

    When upgrading to the new version of Keycloak Authorization Client Java API, you’ll notice that some representation classes were moved to a different package in org.keycloak:keycloak-core.

    Migrating to 3.4.2

    Added session_state parameter to OpenID Connect Authentication Response

    The OpenID Connect Session Management specification requires that the parameter session_state is present in the OpenID Connect Authentication Response.

    In past releases, we did not have this parameter, but now Keycloak adds this parameter by default, as required by the specification.

    However, some OpenID Connect / OAuth2 adapters, and especially older Keycloak adapters, may have issues with this new parameter.

    For example, the parameter will be always present in the browser URL after successful authentication to the client application. In these cases, it may be useful to disable adding the session_state parameter to the authentication response. This can be done for the particular client in the Keycloak admin console, in client details in the section with OpenID Connect Compatibility Modes, described in Compatibility with older adapters. Dedicated Exclude Session State From Authentication Response switch exists, which can be turned on to prevent adding the session_state parameter to the Authentication Response.

    The parameter session_state was added in 3.4.2, however the switch Exclude Session State From Authentication Response was added in 4.0.0.Beta1. If your Keycloak server is on 3.4.2 or 3.4.3 and you have issues with session_state parameter, you will need to upgrade the server to 4.0.0.Beta1 or newer.

    New password hashing algorithms

    We’ve added two new password hashing algorithms (pbkdf2-sha256 and pbkdf2-sha512). New realms will use the pbkdf2-sha256 hashing algorithm with 27500 hashing iterations. Since pbkdf2-sha256 is slightly faster than pbkdf2 the iterations was increased to 27500 from 20000.

    Existing realms are upgraded if the password policy contains the default value for hashing algorithm (not specified) and iteration (20000). If you have changed the hashing iterations you need to manually change to pbkdf2-sha256 if you’d like to use the more secure hashing algorithm.

    ID Token requires scope=openid

    OpenID Connect specification requires that parameter scope with value openid is used in initial authorization request. So in Keycloak 2.1.0 we changed our adapters to use scope=openid in the redirect URI to Keycloak. Now we changed the server part too and ID token will be sent to the application just if scope=openid is really used. If it’s not used, then ID token will be skipped and just Access token and Refresh token will be sent to the application. This also allows that you can omit the generation of ID Token on purpose - for example for space or performance purposes.

    Direct grants (OAuth2 Resource Owner Password Credentials Grant) and Service accounts login (OAuth2 Client credentials grant) also don’t use ID Token by default now. You need to explicitly add scope=openid parameter to have ID Token included.

    Authentication sessions and Action tokens

    We are working on support for multiple datacenters. As the initial step, we introduced authentication session and action tokens. Authentication session replaces Client session, which was used in previous versions. Action tokens are currently used especially for the scenarios, where the authenticator or requiredActionProvider requires sending email to the user and requires user to click on the link in email.

    Here are concrete changes related to this, which may affect you for the migration.

    First change related to this is introducing new Infinispan caches authenticationSessions and actionTokens in standalone.xml or standalone-ha.xml. If you use our migration CLI, you don’t need to care much as your standalone(-ha).xml files will be migrated automatically.

    Second change is changing of some signatures in methods of authentication SPI. This may affect you if you use custom Authenticator or RequiredActionProvider. Classes AuthenticationFlowContext and RequiredActionContext now allow to retrieve authentication session instead of client session.

    We also added some initial support for sticky sessions. You may want to change your load balancer/proxy server and configure it if you don’t want to suffer from it and want to have better performance. The route is added to the new AUTH_SESSION_ID cookie. More info in the clustering documentation.

    Another change is, that token.getClientSession() was removed. This may affect you for example if you’re using Client Initiated Identity Broker Linking feature.

    The ScriptBasedAuthenticator changed the binding name from clientSession to authenticationSession, so you would need to update your scripts if you’re using this authenticator.

    Finally we added some new timeouts to the admin console. This allows you for example to specify different timeouts for the email actions triggered by admin and by user himself.

    Migration of old offline tokens

    If you migrate from version 2.2.0 or older and you used offline tokens, then your offline tokens didn’t have KID in the token header. We added KID to the token header in 2.3.0 together with the ability to have multiple realm keys, so Keycloak is able to find the correct key based on the token KID.

    For the offline tokens without KID, Keycloak 2.5.1 will always use the active realm key to find the proper key for the token verification. In other words, migration of old offline tokens will work. So for example, your user requested offline token in 1.9.8, then you migrate from 1.9.8 to 2.5.1 and then your user will be still able to refresh his old offline token in 2.5.1 version.

    But a limitation exists. Once you change the realm active key, the users won’t be able to refresh old offline tokens anymore. So you shouldn’t change the active realm key until all your users with offline tokens refreshed their tokens. Obviously newly refreshed tokens will have KID in the header, so after all users exchange their old offline tokens, you are free to change the active realm key.

    Changes to the Infinispan caches

    The realms cache defined in the infinispan subsystem in standalone.xml or standalone-ha.xml configuration file, now has the eviction with the 10000 records by default. This is the same default as the users cache.

    Also the authorization cache now doesn’t have any eviction on it by default.

    Server SPI split into Server SPI and Sever SPI Private

    The keycloak-server-spi module has been split into keycloak-server-spi and keycloak-server-spi-private. APIs within keycloak-server-spi will not change between minor releases, while we reserve the right and may quite likely change APIs in keycloak-server-spi-private between minor releases.

    Key encryption algorithm in SAML assertions

    Key in SAML assertions and documents are now encrypted using RSA-OAEP encryption scheme. If you want to use encrypted assertions, make sure that service providers understand this encryption scheme. In the unlikely case that SP would not be able to handle the new scheme, Keycloak can be made to use legacy RSA-v1.5 encryption scheme when started with system property keycloak.saml.key_trans.rsa_v1.5 set to true.

    Infinispan caches realms and users are always local

    Even if you use Keycloak in cluster, the caches realms and users defined in infinispan subsystem in standalone-ha.xml are always local caches now. A separate cache work exists, which handles sending invalidation messages between cluster nodes and informing whole cluster what records in underlying realms and users caches should be invalidated.

    Default max results on paginated endpoints

    All Admin REST API endpoints that support pagination now have a default max results set to 100. If you want to return more than 100 entries you need to explicitly specify that with ?max=<RESULTS>.

    In 2.3.0 release we added support for Public Key Rotation. When admin rotates the realm keys in Keycloak admin console, the Client Adapter will be able to recognize it and automatically download new public key from Keycloak. However this automatic download of new keys is done just if you don’t have realm-public-key option in your adapter with the hardcoded public key. For this reason, we don’t recommend to use realm-public-key option in adapter configuration anymore.

    Note this option is still supported, but it may be useful just if you really want to have hardcoded public key in your adapter configuration and never download the public key from Keycloak. In theory, one reason for this can be to avoid man-in-the-middle attack if you have untrusted network between adapter and Keycloak, however in that case, it is much better option to use HTTPS, which will secure all the requests between adapter and Keycloak.

    Added Infinispan cache keys

    In this release, we added new cache keys to the infinispan subsystem, which is defined in standalone.xml or standalone-ha.xml configuration file. It has also some eviction and expiration defined. This cache is internally used for caching the external public keys of the entities trusted by the server (Identity providers or clients, which uses authentication with signed JWT).

    databaseSchema property deprecated

    The databaseSchema property for both JPA and Mongo is now deprecated and is replaced with initializeEmpty and migrationStrategy. initializeEmpty can bet set to true or false and controls if an empty database should be initialized. migrationStrategy can be set to update, validate and manual. manual is only supported for relational databases and will write an SQL file with the required changes to the database schema. Please note that for Oracle database, the created SQL file contains SET DEFINE OFF command understood by Oracle SQL clients. Should the script be consumed by any other client, please replace the lines with equivalent command of the tool of your choice that disables variable expansion or remove it completely if such functionality is not applicable.

    Changes in Client’s Valid Redirect URIs

    The following scenarios are affected:

    When a Valid Redirect URI with query component is saved in a Client (e.g. http://localhost/auth?foo=bar), redirect_uri in authorization request must exactly match this URI (or other registered URI in this Client).

    When a Valid Redirect URI without a query component is saved in a Client, redirect_uri must exactly match as well.

    Wildcards in registered Valid Redirect URIs are no longer supported when query component is present in this URI, so the redirect_uri needs to exactly match this saved URI as well.

    Fragments in registered Valid Redirect URIs (like http://localhost/auth#fragment) are no longer allowed.

    Upgrading from 1.0.0.Final no longer supported

    Upgrading from 1.0.0.Final is no longer supported. To upgrade to this version upgrade to 1.9.8.Final prior to upgrading to 2.0.0.

    Default password hashing interval increased to 20K

    The default password hashing interval for new realms has been increased to 20K (from 1 previously). This change will have an impact on performance when users authenticate. For example with the old default (1) it takes less than 1 ms to hash a password, but with the new default (20K) the same operation can take 50-100 ms.

    Adapter option auth-server-url-for-backend-requests removed

    We’ve removed the option auth-server-url-for-backend-requests due to issues in some scenarios when it was used. In more details, it was possible to access the Keycloak server from 2 different contexts (internal and external), which was causing issues in token validations etc.

    If you still want to use the optimization of network, which this option provided (avoid the application to send backchannel requests through load balancer but send them to local Keycloak server directly) you may need to handle it at hosts configuration (DNS) level.

    Themes and providers directory moved

    We’ve moved the themes and providers directories from standalone/configuration/themes and standalone/configuration/providers to themes and providers respectively. If you have added custom themes and providers you need to move them to the new location. You also need to update keycloak-server.json as it’s changed due to this.

    Adapter subsystems only bring in dependencies if Keycloak is on

    Previously, if you had installed our SAML or OIDC Keycloak subsystem adapters into WildFly or JBoss EAP, we would automatically include Keycloak client jars into EVERY application irregardless if you were using Keycloak or not. These libraries are now only added to your deployment if you have Keycloak authentication turned on for that adapter (via the subsystem, or auth-method in web.xml)

    Client Registration service endpoints moved

    The Client Registration service endpoints have been moved from {realm-name}/clients to {realm-name}/clients-registrations.

    Session state parameter in authentication response renamed

    In the OpenID Connect authentication response we used to return the session state as session-state this is not correct according to the specification and has been renamed to session_state.

    Deprecated OpenID Connect endpoints

    In 1.2 we deprecated a number of endpoints that where not consistent with the OpenID Connect specifications, these have now been removed. This also applies to the validate token endpoint that is replaced with the new introspect endpoint in 1.8.

    Updates to theme templates

    Feedback in template.ftl has been moved and format has changed slightly.

    Module and source code reorganization

    Most of our modules and source code have been consolidated into two maven modules: keycloak-server-spi and keycloak-services. SPI interfaces are in server-spi, implementations are in keycloak-services. All JPA dependent modules have been consolidated under keycloak-model-jpa. Same goes with mongo and Infinispan under modules keycloak-model-mongo and keycloak-model-infinispan.

    For adapters, session id changed after login

    To plug a security attack vector, for platforms that support it (Tomcat 8, Undertow/WildFly), the Keycloak OIDC and SAML adapters will change the session id after login. You can turn off this behavior check adapter config switches.

    SAML SP Client adapter changes

    Keycloak SAML SP Client adapter now requires a specific endpoint, /saml to be registered with your IDP.

    Admin account

    In previous releases we shipped with a default admin user with a default password, this has now been removed. If you are doing a new installation of 1.8 you will have to create an admin user as a first step.

    OAuth2 token introspection

    In order to add more compliance with OAuth2 specification, we added a new endpoint for token introspection. The new endpoint can reached at /realms/{realm-name}/protocols/openid-connect/token/introspect and it is solely based on RFC-7662.

    The /realms/{realm-name}/protocols/openid-connect/validate endpoint is now deprecated and we strongly recommend you to move to the new introspection endpoint as soon as possible. The reason for this change is that RFC-7662 provides a more standard and secure introspection endpoint.

    The new token introspection URL can now be obtained from OpenID Connect Provider’s configuration at /realms/{realm-name}/.well-known/openid-configuration. There you will find a claim with name token_introspection_endpoint within the response. Only confidential clients are allowed to invoke the new endpoint, where these clients will be usually acting as a resource server and looking for token metadata in order to perform local authorization checks.

    Direct access grants disabled by default for clients

    In order to add more compliance with OpenID Connect specification, we added flags into admin console to Client Settings page, where you can enable/disable various kinds of OpenID Connect/OAuth2 flows (Standard flow, Implicit flow, Direct Access Grants, Service Accounts). As part of this, we have Direct Access Grants (corresponds to OAuth2 Resource Owner Password Credentials Grant) disabled by default for new clients.

    Clients migrated from previous version have Direct Access Grants enabled just if they had flag Direct Grants Only on. The Direct Grants Only flag was removed as if you enable Direct Access Grants and disable both Standard+Implicit flow, you will achieve same effect.

    We also added built-in client admin-cli to each realm. This client has Direct Access Grants enabled. So if you’re using Admin REST API or Keycloak admin-client, you should update your configuration to use admin-cli instead of security-admin-console as the latter one doesn’t have direct access grants enabled anymore by default.

    Option 'Update Profile On First Login' moved from Identity provider to Review Profile authenticator

    In this version, we added First Broker Login, which allows you to specify what exactly should be done when new user is logged through Identity provider (or Social provider), but no Keycloak user linked to the social account exists yet. As part of this work, we added option First Login Flow to identity providers where you can specify the flow and then you can configure this flow under Authentication tab in admin console.

    We also removed the option Update Profile On First Login from the Identity provider settings and moved it to the configuration of Review Profile authenticator. So once you specify which flow should be used for your Identity provider (by default it’s First Broker Login flow), you go to Authentication tab, select the flow and then you configure the option under Review Profile authenticator.

    Element 'form-error-page' in web.xml not supported anymore

    form-error-page in web.xml will no longer work for client adapter authentication errors. You must define an error-page for the various HTTP error codes. See documentation for more details if you want to catch and handle adapter error conditions.

    IdentityProviderMapper changes

    The interface itself and method signatures did not change. However some changes in the behavior exist. We added First Broker Login flow in this release and the method IdentityProviderMapper.importNewUser is now called after First Broker Login flow is finished. So if you want to have any attribute available in Review Profile page, you would need to use the method preprocessFederatedIdentity instead of importNewUser . You can set any attribute by invoke BrokeredIdentityContext.setUserAttribute and that will be available on Review profile page.

    Option that refresh tokens are not reusable anymore

    Old versions of Keycloak allowed reusing refresh tokens multiple times. Keycloak still permits this, but also have an option Revoke refresh token to disallow it. Option is under token settings in admin console. When a refresh token is used to obtain a new access token a new refresh token is also included. When option is enabled, then this new refresh token should be used next time the access token is refreshed. It won’t be possible to reuse old refresh token multiple times.

    Some packages renamed

    We did a bit of restructure and renamed some packages. It is mainly about renaming internal packages of util classes. The most important classes used in your application ( for example AccessToken or KeycloakSecurityContext ) as well as the SPI are still unchanged. However, a slight chance exists that you will be affected and will need to update imports of your classes. For example if you are using multitenancy and KeycloakConfigResolver, you will be affected as for example class HttpFacade was moved to different package - it is org.keycloak.adapters.spi.HttpFacade now.

    Persisting user sessions

    We added support for offline tokens in this release, which means that we are persisting "offline" user sessions into database now. If you are not using offline tokens, nothing will be persisted for you, so you don’t need to care about worse performance for more DB writes. However in all cases, you will need to update standalone/configuration/keycloak-server.json and add userSessionPersister like this:

    "userSessionPersister": {
        "provider": "jpa"
    

    If you want sessions to be persisted in Mongo instead of classic RDBMS, use provider mongo instead.

    Realm and User cache providers

    Infinispan is now the default and only realm and user cache providers. In non-clustered mode a local Infinispan cache is used. We’ve also removed our custom in-memory cache and the no cache providers. If you have realmCache or userCache set in keycloak-server.json to mem or none please remove these. As Infinispan is the only provider the realmCache and userCache objects are no longer needed and can be removed.

    Uses Session providers

    Infinispan is now the default and only user session provider. In non-clustered mode a local Infinispan cache is used. We’ve also removed the JPA and Mongo user session providers. If you have userSession set in keycloak-server.json to mem, jpa or mongo please remove it. As Infinispan is the only provider the userSession object is no longer needed and can be removed.

    For anyone that wants to achieve increased durability of user sessions this can be achieved by configuring the user session cache with more than one owner or use a replicated cache. It’s also possible to configure Infinispan to persist caches, although that would have impacts on performance.

    Contact details removed from registration and account management

    In the default theme we have now removed the contact details from the registration page and account management. The admin console now lists all the users attributes, not just contact specific attributes. The admin console also has the ability to add/remove attributes to a user. If you want to add contact details, please refer to the address theme included in the examples.

    Direct Grant API always enabled

    In the past Direct Grant API (or Resource Owner Password Credentials) was disabled by default and an option to enable it on a realm existed. The Direct Grant API is now always enabled and the option to enable/disable for a realm is removed.

    Database changed

    There are again few database changes. Remember to back up your database prior to upgrading.

    UserFederationProvider changed

    There are few minor changes in UserFederationProvider interface. You may need to sync your implementation when upgrade to newer version and upgrade few methods, which has changed signature. Changes are really minor, but were needed to improve performance of federation.

    WildFly 9.0.0.Final

    Following on from the distribution changes that was done in the last release the standalone download of Keycloak is now based on WildFly 9.0.0.Final. This also affects the overlay which can only be deployed to WildFly 9.0.0.Final or JBoss EAP 6.4.0.GA. WildFly 8.2.0.Final is no longer supported for the server.

    WildFly, JBoss EAP and JBoss AS7 adapters

    There are now 3 separate adapter downloads for WildFly, JBoss EAP and JBoss AS7:

    You also need to update standalone.xml as the extension module and subsystem definition has changed. See Securing Applications and Services Guide for details.

    Distribution changes

    Keycloak is now available in 3 downloads: standalone, overlay and demo bundle. The standalone is intended for production and non-JEE developers. Overlay is aimed at adding Keycloak to an existing WildFly 8.2 or EAP 6.4 installation and is mainly for development. Finally we have a demo (or dev) bundle that is aimed at developers getting started with Keycloak. This bundle contains a WildFly server, with Keycloak server and adapter included. It also contains all documentation and examples.

    Database changed

    This release contains again a number of changes to the database. The biggest one is Application and OAuth client merge. Remember to back up your database prior to upgrading.

    Application and OAuth client merge

    Application and OAuth clients are now merged into Clients. The UI of admin console is updated and database as well. Your data from database should be automatically updated. The previously set Applications will be converted into Clients with Consent required switch off and OAuth Clients will be converted into Clients with this switch on.

    iss in access and id tokens

    The value of iss claim in access and id tokens have changed from realm name to realm url. This is required by OpenID Connect specification. If you’re using our adapters no change is required, except if you’ve been using bearer-only without specifying the auth-server-url, you have to add it now. If you’re using another library (or RSATokenVerifier) you need to make the corresponding changes when verifying iss.

    OpenID Connect endpoints

    To comply with OpenID Connect specification the authentication and token endpoints have been changed to having a single authentication endpoint and a single token endpoint. As per-spec response_type and grant_type parameters are used to select the required flow. The old endpoints (/realms/{realm-name}/protocols/openid-connect/login, /realms/{realm-name}/protocols/openid-connect/grants/access, /realms/{realm-name}/protocols/openid-connect/refresh, /realms/{realm-name}/protocols/openid-connect/access/codes) are now deprecated and will be removed in a future version.

    Theme changes

    The layout of themes has changed. The directory hierarchy used to be type/name this is now changed to name/type. For example a login theme named sunrise used to be deployed to standalone/configuration/themes/login/sunrise, which is now moved to standalone/configuration/themes/sunrise/login. This change was done to make it easier to have groups of the different types for the same theme into one folder.

    If you deployed themes as a JAR in the past you had to create a custom theme loader which required Java code. This has been simplified to only requiring a plain text file (META-INF/keycloak-themes.json) to describe the themes included in a JAR.

    Claims changes

    Previously a dedicated Claims tab existed in the admin console for application and OAuth clients. This was used to configure which attributes should go into access token for particular application/client. This was removed and is replaced with protocol mappers which are more flexible.

    You don’t need to care about migration of database from previous version. We did migration scripts for both RDBMS and Mongo, which should ensure that claims configured for particular application/client will be converted into corresponding protocol mappers (Still it’s safer to back up DB before migrating to newer version though). Same applies for exported JSON representation from previous version.

    Social migration to identity brokering

    We refactored social providers SPI and replaced it with Identity Brokering SPI, which is more flexible. The Social tab in admin console is renamed to Identity Provider tab.

    Again you don’t need to care about migration of database from previous version similarly like for Claims/protocol mappers. Both configuration of social providers and "social links" to your users will be converted to corresponding Identity providers.

    Only required action from you would be to change allowed Redirect URI in the admin console of particular 3rd party social providers. You can first go to the Keycloak admin console and copy Redirect URI from the page where you configure the identity provider. Then you can simply paste this as allowed Redirect URI to the admin console of 3rd party provider (IE. Facebook admin console).

    adapters are now a separate download. They are not included in appliance and war distribution. We have too many now and the distro is getting bloated.

    org.keycloak.adapters.tomcat7.KeycloakAuthenticatorValve +org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve

    JavaScript adapter now has idToken and idTokenParsed properties. If you use idToken to retrieve first name, email, etc. you need to change this to idTokenParsed.

    The as7-eap-subsystem and keycloak-wildfly-subsystem have been merged into one keycloak-subsystem. If you have an existing standalone.xml or domain.xml, you will need edit near the top of the file and change the extension module name to org.keycloak.keycloak-subsystem. For AS7 only, the extension module name is org.keycloak.keycloak-as7-subsystem.

    Server installation is no longer supported on AS7. You can still use AS7 as an application client.

    UserSessionModel JPA and Mongo storage schema has changed as these interfaces have been refactored

    Upgrade your adapters, old adapters are not compatible with Keycloak 1.1. We interpreted JSON Web Token and OIDC ID Token specification incorrectly. 'aud' claim must be the client id, we were storing the realm name in there and validating it.

    A lot of info level logging has been changed to debug. Also, a realm no longer has the jboss-logging audit listener by default. If you want log output when users login, logout, change passwords, etc. enable the jboss-logging audit listener through the admin console.

    logout REST API has been refactored. The GET request on the logout URI does not take a session_state parameter anymore. You must be logged in in order to log out the session. You can also POST to the logout REST URI. This action requires a valid refresh token to perform the logout. The signature is the same as refresh token minus the grant type form parameter. See documentation for details.

    LDAP/AD configuration is changed. It is no longer under the "Settings" page. It is now under Users→Federation. Add Provider will show you an "ldap" option.

    Authentication SPI has been removed and rewritten. The new SPI is UserFederationProvider and is more flexible.

    ssl-not-required +ssl-required +all +external +none

    DB Schema has changed again.

    Created applications now have a full scope by default. This means that you don’t have to configure the scope of an application if you don’t want to.

    Format of JSON file for importing realm data was changed. Now role mappings is available under the JSON record of particular user.

    DB Schema has changed. We have added export of the database to Beta 1, but not the ability to import the database from older versions. This will be supported in future releases.

    For all clients except bearer-only applications, you must specify at least one redirect URI. Keycloak will not allow you to log in unless you have specified a valid redirect URI for that application.

    Direct Grant API

    standalone/configuration/keycloak-server.json

    JavaScript adapter

    Session Timeout

    SkeletonKeyToken, SkeletonKeyScope, SkeletonKeyPrincipal, and SkeletonKeySession have been renamed to: AccessToken, AccessScope, KeycloakPrincipal, and KeycloakAuthenticatedSession respectively.

    ServletOAuthClient.getBearerToken() method signature has changed. It now returns an AccessTokenResponse so that you can obtain a refresh token too.

    adapters now check the access token expiration with every request. If the token is expired, they will attempt to invoke a refresh on the auth server using a saved refresh token.

    Subject in AccessToken has been changed to the User ID.

    JBoss and WildFly adapters are now installed via a WildFly subsystem. Please review the adapter installation documentation. Edits to standalone.xml are now required.

    A new credential type "secret" got introduced. Unlike other credential types, it is stored in plain text in the database and can be viewed in the admin console.

    Application and OAuth Client credentials are no longer required. These client types are now hard coded to use the "secret" credential type.

    Because of the "secret" credential change to Application and OAuth Client, you’ll have to update your keycloak.json configuration files and regenerate a secret within the Application or OAuth Client credentials tab in the administration console.

    Back up the database using instructions in the documentation for your relational database.

    The database will no longer be compatible with the old server after you upgrade the server. If you need to revert the upgrade, first restore the old installation, and then restore the database from the backup copy.

    Keycloak can automatically migrate the database schema, or you can choose to do it manually. By default the database is automatically migrated when you start the new installation for the first time.

    Automatic relational database migration

    To perform an automatic migration, start the server connected to the desired database. If the database schema has changed for the new server version, the migration starts automatically unless the database has too many records.

    For example, creating an index on tables with millions of records can be time-consuming and cause a major service disruption. Therefore, a threshold of 300000 records exists for automatic migration. If the number of records exceeds this threshold, the index is not created. Instead, you find a warning in the server logs with the SQL commands that you can apply manually.

    To change the threshold, set the index-creation-threshold property, value for the default connections-liquibase provider:

    kc.[sh|bat] start --spi-connections-liquibase-default-index-creation-threshold=300000

    Manual relational database migration

    To enable manual upgrading of the database schema, set the migration-strategy property value to "manual" for the default connections-jpa provider:

    kc.[sh|bat] start --spi-connections-jpa-quarkus-migration-strategy=manual

    When you start the server with this configuration, the server checks if the database needs to be migrated. The required changes are written to the bin/keycloak-database-update.sql SQL file that you can review and manually run against the database.

    To change the path and name of the exported SQL file, set the migration-export property for the default connections-jpa provider:

    kc.[sh|bat] start --spi-connections-jpa-quarkus-migration-export=<path>/<file.sql>

    For further details on how to apply this file to the database, see the documentation for your relational database. After the changes have been written to the file, the server exits.

    If you created custom themes, those themes must be migrated to the new server. Also, any changes to the built-in themes might need to be reflected in your custom themes, depending on which aspects you customized.

    Procedure

    Copy your custom themes from the old server themes directory to the new server themes directory.

    Use the following sections to migrate templates, messages, and styles.

    If you customized any of the updated templates listed in Migration Changes, compare the template from the base theme to check for any changes you need to apply.

    If you customized messages, you might need to change the key or value or to add additional messages.

    If you customized any styles and you are extending the Keycloak themes, review the changes to the styles. If you are extending the base theme, you can skip this step.

    Migrating templates

    If you customized any template, review the new version to decide about updating your customized template. If you made minor changes, you could compare the updated template to your customized template. However, if you made many changes, consider comparing the new template to your customized template. This comparison will show you what changes you need to make.

    You can use a diff tool to compare the templates. The following screenshot compares the info.ftl template from the Login theme and an example custom theme:

    Updated version of a Login theme template versus a custom Login theme template

    This comparison shows that the first change (Hello world!!) is a customization, while the second change (if pageRedirectUri) is a change to the base theme. By copying the second change to your custom template, you have successfully updated your customized template.

    In an alternative approach, the following screenshot compares the info.ftl template from the old installation with the updated info.ftl template from the new installation:

    Login theme template from the old installation versus the updated Login theme template

    This comparison shows what has been changed in the base template. You can then manually make the same changes to your modified template. Since this approach is more complex, use this approach only if the first approach is not feasible.

    Migrating messages

    If you added support for another language, you need to apply all the changes listed above. If you have not added support for another language, you might not need to change anything. You need to make changes only if you have changed an affected message in your theme.

    Procedure

    For added values, review the value of the message in the base theme to determine if you need to customize that message.

    For renamed keys, rename the key in your custom theme.

    For changed values, check the value in the base theme to determine if you need to make changes to your custom theme.

    Migrating styles

    You might need to update your custom styles to reflect changes made to the styles from the built-in themes. Consider using a diff tool to compare the changes to stylesheets between the old server installation and the new server installation.

    For example:

    $ diff KEYCLOAK_HOME_OLD/themes/keycloak/login/resources/css/login.css \
    KEYCLOAK_HOME_NEW/themes/keycloak/login/resources/css/login.css

    Review the changes and determine if they affect your custom styling.

    After you upgrade the Keycloak server, you can upgrade the adapters. Earlier versions of the adapter might work with later versions of the Keycloak server, but earlier versions of the Keycloak server might not work with later versions of the adapter.

    Compatibility with older adapters

    Newer versions of the Keycloak server potentially work with older versions of the adapters. However, some fixes of the Keycloak server may break compatibility with older versions of the adapters. For example, a new implementation of the OpenID Connect specification may not match older client adapter versions.

    For this situation, you can use Compatibility modes. For OpenID Connect clients, the Admin Console includes OpenID Connect Compatibility Modes on the page with client details. With this option, you can disable some new aspects of the Keycloak server to preserve compatibility with older client adapters. For more details, see the tool tips of individual switches.

    Upgrading the EAP adapter

    To upgrade the WildFly adapter, complete the following steps:

    Procedure

    Download the new adapter archive.

    Remove the previous adapter modules by deleting the WILDFLY_HOME/modules/system/add-ons/keycloak/ directory.

    Unzip the downloaded archive into WILDFLY_HOME.

    Upgrading the JavaScript adapter

    To upgrade a JavaScript adapter that has been copied to your web application, perform the following procedure.

    Procedure

    Download the new adapter archive.

    Overwrite the keycloak.js file in your application with the keycloak.js file from the downloaded archive.

    Upgrading the Node.js adapter

    To upgrade a Node.js adapter that has been copied to your web application, perform the following procedure.

    Procedure

    Download the new adapter archive.

    Remove the existing Node.js adapter directory

    Unzip the updated file into its place

    Change the dependency for keycloak-connect in the package.json of your application

    Be sure that you upgrade the Keycloak server before you upgrade the admin-client. Earlier versions of the admin-client might work with later versions of Keycloak server, but earlier versions of Keycloak server might not work with later versions of the admin-client. Therefore, use the admin-client version that matches the current Keycloak server version.