In this article, Janua’s CTO shares tips and tricks about understanding Keycloak user Federation
1 Understanding Keycloak user Federation
1.1 Overview
Keycloak comes up with a user storage SPI. By default Keycloak comes with 3 different user storage federation adapters:
The customer can write his own user storage implementation using the userstorage SPI. This can be very handy in case of former migration an old customer tdatabase (such as SQL or other) to a LDAP database. The customer has only to implement a a specific user storage plugin during the migration time.
1.2 User Federation storage Provider
https://www.keycloak.org/docs/latest/server_admin/index.html#_ldap
Out of the box we have support for LDAP and Active Directory and Kerberos. You can also code your own extension for any custom user databases you might have using our User Storage SPI.
The way it works is that when a user logs in, Keycloak will look into its own internal user store to find the user. If it can’t find it there it will iterate over every User Storage provider you have configured for the realm until it finds a match. Data from the external store is mapped into a common user model that is consumed by the Keycloak runtime.
1.3 Keycloak default local userstorage (SQL database)
1.3.1 Synchronizing LDAP users to keycloak
By default, Keycloak will import users from LDAP into the local Keycloak user database (sql database)
• synchronized is done on demand, or through a periodic background task.
• Only Passwords are not imported and password validation is delegated to the LDAP server.
Advantages:
• The beneficial Keycloak features will work as any extra per-user data that is needed can be stored locally.
• This approach also reduces load on the LDAP server as uncached users are loaded from the Keycloak database the 2nd time they are accessed.
• only load your LDAP server will have is password validation.
Disadvantage:
• The downside to this approach is that when a user is first queried, this will require a Keycloak database insert.
• import will also have to be synchronized with your LDAP server as needed.
Alternatively, you can choose not to import users into the Keycloak user database. In this case, the common user model that the Keycloak runtime uses is backed only by the LDAP server
• storage mode is controlled by the Import Users switch.
• Users are imported when this flag is to ON (as above on the screenshot)
• It is possible to define the synchronization frequency (periodically, or or demand).
• When this flag is to OFF, users attributes are read from LDAP
1.3.2 Synchronizing newly created Keycloak users to LDAP
The flag Sync Registration when enabled, indicates that newly created keycloak user have to be created on LDAP as well.
1.3.3 Dealing with keycloak – LDAP synchronization parameter
Keycloak LDAP sync strategy has to be has to be adjusted and tailored according to customer needs.
The most effective way to use synchronization is to base synchronization on LDAP user change log (i.e enable periodic Change Users Sync)
1.4 Using Keycloak user Federation SPI
https://www.keycloak.org/docs/latest/server_development/index.html#_user-storage-spi
https://www.keycloak.org/docs/latest/server_development/index.html#provider-capability-interfaces
Keycloak defines the following user provider interfaces
SPI | Description |
org.keycloak.storage.user.UserLookupProvider | This interface is required if you want to be able to log in with users from this external store. Most (all?) providers implement this interface. |
org.keycloak.storage.user.UserQueryProvider | Defines complex queries that are used to locate one or more users. You must implement this interface if you want to view and manage users from the administration console. |
org.keycloak.storage.user.UserRegistrationProvider | Implement this interface if your provider supports adding and removing users. |
org.keycloak.storage.user.UserBulkUpdateProvider | Implement this interface if your provider supports bulk update of a set of users. |
org.keycloak.credential.CredentialInputValidator | Implement this interface if your provider can validate one or more different credential types (for example, if your provider can validate a password). |
org.keycloak.credential.CredentialInputUpdater | Implement this interface if your provider supports updating one or more different credential types. |
1.5 Using Keycloak Provider interfaces
Keycloak comes with 2 samples which are:
• keycloak user-storage-simple
https://github.com/keycloak/keycloak-quickstarts/tree/latest/user-storage-simple
• keycloak user-storage-jpa
https://github.com/keycloak/keycloak-quickstarts/tree/latest/user-storage-jpa
Those both examples can be downloaded from keycloak quickstart
1.6 keycloak user storage simple (read-only)
1.6.1 Deploying providers
The user has to compile and deploy the example, which entails the creation of 2 providers:
• read-only-property-file
• write-only-property-file
step 0
starting keycloak
sh standalone.sh
step 1
deploying the providers
cd user-storage-simple
mvn clean install wildfly:deploy
Step2
Selecting the newly created provider
and click “save”
step 3
The user is defined is in the file users.properties
user-storage-simple/src/main/resources$ cat users.properties
#
tbrady=superbowl
Step 4 – Logging
It is possible to use the account realm client-credentials
Once logged, is displayed the credentials.
1.7 User storega simple provider (write only)
1.7.1 Configuring the write only provider
The write only provider behaves in the same way, as previous one.
You have to enter the path of your write only provider file
1.7.2 example-user.properties
In example-users.properties, the entries user1, user2, user3 are created
orivat@asus:~/dev/keycloak_4.83/keycloak-quickstarts-latest/user-storage-simple$ cat /tmp/example-users.properties
#
#Mon Feb 25 10:37:20 CET 2019
user1=password
user2=password
uers3=password
1.7.3 Logging to keycloak
It possible to log to the keycloak account app
The keycloak user session has been created as well
1.7.4 Displaying all the users
When using the keycloak quickstart gitlab sources, you need to modify the sources as follows, if you want to display the users within the keycloak admin console
(modif 1)
@Override
public List searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
List users = new LinkedList<>();
int i = 0;
for (Object obj : properties.keySet()) {
String username = (String)obj;
///modif
if ((search !=null) && (!username.contains(search))) continue;
if (i++ < firstResult) continue;
UserModel user = getUserByUsername(username, realm);
users.add(user);
if (users.size() >= maxResults) break;
}
return users;
}
(modif 2)
@Override
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
// only support searching by username
String usernameSearchString = params.get(« username »);
// does not exit
// in case user are displayed
// if (usernameSearchString == null) return Collections.EMPTY_LIST;
return searchForUser(usernameSearchString, realm, firstResult, maxResults);
}
1.8 Keycloak user storage JPA provider
1.8.1 Presentation
Keycloak provides out of the box an implementation for JavaEE apps using JPA, allowing to connect to SQL database.
https://www.keycloak.org/docs/latest/server_development/index.html#leveraging-java-ee-2
1.8.2 Using JPA
JPA is de facto a standard when using SQL database,and allows to perform sql queries from the java app whithout being knowledgeable about sql
Some key features of JPA with SQL:
• Named queries
◦ it allows to write/define high level queries from Java
• Entity Manager (Persitence Manager)
▪ An EntityManager instance may represent either a remote connection to a remote database server
• Entity
◦ JPA Entity classes are user defined classes whose instances can be stored in a database.
When deploying a Jpa app, those are some of the key elepments to pay attention to.
Pointers:
https://www.objectdb.com/java/jpa
https://examples.javacodegeeks.com/enterprise-java/jpa/jpa-criteriabuilder-example/
https://www.logicbig.com/tutorials/java-ee-tutorial/jpa/connecting-oracle.html
1.8.3 Keycloak user storage jpa example
Keycloak provides a user-storage-jpa example,in the keycloak quickstart guide
This example is created a XA database at deployment, but breaks later
step 0
Keycloak needs to be launched as follows:
sh standalone.sh -Djboss.socket.binding.port-offset=100 –debug 8100
Step1
From
https://github.com/keycloak/keycloak-quickstarts/tree/latest/user-storage-jpa
You must first deploy the datasource it uses. Start up the Keycloak server. Then in the directory of this example type the following maven command:
mvn -Padd-datasource install
The command mvn -Padd-datasource install is failing as follows:
mvn -Padd-datasource install
[INFO] Scanning for projects…
[INFO]
[INFO] ————————————————————————
[INFO] Building Keycloak Quickstart: user-storage-jpa 4.8.3.Final
[
INFO: ELY00001: WildFly Elytron version 1.1.7.Final
[INFO] ————————————————————————
[INFO] BUILD FAILURE
[INFO] ————————————————————————
[INFO] Total time: 3.226 s
[INFO] Finished at: 2019-02-25T11:32:09+01:00
[INFO] Final Memory: 32M/388M
[INFO] ————————————————————————
[ERROR] Failed to execute goal org.wildfly.plugins:wildfly-maven-plugin:1.2.2.Final:add-resource (add-datasource) on project keycloak-user-storage-jpa: Could not execute goal add-resource. Reason: Operation failed: {« WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed: » => {« Operation step-1 » => « WFLYCTL0158: Operation handler failed: org.jboss.msc.service.DuplicateServiceException: Service jboss.data-source.\ »jboss.naming.context.java.jboss.datasources.ExampleXADS\ » is already registered »}} -> [Help 1]
………….
………
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] https://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Some internal analysis have showcased that the file pom.xml is incorrect :
orivat@asus:~/dev/keycloak_4.83/keycloak-quickstarts-latest/user-storage-jpa$ diff pom.xml.good pom.xml
148c148
< <address>xa-data-source=ExampleXADS</address>
—
> <address>xa-data-source=java:jboss/datasources/ExampleXADS</address>
the correct line is:
<address>xa-data-source=ExampleXADS</address>
You should update your pom.xml accordingly
Once you have updted your pom.xml, creation of the datasource should proceed quietly
1.8.4 Testing XA data source with keycloak console management
A possible way to proceed with XA data source testing is to use the keycloak admin management console.
The admin management console is launched at URL 10090
https://localhost:10090/console
You also need to have created an admin management user to use the console using add-user.sh.
Like this, you can see all datasources, and also test that the datasource is enabled.
1.8.5 Testing with with the Ejb appl
You need to deploy the app manually
Jboss-cli.sh
connect localhost:10090
[standalone@localhost:10090 /] deploy –force /home/orivat/dev/keycloak_4.83/keycloak-quickstarts-latest/user-storage-jpa/target/user-storage-jpa-example.jar
1.8.6 Rendering users visible in the admin console
By default, cretaed users are not visible in the amin console
You need to do 2 code mode modification to render them visible in the admin console
(modif1)
@Override
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
//return Collections.EMPTY_LIST;
return getUsers(realm, firstResult, maxResults);
}
(modif2)
The following method needs to be updated as follows:
/*
*
* @Override
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
List<UserModel> users = new LinkedList<>();
int i = 0;
for (Object obj : properties.keySet()) {
String username = (String)obj;
if ((search !=null) && (!username.contains(search))) continue;
if (i++ < firstResult) continue;
UserModel user = getUserByUsername(username, realm);
users.add(user);
if (users.size() >= maxResults) break;
}
return users;
}
1.9 Pointers
https://www.keycloak.org/docs/latest/server_development/index.html#leveraging-java-ee-2
https://www.keycloak.org/docs/latest/server_admin/index.html#_user-storage-federation
https://www.keycloak.org/docs-api/4.8/javadocs/index.html
- New Keycloak online training - 19 janvier 2022
- Sizing Keycloak or Redhat SSO projects - 8 juin 2021
- Keycloak.X Distribution - 28 janvier 2021