# Introduction

## Objective

The objective of this project is to provide a *"simple"* example to access a Java Microservice using the [*Open Source Identity and Access Management* Keycloak](https://www.keycloak.org) and [JavaWebToken (JWT)](https://jwt.io).

We want to ...

* ... secure the Microservice with [Authentication](https://en.wikipedia.org/wiki/Authentication)
* ... secure a specific REST Endpoint invocation of the Microservice with [Authorization](https://en.wikipedia.org/wiki/Authorization)
* ... test the access to the Microservice with a [JUnit](https://junit.org/junit5/) test.

The Microservice runs on [OpenLiberty](https://openliberty.io/) and uses [MicroProfile](https://microprofile.io/). The example Microservice is called `Authors` and is from the open sourced [Cloud Native Starter project](https://github.com/IBM/cloud-native-starter).The example doesn't use a frontend UI for the Authentication. The JUnit test will authenticate with the Keycloak REST API.

Here is a 7 minutes [YouTube video](https://youtu.be/fP1_3MkhqG0) about the setup of the example.

[![You Tube Setup](https://img.youtube.com/vi/fP1_3MkhqG0/0.jpg)](https://www.youtube.com/watch?fP1_3MkhqG0)

## Architecture

The `Authors` Microservice application supports a protected login with JWT and the specific REST call `getAuthors` is protected by a specific user role. The image below contains a simplified architecture overview of the example which runs on the local machine, here you see:

* The `JUnit` test and Authors Microservice are running on a `OpenLiberty` server
* The `Authors` Microservice is build with MicroProfile
* The needed `JWT` Key is saved on the OpenLiberty server in the `Authors` Microservice using [MicroProfile configuration](https://www.eclipse.org/community/eclipse_newsletter/2017/september/article3.php)
* The `JUnit` test requests a `bearer token` to access the `Authors` service
* The major configuration information inside `Keycloak`

![](/files/-MB-MOp6hYUj4d9X0Wte)

*Note:* In this example **Keycloak** server is available on **localhost:8282** and Authors Microservice on **OpenLiberty** runs on **localhost:3000**.

A very simplified overview of the test execution to access `Authors` Microservice using `Keycloak`, `OpenLiberty`, `MicroProfile` and `JWT` , is shown in the sequence diagram below.

![](/files/-MB-MOpCgkYSIrTt2OjH)

1. Start the `JUnit` test called `Test_GetAuthors`. The test invokes the private operation `getToken`.
2. Request a bearer token from `Keycloak` using a REST Endpoint (<http://localhost:8282/auth/realms/protocol/openid-connect/token>). The request contains the needed Keycloak data for the authorization as parameters to get the `bearer token`.

   ```java
   formData.param("username", user)
   .param("password", password)
   .param("realm", realm)
   .param("grant_type", grant_type)
   .param("client_id", client_id);
   ```

   That `bearer token` does contain the `Java Web Token`, which is protected with the `RS256 (RSA Signature with SHA-256)`. `RS256` is a [JWT](https://en.wikipedia.org/wiki/JSON_Web_Token) signing algorithm.
3. Proceeding with the test by invoking the private operation `getAuthorAuthorized`.
4. Now the `Authors` REST Endpoint (<http://localhost:3000/api/v1/getAuthor>) is invoked using the bearer token we got from Keycloak, which contains the [JWT](https://en.wikipedia.org/wiki/JSON_Web_Token). The JWT does contain all needed information such as user, role and soon.&#x20;
5. Verifying the JWT by the `Authors` Microservice application, that will be done automatically,, by using the given `RS256 signed Key` for the JWT in our Microservice application on the `OpenLiberty` server. When the provided Key is validated, the JWT can be used to access the REST Endpoint of the Authors Microservice.
6. Now the Endpoint validates, does the `JavaWebToken` contain the right role to access the information?
7. Then the response data data will be compared with the expected value.

## Setup of the example an overview

* [**Keycloak**](https://www.keycloak.org)

  For the setup of [Keycloak](https://www.keycloak.org) we need ...

  1. ... run a local Keycloak Docker image
  2. ... add a [realm](https://www.keycloak.org/docs/latest/getting_started/index.html#creating-a-realm-and-user)
  3. ... import an existing realm configuration with:
     * Realm Keys
     * Client definition
     * Role and Group definition
     * Groups role mapping     &#x20;
  4. ... create a user and add him to the existing group with the role to add the Microservice
* [**OpenLiberty**](https://openliberty.io/) and [**MicroProfile**](https://microprofile.io/)

  For the setup of the Java Microservice with [**OpenLiberty**](https://openliberty.io/) and [**MicroProfile**](https://microprofile.io/) with the [**JUnit**](https://junit.org/junit5/) test, it's useful to understand the steps from the blog post ["Write and execute a JUnit test for a Java Microservice based on MicroProfile and run both in the OpenLiberty development mode"](https://suedbroecker.net/2020/03/04/write-and-execute-a-junit-test-for-a-java-microservice-based-on-mircoprofile-and-run-both-in-the-openliberty-development-mode/).

  We need to ...

  1. ... configure the `server.xml` of OpenLiberty
  2. ... add login and security functionality to the `AuthorsApplication` class
  3. ... secure the REST Endpoint in the `GetAuthor`class
* [**JUnit test**](https://junit.org/junit5/)

  We need to ...

  1. ... use the two-factor authentication to access the `Authors` Microservice
  2. ... use a REST a client to send the requests to the `Authors` Microservice and Keycloak
  3. ... verify `Authors` Microservice response in the JUnit test

## Technologies Used

* [**Jakarta EE**](https://jakarta.ee/)
* [**MicroProfile**](https://microprofile.io/)
* [**OpenLiberty**](https://openliberty.io/)
* [**Keycloak**](https://www.keycloak.org)
* [**Microservices architecture**](https://en.wikipedia.org/wiki/Microservices)
* [**JUnit**](https://junit.org/junit5/)
* [**Java Web Token**](https://de.wikipedia.org/wiki/JSON_Web_Token)
* [**Docker**](https://www.docker.com)
* [**Keycloak**](https://www.keycloak.org)

## Compatibility

This project has been created by using following technical environment:

* Development environment:
  * [**Docker Desktop:**](https://www.docker.com) version 2.3
  * [**MacOS:**](https://www.apple.com/macos/catalina/): 10.15.5 OS Catalina
  * [**Visual Studio Code**](https://code.visualstudio.com) with the [Java extension Pack](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)
* Java project:
  * [**OpenLiberty**](https://openliberty.io): version 20.0.0.6
  * [**Keycloak**](https://www.keycloak.org): version 9.0.2
  * [**MicroProfile**](https://microprofile.io/): version 3.2
  * [**Glassfish**](https://javaee.github.io/glassfish/): version 1.1
  * [**yasson**](https://projects.eclipse.org/projects/ee4j.yasson): version 1.0
  * [**JUnit**](https://junit.org/junit5/): version 5.6.0
  * [**OpenLiberty Maven Plugin**](https://openliberty.io/blog/2019/11/28/dev-mode-liberty-maven-plugin.html): version 3.1
  * [**Apache Maven Compiler Plugin**](https://maven.apache.org/plugins/maven-compiler-plugin/): version 3.1
  * [**Maven Surefire Plugin**](http://maven.apache.org/surefire/maven-surefire-plugin/): version 2.22.2
  * [**Apache CXF MicroProfile Client:**](https://mvnrepository.com/artifact/org.apache.cxf/cxf-rt-rs-mp-client) version 3.3.1
  * [**Maven Java Compiler:**](https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html): version 1.8


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://thomas-suedbroecker.gitbook.io/example-using-keycloak-mp-and-openliberty-locally/master.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
