Keycloak
Custom rest api
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.
Its developed by JBoss , A division
of Red Hat and it can be use as free replacement for OAuth2.0 provider.
Keycloak comes with its own
set of REST API’s as well we can add our own REST API’s by extending SPI
features.
Service Provider
Interfaces (SPI) –
SPI enables the
customization of various aspects of server. Authentication flows, user
federation providers, protocol mappers and many more.
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.
Where keycloak.version is
the version of keycloak server.
<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>
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.
private final KeycloakSession session;
public DemoRestProvider(KeycloakSession session) { this.session = session;
}
And add method to return list
of user details.
@GET
@Path("users")
@NoCache
@Produces({MediaType.APPLICATION_JSON})
@Encoded
public List<UserDetails> getUsers() {
List<UserModel> userModel = session.users()
.getUsers(session.getContext().getRealm());
return userModel.stream()
.map(e -> toUserDetail(e))
.collect(Collectors.toList());
}
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
Deployment
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.
06:26:10,212 INFO [org.jboss.as.server] (DeploymentScanner-threads - 1) WFLYSRV0016: Replaced deployment "keycloak-rest-api-1.0.jar" with deployment "keycloak-rest-api-1.0.jar"
Validation
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