Keycloak : create custom rest api

gaurav wadhone
4 min readSep 24, 2020

--

Get all user details without password/Token

Introduction:

Keycloak is an open source software product to allow single sign-on with Identity and Access Management aimed at modern applications and services.

Keycloak is developed by JBoss , A division of Red Hat and it can be use as free replacement for OAuth2.0 provider.

Service Provider Interfaces (SPI)

Keycloak comes with its own set of REST API’s as well we can add our own REST API’s by extending SPI features.

SPI enables the customization of various aspects of server. Authentication flows, user federation providers, protocol mappers and many more.

Why custom REST API ?

Keycloak provides adapters for languages as well platforms but it comes with limited Admin Rest API which requires Admin role to retrieve any details or reset user own password.

Creating a REST API

In this article we will create REST API which will be served by keycloak server and provide all uses details without login.

To begin with let’s create plain java application with maven and the below dependencies to it.

<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
<version>${keycloak.version}</version>
</dependency>
</dependencies>

Where keycloak.version is the version of keycloak server.

In maven project create below structure for resources

+--- pom.xml
+--- src
| +--- main
| | +--- java
| | | +--- gaurav
| | | | +--- keycloak
| | | | | +--- DemoRestProvider.java
| | | | | +--- DemoRestProviderFactory.java
| | +--- resources
| | | +--- META-INF
| | | | +--- jboss-deployment-structure.xml
| | | | +--- services
| | | | | +--- org.keycloak.services.resource.RealmResourceProviderFactor

Here we added DemoRestProviderFactory to create factory class for DemoRestProvider

Class DemoRestProviderFactory and DemoRestProvider will implement the interfaces org.keycloak.services.resource.RealmResourceProviderFactory and org.keycloak.services.resource.RealmResourceProvider respectively.

In Factory class DemoRestProviderFactory we will define the rest api end point name. say for demo its “gaurav-rest” and during constructor it will create instance for DemoRestProvider.

Please note factory instance will remain through out the lifecycle of keycloak server but DemoRestProvider instance will be created whenever we will hit the rest request for it.

Below is code for DemoRestProviderFactory

public class DemoRestProviderFactory implements RealmResourceProviderFactory{

public static final String ID = "gaurav-rest";
public RealmResourceProvider create(KeycloakSession session) {
return new DemoRestProvider(session);
}
public void init(Scope config) {}
public void postInit(KeycloakSessionFactory factory) {}
public void close() {}
public String getId() { return ID;}

}

Now let update DemoRestProvider class with constructor to retrieves session from factory.

public class DemoRestProviderFactory implements RealmResourceProviderFactory{

public static final String ID = "gaurav-rest";
public RealmResourceProvider create(KeycloakSession session) {
return new DemoRestProvider(session);
}
public void init(Scope config) {}
public void postInit(KeycloakSessionFactory factory) {}
public void close() {}
public String getId() { return ID;}
}

And add method to return list of user details.

Here UserDetails is custom class to store only username, first name, last name.

Now register the factory class to keycloak by adding factory class name to org.keycloak.services.resource.RealmResourceProviderFactory (as below file location)

| +--- resources
| | +--- META-INF
| | | +--- services
| | | | +--- org.keycloak.services.resource.RealmResourceProviderFactory

Create the package by running maven build and copy it to keycloak deployment directory.

${KEYCLOAK_HOME}/standalone/deployments.

Keycloak support hot deployment so as soon file jar file copied to above location it will create <jar name>.deployed file if deployment was successful and also add below in log file of keycloak.

If application was deployed correctly it will be added to keycloak server and visible under provider details as below.

Testing

Before testing we need to create realm and add few user to keycloak.

To create realm first login to keycloak server and create realm as below.

Here I create realm “GW” and added few users to it.

Now we have user we can execute the rest . Below is sample for curl command

curl-s -X GET"http://localhost:8180/auth/realms/GW/gaurav-rest/users" | jq
[
{
"userName": "gaurav",
"firstName": "gaurav",
"lastName": "wadhone"
},
{
"userName": "testuser",
"firstName": "test",
"lastName": "user"
},
{
"userName": "testuser2",
"firstName": "test",
"lastName": "user2"
}
]

Conclusion

Although this is bed example to retrieve user details without login/password but we can achieve same by extending SPI interface and we can use similar approach where Out of Box Admin API’s of keycloak are not enough.

We can also extend above example to execute with JWT token where user has specific role

Source

Source code : https://github.com/gauravwadhone/keycloak

Originally published at https://gaurav-wadhone.blogspot.com.

--

--