Keycloak is an open-source IAM solution that provides user federation, strong authentication, user management, and much more. As a single sign-on provider, it allows users to authenticate via external identity sources such as LDAP or Active Directory services that store user and credential information. You can point Keycloak to validate credentials from those external stores and pull in identity information.
In this post, we will look at options provided by Keycloak that allow a server developer to build their own authentication strategy by extending Keycloak’s user federation APIs. Our starting position is:
22
17
You can use Keycloak’s User Storage SPI to write extensions to Keycloak to connect to external user databases and credential stores. Organizations often have existing external proprietary user databases that they cannot migrate to Keycloak’s data model and application developers then need to write implementations of the User Storage SPI to bridge the external user store and the internal user object model that Keycloak uses to log in users and manage them.
When the Keycloak runtime needs to look up a user, such as when a user is logging in, it performs a number of steps to locate the user. It first looks to see if the user is in the user cache; if the user is found it uses that in-memory representation. Then it looks for the user within the Keycloak local database. If the user is not found, it then loops through User Storage SPI provider implementations to perform the user query until one of them returns the user the runtime is looking for.
Note that User Storage SPI provider implementations are not enabled by default, but instead must be enabled and configured per realm under the User Federation tab in the administration console.
To extend parts of Keycloak, one has to register custom implementations of Keycloak Service Provider Interfaces (SPIs). In our case, we will need to implement the org.keycloak.storage.UserStorageProviderFactory
and register it with the Java Service Loader API. This factory is then tasked to supply an implementation of the UserStorageProvider
that selects and delivers the final user to Keycloak.
So, let’s start with our factory implementation:
package org.example.keycloak;
public class MyUserStorageProviderFactory
implements UserStorageProviderFactory<MyUserStorageProvider> {
private MyAuthenticationClient client;
@Override
public void init(final Config.Scope config) {
client = new MyAuthenticationClient(...);
}
@Override
public MyUserStorageProvider create(KeycloakSession keycloakSession,
ComponentModel componentModel) {
return new MyUserStorageProvider(keycloakSession, componentModel, client);
}
@Override
public String getId() {
return "my-user-storage";
}
@Override
public String getHelpText() {
return "My User Storage Provider";
}
}
…and then, our own MyUserStorageProvider
implementation:
public class MyUserStorageProvider implements UserStorageProvider {
}
Keycloak also providers a number of additional Provider implementation that you may choose to implement to assist with various CRUD and password operations:
UserLookupProvider
CredentialInputValidator
CredentialInputUpdater
UserQueryProvider
Next, we need to register our factory implementation inside the file META-INF/services/org.keycloak.storage.UserStorageProviderFactory
:
org.example.keycloak.MyUserStorageProviderFactory
As discussed before, User Storage SPI provider implementations are not enabled by default, but instead must be enabled and configured per realm under the User Federation tab in the administration console. This can be done with the following steps:
…and you’re done!
If you have questions about the contents and the topic of this blog post, or if you need additional guidance and support, feel free to send us a note and ask about consulting and support services.
I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please feel free to engage and contribute as best as you can.
Monday-Friday
9am-6pm, Central European Time
7am-1pm, U.S. Eastern Time
Monday-Friday
9am-6pm, Central European Time