diff --git a/content/blog/secure-quarkus-api-with-keycloak.md b/content/blog/secure-quarkus-api-with-keycloak.md new file mode 100644 index 0000000..c533040 --- /dev/null +++ b/content/blog/secure-quarkus-api-with-keycloak.md @@ -0,0 +1,354 @@ +--- +title: "Secure a Quarkus API with Keycloak" +date: 2020-03-17T00:00:00+02:00 +opensource: +- Keycloak +- Quarkus +--- + +[Quarkus](https://quarkus.io/) is a Java stack that is Kubernetes native, lightweight and fast. +Quarkus can be used for any type of backend development, including API-enabled backends. +[Keycloak](https://www.keycloak.org/) is an open source Single Sign On solution that can be used to secure APIs. + +In this article, I'm describing how to secure a Quarkus API with Keycloak using JWT tokens. + +## Preparation + +As a pre-requisite, install [Maven](https://maven.apache.org/), [jq](https://stedolan.github.io/jq/download/) and [jwt-cli](https://github.com/mike-engel/jwt-cli#installation). + +Create a Quarkus project using either [code.quarkus.io](https://code.quarkus.io/) or Maven. Example shown below with Maven. + +```sh +mvn io.quarkus:quarkus-maven-plugin:1.2.0.Final:create \ + -DprojectGroupId=fr.itix.test \ + -DprojectArtifactId=secured-rest \ + -DclassName="fr.itix.test.SecuredResource" +``` + +Enter the created directory. + +```sh +cd secured-rest +``` + +## Install and configure Keycloak + +Download Keycloak and install it locally. + +```sh +curl -L -o keycloak.tgz https://downloads.jboss.org/keycloak/9.0.0/keycloak-9.0.0.tar.gz +tar zxvf keycloak.tgz +mv keycloak-* keycloak +``` + +Create the Keycloak admin user. + +```sh +./keycloak/bin/add-user-keycloak.sh -u admin -r master -p secret +``` + +Start the Keycloak server. + +```sh +nohup ./keycloak/bin/standalone.sh -Djboss.socket.binding.port-offset=100 & +``` + +Quickly, the Keycloak admin console should be available at [localhost:8180/auth/admin/](http://localhost:8180/auth/admin/). The login is **admin** and password is **secret**. + +In the rest of this section, we will configure Keycloak with: + +* a realm named **demo** +* a client named **quarkus-app** +* a user named **jdoe** +* two groups named **user** and **admin** + +Authenticate as admin on Keycloak using the **kcadm** CLI. + +```sh +./keycloak/bin/kcadm.sh config credentials --server http://localhost:8180/auth --realm master --user admin --client admin-cli --password secret +``` + +Create a realm named **demo**. + +```sh +./keycloak/bin/kcadm.sh create realms -s realm=demo -s enabled=true -o +``` + +Create a client named **quarkus-app**. + +```sh +./keycloak/bin/kcadm.sh create clients -r demo -s 'clientId=quarkus-app' -s 'standardFlowEnabled=false' -s 'directAccessGrantsEnabled=true' -s 'serviceAccountsEnabled=true' -s 'clientAuthenticatorType=client-secret' -s 'secret=s3cr3t' +``` + +The framework used by Quarkus to implement security is based on [Eclipse MicroProfile - JWT RBAC Security (MP-JWT)](https://www.eclipse.org/community/eclipse_newsletter/2017/september/article2.php) and requires a claim named **groups** to hold the group membership. + +So, we need to create a **custom protocol mapper** to map the user's client role mapping to the **groups** claim. + +```sh +CLIENT_ID="$(./keycloak/bin/kcadm.sh get clients -r demo -q clientId=quarkus-app |jq -r '.[0].id')" + +./keycloak/bin/kcadm.sh create clients/$CLIENT_ID/protocol-mappers/models -r demo -f - < src/main/resources/application.properties <