MicroProfile JWT with Keycloak

Posted by Hayri Cicek on April 23, 2019


In this tutorial, we will learn how to secure our services using MicroProfile JWT and Keycloak. Go to https://www.keycloak.org/downloads.html and download latest Standalone server distribution. Unzip the zip file and open a new terminal window and navigate to the keycloak folder. Now type following command to start the Keycloak server:


./bin/standalone.sh -Djboss.http.port=8084

First thing we will do is to create a new user, open your browser and navigate to http://localhost:8080/auth/ and create a new user with admin access.

Keycloak Create Admin

Now go to http://localhost:8080/auth/admin/ and login with the newly created user.

Keycloak Admin Login

Click on Select Realm and click on Add Realm and create a new realm called public.

Keycloak Create Realm

Now click on Client and create a new client called microprofile-jwt-client

Keycloak Create Client

Click on Groups and create a new Group called User.

Keycloak Create Group

Click on Roles and create a new role called mysimplerole.

Keycloak User Join Group

Click on Users and create another user, this new user will have access right to the endpoint we will secure later.

Keycloak Create User

Now click on Credentials and create a new password and click on Reset password. Click on the Groups tab and add the new group we created to the user.

Keycloak User Join Group

Click on Role Mappings tab and assign the mysimplerole to the user.

Keycloak Assign user new role

Click on Clients and find the microprofile-jwt-client and click on Mappers tab and click on Add Builtin button and add the groups mapper to the client.

Keycloak Mapper

Now we are done with the Keycloak configuration, it's time to secure our service.

Generate the project
Type the following command to generate a new project:

mvn archetype:generate -DarchetypeGroupId=com.kodnito -DarchetypeArtifactId=kodnito-microprofile-archetype -DarchetypeVersion=1.0.1 -DgroupId=com.kodnito.microprofile_jwt.rest -DartifactId=microprofile-jwt -Dversion=1.0-SNAPSHOT


Open microprofile-config.properties and add the following:

mp.jwt.verify.publickey.location=/META-INF/keycloak-public-key.pem
mp.jwt.verify.issuer=http://localhost:8084/auth/realms/public

And create a new file called keycloak-public-key.pem inside src/main/resources/META-INF and store the public key.

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvBRpZSvJCTnr5mXnU8RAB6dTI17PE3nig/DM
TiW1J8Ynm+WxqbdTjGadveihQqj2r5VFaKbG7FG2Xj1wkey9FfqGap+efJ9w2OOxwNNPTW36xf68LiPO
fpmr4XDOy0fHiVsVYqo4bhFSqngNPxGnmutbUIRj2Isa5y5f58QDc1PGMX+5sjkH4gJc4kxidfB635gXZ
bvHvTU2u9wUEFLfqG60qeXQTwriwZu9tbPivPBf7JMtv5qPbLWPmSP87tewlZi4wevWtS9TB7b453Usiep
QI3dBW27KUXJksSdvBRSXHgYgqqHuhN/yfN+dYbKaSMw2qNlM3LL2HeHhPCC2nQIDAQAB
-----END PUBLIC KEY-----

You find the public key here http://localhost:8084/auth/realms/public/.

Update

Since Keycloak version 6.0.0, there is built-in Client Scope which makes it really easy to issue tokens and you don't have to add the public key to the PEM file. Instead you point to Keycloak JWK's endpoint.
Open microprofile-config.properties and update it to look like this:

mp.jwt.verify.publickey.location=http://localhost:8084/auth/realms/public/protocol/openid-connect/certs
mp.jwt.verify.issuer=http://localhost:8084/auth/realms/public

Thanks @sebi2706 for the tips.

Now open the ApplicationConfig.java and make it look like this:

package com.kodnito.microprofile_jwt.rest;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import org.eclipse.microprofile.auth.LoginConfig;
import javax.annotation.security.DeclareRoles;

@LoginConfig(authMethod = "MP-JWT")
@ApplicationPath("/")
@DeclareRoles({ "mysimplerole", "USER" })
public class ApplicationConfig extends Application {

}

@LoginConfig annotation describe what associated realm name will be used in the application.
@DeclareRoles annotation is used to declare security roles.

Now open the HelloWorldEndpoint.java file and add @RolesAllowed("mysimplerole") to the doGet() method.

package com.kodnito.microprofile_jwt.rest;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.annotation.security.RolesAllowed;

@ApplicationScoped
@Path("/hello")
public class HelloWorldEndpoint {

    @GET
    @Produces("text/plain")
    @RolesAllowed("mysimplerole")
    public Response doGet() {
        return Response.ok("Hello from MicroProfile!").build();
    }
}

@RolesAllowed annotation is used to declare security roles and specifies a list of roles to access methods in the application.
Download Postman, if you don’t already have it installed. We will now invoke the Keycloak auth token endpoint to retrieve the access token to use in our service. Open Postman and add the following to retrieve access token.

POST: http://localhost:8084/auth/realms/public/protocol/openid-connect/token
realm: public
grant_type: password
client_id: microprofile-jwt-client
username: microprofile-jwt-user
password: the_password_of_the_user


Keycloak Authentication Endpoint

Now click on Send and you will retrieve access token. Copy the access token and open a new Postman tab. Now, make an GET request to http://localhost:8080/restapi/hello, if you don’t send the request with access token, you will get 401 Unauthorized. In Type dropdown menu, choose Bearer Token and paste the token in Token field. Now click on Send again and you will now get 200 OK.

MicroProfile JWT Keycloak AccessToken

And that’s it, we have secured our /hello endpoint.


Share this: