Securing a MicroProfile application with Keycloak

In this tutorial we will learn how to secure a Microprofile application running with Thorntail runtime and Keycloak.

 

Keycloak is an Identity and Access Management Server for Modern Applications and Services. In this tutorial we will learn how to delegate a bash Web application authentication (running on WildFly) to a KeyCloak server.

First of all, download the latest stable build of Keycloak from http://keycloak.jboss.org/keycloak/downloads

Starting Keycloak

Keycloak ships bundled in a WildFly installation. We will start it with an offset of 100 in order to avoid conflicts with our default Thorntail runtime (that will be bound with 0 offset), where our application will run:

$ ./standalone.sh -Djboss.socket.binding.port-offset=100

Now log into the Administration Console, available at: http://localhost:8180

In your first Login, you will be requested to create an administration user:

keycloak tutorial

Next, login with the admin user you have just created:

keycloak introduction

Create your Keycloak Realm, Roles and Users

The core concept in Keycloak is a Realm. A realm secures and manages security metadata for a set of users, applications, and registered oauth clients. Users can be created within a specific realm within the Administration console. Roles (permission types) can be defined at the realm level and you can also set up user role mappings to assign these permissions to specific users.

Let’s start by creating a new Realm by clicking on the Add Realm Button, located on the left side bar:

keycloak tutorial

Enter the Realm Name, for example MyRealm and click on Create:

keycloak tutorial

Now we will define a Role. The Role will be used by your applications to define which users will be authorized to access the application. Click on the “Roles” left link and choose “Add Role“:

keycloak tutorial

We have added a Role named “Manager” that will be authorized to access our application. So far we don’t have any User, besides the admin user. We will create another one to be used by our application. Click on the “Users” left option and choose to Add a new User:

keycloak tutorial

The User named “frank” will be added by clicking on Save. Now select the User from the list: we need to perform two actions on it.

keycloak tutorial

The first one will be setting a password for it so click on Credentials and set a new Password for the user:

keycloak tutorial

Next we will include the User as part of the Manager Role. Click on Role Mappings and assign the User to the Manager Role by selecting the Manager Role and clicking on Add selected:

keycloak tutorial

Define Client policies

Done with User and Realms. We need to define which applications are mapped to our Users/Roles. In the earlier versions of KeyCloak you had to click on the “Applications” left link. Now applications are categorized as “Clients” so click on that link on the left:

keycloak tutorial

Choose to Create a new Client. The most important settings are the application Root URL (that will be appended to the URI path) and the Redirect URIs where request will be forwarded after login. In our case, we will create a web application named “keydemo” therefore we will use the following settings:

keycloak tutorial

Click on Save. Once saved, the last step will be generating a public key for your realm that will be bundled in your application. From the Clients perspective, click on the Installation link and choose to generate a JSON authorization code for your application:

keycloak tutorial

Download the JSON or simply copy it in an editor, we will use it in a minute.

Securing a Microprofile application with Keycloak

We will be creating a simple JAX-RS application that exposes an “/hello” resource. We therefore need the jaxrs and keycloak fraction in our configuration:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.thorntail.examples</groupId>
   <version>1.0</version>
   <artifactId>example-keycloak</artifactId>
   <name>Thorntail Examples: Keycloak</name>
   <description>Thorntail Examples: Keycloak</description>
   <packaging>war</packaging>
   <properties>
      <version.thorntail>2.4.0.Final</version.thorntail>
   </properties>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
               <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
         </plugin>
         <plugin>
            <groupId>io.thorntail</groupId>
            <artifactId>thorntail-maven-plugin</artifactId>
            <executions>
               <execution>
                  <id>package</id>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>io.thorntail</groupId>
            <artifactId>bom-all</artifactId>
            <version>${version.thorntail}</version>
            <scope>import</scope>
            <type>pom</type>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>io.thorntail</groupId>
         <artifactId>jaxrs</artifactId>
      </dependency>
      <dependency>
         <groupId>io.thorntail</groupId>
         <artifactId>keycloak</artifactId>
      </dependency>
   </dependencies>
</project>

Here is our Application class that activates the REST resource:

package com.demo;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class SecuredApplication extends Application {
}

Ans our minimal JAX-RS endpoint:

package com.demo;

import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
 
@Path("/hello")
public class HelloWorldEndpoint {
 
  @GET
  @Produces("text/plain")
  public Response doGet() {
    return Response.ok("Hello from Thorntail!").build();
  }
}

Now, we need to specify in our Thorntail configuration (src/main/resources/project-defaults.yml) that we will be using KEYCLOAK Authentication for our Web application:

thorntail:
  deployment:
    example-keycloak-1.0.war:
      web:
        login-config:
          auth-method: KEYCLOAK
        security-constraints:
          - url-pattern: /*
            methods: [GET]
            roles: [Manager]

The last thing we need to add, in the WEB-INF folder, is the keycloak.json with that contains the JSON descriptor we have just generated.

{
  "realm": "MyRealm",
  "auth-server-url": "http://localhost:8180/auth",
  "ssl-required": "external",
  "resource": "demo-keycloak",
  "credentials": {
    "secret": "86f1644f-b686-4011-8c05-31ca7245f94a"
  },
  "confidential-port": 0
}

Save and deploy the application. If you try to access your application at http://localhost:8080/hello the Keycloak login authentication UI will prompt:

keycloak

Enter your User’s credentials with the “Manager” Role and verify that you can access the pages contained in your application.

That’s all! We have covered how to secure a Microprofile application using Keycloak.

Found the article helpful? if so please follow us on Socials