Search Users in Keycloak using Admin REST APIs

In this Keycloak tutorial, we will learn to use the Keycloak Admin REST API to search for users in Keycloak from a Spring Boot application. We will start by configuring a Keycloak server and setting up the necessary configurations. Then, we will explore the search API provided by Keycloak to search for users by ID, email, username, custom attributes, and role.

1. Prerequisites

To follow along with the code examples and explanations in this article, we should have a few prerequisites in place:

2. Setup

2.1. Users in the Realm

After installing the Keycloak server, the next step is to setup the working environment. This involves creating a realm, client, users, and roles. While you are free to create your own objects, we will use the objects that come with Keycloak (such as the master realm and admin CLI client) and create some additional users and roles for demonstration purposes.

For this tutorial, we are configuring the following users in the keycloak.

"users" : [ 
{
    "id" : "cf84e94e-21e0-4c31-a153-a392ecae5054",
    "createdTimestamp" : 1683300067698,
    "username" : "admin",
    "enabled" : true,
    "totp" : false,
    "emailVerified" : false,
    "firstName" : "",
    "lastName" : "",
    "email" : "hamza.nassour13@gmail.com",
    "credentials" : [ {
      "id" : "d3325bd0-307c-4c9f-926b-1b8264389b89",
      "type" : "password",
      "createdDate" : 1683300067850,
      "secretData" : "{...} ],
    "disableableCredentialTypes" : [ ],
    "requiredActions" : [ ],
    "realmRoles" : [ "admin", "default-roles-master" ],
    "notBefore" : 0,
    "groups" : [ ]
  }, 
  {
    "id" : "967a26d3-9a37-4a3b-9c22-c774f2933158",
    "createdTimestamp" : 1683304603863,
    "username" : "user1",
    "enabled" : true,
    "totp" : false,
    "emailVerified" : false,
    "firstName" : "user1",
    "lastName" : "user1",
    "email" : "user1@howtodoinjava.com",
    "attributes" : {
      "phone" : [ "1234567890" ]
    },
    "credentials" : [ ],
    "disableableCredentialTypes" : [ ],
    "requiredActions" : [ ],
    "realmRoles" : [ "default-roles-master" ],
    "notBefore" : 0,
    "groups" : [ ]
  } 
]

Please refer to this article for more information.

2.2. Maven

Keycloak REST API provides a convenient way to access all the features available on the Admin Console from our applications. To start making calls to Keycloak, add the latest version of keycloak-admin-client that provides a Java client for interacting with the Keycloak server’s admin API, allowing us to manage Keycloak resources programmatically (users, realms, clients, roles, etc).

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-admin-client</artifactId>
    <version>21.1.1</version>
</dependency>

3. Configuring the Keycloak Bean

The Keycloak Admin Client provides the Keycloak class, which can be used to send requests to Keycloak’s REST API. To create a Keycloak instance, we can use the KeycloakBuilder class.

@Configuration
public class Config {

    @Bean
    public  Keycloak keycloak() {

       return KeycloakBuilder.builder()
                .serverUrl("http://localhost:8080/")
                .realm("master")
                .grantType(OAuth2Constants.PASSWORD)
                .username("admin")
                .password("admin")
                .clientId("admin-cli")
                .resteasyClient(new ResteasyClientBuilder()
                        .connectionPoolSize(10)
                        .build()).build();
    }
}

Here we are setting up the Keycloak bean by providing the necessary values such as admin credentials, client ID, and realm. Once the bean is instantiated, it can be used to perform various administrative tasks within a Spring Boot application, such as searching for users in Keycloak and creating users.

Now we can use the bean by injecting it into any class:

@Service
public class KeycloakService {

    @Autowired
    Keycloak keycloak;

    //...
}

4. Searching Users in Keycloak

Keycloak offers a range of search methods to locate users, including searching by ID, email, username, custom attributes, and role.

4.1. Search by ID

Every user in Keycloak has a unique ID, which can be used to search for that user.

UserResource userResource = keycloak.realm("master").users().get(id);

To access the users within the realm, we use the users() method of the RealmResource object. It returns an UsersResource object that represents a collection of users in the realm. To retrieve a specific user by ID, we use the get(id). This method returns an UserResource object that contains complete information about a specific user, such as their username and email etc.

4.2. The UsersResource.search() API

Another way to search for a user in Keycloak is by their email address. To do this, we can use the UsersResource.search() API.

The search() method is an overloaded method that takes different arguments for different search parameters. These parameters and methods are version-specific so checkout the latest Java docs for supported methods and arguments.

List<UserRepresentation> searchByEmail​(String email, Boolean exact);
List<UserRepresentation> searchByFirstName​(String email, Boolean exact)	 
List<UserRepresentation> searchByLastName​(String email, Boolean exact)	 
List<UserRepresentation> searchByUsername​(String username, Boolean exact)

//Search for users based on the given filters.

List<UserRepresentation> search(@QueryParam("username") String var1, 
		@QueryParam("firstName") String var2, 
		@QueryParam("lastName") String var3, 
		@QueryParam("email") String var4, 
		@QueryParam("first") Integer var5, 
		@QueryParam("max") Integer var6);

4.3. Search by Email

For example, we can search user(s) based on the email address as follows. The method returns a list of UserRepresentation objects that match the given email.

List<UserRepresentation> userRepresentationsList = keycloak.realm("master").users().searchByEmail(email, true);

In this example code, we use the search() method of the UsersResource object to search for users in the “master” realm of Keycloak that have the provided email address.

4.4. Search By Username

We can use the search API to find a user by username as well. Note that there can be multiple users with the same username (a few may be disabled) so the API returns a List.

List<UserRepresentation> users = keycloak.realm("master").users().searchByUsername(username, true);

4.5. Search by Attribute

Keycloak allows us to define custom attributes for users, which can be used to store additional information about the user. We can also search for users based on these custom attributes.

List<UserRepresentation> searchByAttributes(@QueryParam("q") String var1);

We construct the search query by concatenating the attribute name (“phone”), a colon, and the search term. Assuming that a custom attribute named “phone” has been defined, we can search the users using the following code:

List<UserRepresentation> users = keycloak.realm("master").users().searchByAttributes("phone:" + phone);

4.6. Search by Role

In Keycloak, we can assign roles to users to control their access to resources and functionality within our application. We can also search for users based on the roles they have been assigned.

Assuming that a role named “admin” has been defined in the Keycloak realm and assigned to some users, we can search for users with this role using the following code. This API returns users that have the given role, sorted by username ascending.

Also, this method returns the first 100 users. In order to retrieve all users, use paging (see getUserMembers(Integer, Integer)).

Set<UserRepresentation> users = keycloak.realm("master").roles().get(roleName).getUserMembers();

5. Test

The following test class declaration injects the Keycloak instance class, enabling testing of the different APIs provided by Keycloak.

@SpringBootTest
class SearchInKeycloakWithSpringBootApplicationTests {

  @Autowired
  private Keycloak keycloak;

  @Test
  void testSearchById() {

    String id = "967a26d3-9a37-4a3b-9c22-c774f2933158";
    UserResource userResource = keycloak.realm("master").users().get(id);
    Assertions.assertEquals(id, userResource.toRepresentation().getId());
  }

  @Test
  void testSearchByEmail() {

    String email = "user1@howtodoinjava.com";
    List<UserRepresentation> userRepresentationsList = keycloak.realm("master").users().searchByEmail(email, true);
    Assertions.assertEquals(1, userRepresentationsList.size());
    Assertions.assertEquals(email, userRepresentationsList.get(0).getEmail());
  }

  @Test
  void testSearchByUsername() {

    String username = "user1";
    List<UserRepresentation> userRepresentationsList = keycloak.realm("master")
        .users()
        .searchByUsername(username, true);
    Assertions.assertEquals(1, userRepresentationsList.size());
    Assertions.assertEquals(username, userRepresentationsList.get(0).getUsername());
  }

  @Test
  void testSearchByPhone() {

    String phone = "1234567890";
    List<UserRepresentation> userRepresentationsList = keycloak.realm("master")
            .users()
            .searchByAttributes("phone:" + phone);
    Assertions.assertEquals(1, userRepresentationsList.size());
    Assertions.assertEquals(phone, userRepresentationsList.get(0).firstAttribute("phone"));
  }

  @Test
  void testSearchByRole() {

    String role = "admin";
    Set<UserRepresentation> userRepresentationSet =keycloak.realm("master").roles().get(role)
            .getRoleUserMembers();
    Assertions.assertEquals(1, userRepresentationSet.size());
    for (UserRepresentation userRepresentation : userRepresentationSet) {
      Assertions.assertEquals("admin" , userRepresentation.getUsername());
    }
  }
}

6. Conclusion

In this article, we’ve explored how to search for users in Keycloak using various criteria, including their ID, email, username, custom attributes, and assigned roles. We’ve seen how to use the Keycloak API to search for users by using various methods on the RealmResource, RolesResource and UsersResource objects.

Happy Coding!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode