Keycloak: Work with client roles in Spring Boot

Justus Nithushan
Chain Analytica
Published in
4 min readNov 17, 2020

Before reading this, to get a clear understanding on how to create and setup a keycloak server, how to create user, what is a role, what are the types of role exist in keycloak, how to create realm role and how to assign a realm role to a user etc. read my previous two posts. The links are given below.

https://medium.com/chain-analytica/keycloak-create-users-for-a-realm-in-spring-boot-3eff924a8db1

https://medium.com/chain-analytica/keycloak-working-with-realm-roles-in-springboot-dc2776ccd27e

With admin console

Login to the admin console http://localhost:8080/auth/admin/ using your admin credentials. Switch to the realm of your client. Click on your client ID from the list of ‘clients’ that you can see when clicking on Clients button in the left side navigation bar. In the next screen switch to ‘Roles’ tab and click on ‘Add Role’ button.

In the next screen, give the name of you role and description(optional) and click on save.

Using the following screen that appears after saving, you can make it a composite role by adding some more roles to it if needed. For that, you can on the switch which is corresponding to the label named Composite role and in the Composite Roles section you can add more roles to associate with our newly created role. Below picture shows a role named ‘offline-access’ is added to our role.

We have successfully created a client role, let us add this to a user. For that click on Users button on the left side navigation bar and then click on the user id or edit button which is corresponding to the preferred user. Then go to Role Mappings tab; From the Client Roles drop down button select your preferred client; then select the role from the Available Roles area and click on Add Selected to assign that particular client role to that particular user.

Time to move on to the interesting part! From now we will look into how we can do all the above works programmatically in Spring Boot using Keycloak admin client API. Let’s start.

With Spring Boot application

Open your preferred browser and go to start.spring.io and create a new spring boot application. Make sure the following dependencies are added in pom.xml file.

<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>11.0.3</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.1.3.Final</version>
</dependency>

Yes it is coding time!! Let’s first have a look on how to get a Keycloak instance.

static Keycloak keycloak = null;
final static String serverUrl = "http://localhost:8080/auth";
final static String realm = "YOUR_REALM_NAME";
final static String clientId = "YOUR_CLIENT_ID";
final static String clientSecret = "YOUR_CLIENT_SECRET_KEY";
final static String userName = "YOUR_REALM_ADMIN_USERNAME";
final static String password = "Your_REALM_ADMIN_PASSWORD";

if(keycloak == null){

keycloak = KeycloakBuilder.builder()
.serverUrl(serverUrl)
.realm(realm)
.grantType(OAuth2Constants.PASSWORD)
.username(userName)
.password(password)
.clientId(clientId)
.clientSecret(clientSecret)
.resteasyClient(new ResteasyClientBuilder()
.connectionPoolSize(10)
.build();
)
.build();
}

Fine, if it is successful we can do the magic with our keycloak instance. Follow on folks. The below code snippet shows how we can get all the available roles for the particular client registered in our keycloak server.

public List<String> getAllRoles(){ 
ClientRepresentation clientRep = keycloak
.realm(realm)
.clients()
.findByClientId(clientId)
.get(0);
List<String> availableRoles = keycloak
.realm(realm)
.clients()
.get(clientRep.getId())
.roles()
.list()
.stream()
.map(role -> role.getName())
.collect(Collectors.toList());
return availableRoles;
}

Lets create a method to add a new client role.

public addRealmRole(String new_role_name){ 
if(!getAllRoles().contains(new_role_name)){
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName(new_role_name);
roleRep.setDescription("role_" + new_role_name);
ClientRepresentation clientRep = keycloak
.realm(realm)
.clients()
.findByClientId(clientId)
.get(0);
keycloak.realm(realm)
.clients()
.get(clientRep.getId())
.roles()
.create(roleRep);
}
}

We have created a new role to our realm. Now we shall look into how to get our new role as a Role Representation and make it a composite role by adding “offline_access” realm role to it.

public void makeComposite(String role_name){ClientRepresentation clientRep = keycloak
.realm(realm)
.clients()
.findByClientId(clientId)
.get(0);
RoleRepresentation role = keycloak
.realm(realm)
.clients()
.get(clientRep.getId())
.roles()
.get(role_name)
.toRepresentation();
List<RoleRepresentation> composites = new LinkedList<>(); composites.add(keycloak
.realm(realm)
.roles()
.get("offline_access")
.toRepresentation()
);
keycloak.realm(realm).rolesById().addComposites(composites);
}

Let us finish this story by creating a method to add a client role specified by its name to a user specified by a user name.

public void addRealmRoleToUser(String userName, String role_name){ String client_id = keycloak
.realm(realm)
.clients()
.findByClientId(clientId)
.get(0)
.getId();
String userId = keycloak
.realm(realm)
.users()
.search(userName)
.get(0)
.getId();
UserResource user = keycloak
.realm(realm)
.users()
.get(userId);
List<RoleRepresentation> roleToAdd = new LinkedList<>(); roleToAdd.add(keycloak
.realm(realm)
.clients()
.get(client_id)
.roles()
.get(role_name)
.toRepresentation()
);
user.roles().clientLevel(client_id).add(roleToAdd);
}

Hope you enjoyed this blog. Follow me to get to know some more interesting stuffs like this. Please don’t forget to give some clapping.

--

--