Skip to content

Part 2: Running Fine-grained Keycloak Authorization Feature with Quarkus

Overview

The quarkus-keycloak-authorization extension is based on quarkus-oidc and provides a policy enforcer that enforces access to protected resources based on permissions managed by Keycloak and currently can only be used with the Quarkus OIDC service applications.

 It is important to realize that it is the Bearer Token authentication mechanism which does the authentication and creates a security identity – while the quarkus-keycloak-authorization extension is responsible for applying a Keycloak Authorization Policy to this identity based on the current request path and other policy settings.

Keycloak Termes:

  • Resource : object which users will be accessing or performing the action on ( like Rest URL / File)
  • Auth scopes : Actions that users can perform on the specific object
    • The Magic Mapping is done in the Quarkus application.properties file
    • Quarkus application.properties map HTTP Methods to the scopes in Keycloak Authorization Services’ i.e. map HTTP GET to view scope and HTTP POST to create scope:
      • Scope scopes:create is mapped to HTTP Post for resource account ( paths.2.methods.1 )
      • Scope scopes:view is mapped to HTTP Get for resource account ( see paths.3.methods.2 )

Quarkus application.properties Content

# Enable Policy Enforcement
quarkus.keycloak.policy-enforcer.enable=true
quarkus.keycloak.policy-enforcer.lazy-load-paths=false

# Enables policy enforcement for a path
quarkus.keycloak.policy-enforcer.paths.1.path=/accounts
quarkus.keycloak.policy-enforcer.paths.1.methods.1.method=GET
quarkus.keycloak.policy-enforcer.paths.1.methods.1.scopes=scopes:viewall

quarkus.keycloak.policy-enforcer.paths.2.path=/account
quarkus.keycloak.policy-enforcer.paths.2.methods.1.method=POST
quarkus.keycloak.policy-enforcer.paths.2.methods.1.scopes=scopes:create

quarkus.keycloak.policy-enforcer.paths.3.path=/account/*
quarkus.keycloak.policy-enforcer.paths.3.methods.1.method=DELETE
quarkus.keycloak.policy-enforcer.paths.3.methods.1.scopes=scopes:delete
quarkus.keycloak.policy-enforcer.paths.3.methods.2.method=GET
quarkus.keycloak.policy-enforcer.paths.3.methods.2.scopes=scopes:view
quarkus.keycloak.policy-enforcer.paths.3.methods.3.method=PUT
quarkus.keycloak.policy-enforcer.paths.3.methods.3.scopes=scopes:manage

# /q/dev/ enables DEV UI in development mode [ /q/dev/ ]  - we don't need to secure this path
# Note: Without this entry DEV UI isn't working at all in an Keycloak Authoriztation Environment
quarkus.keycloak.policy-enforcer.paths.4.path=/q/*
quarkus.keycloak.policy-enforcer.paths.4.enforcement-mode=DISABLED
  • Policies : Resource protection using fine-grained authorization policies and different access control mechanisms
  • Permission : Mapping actually occur here

Keycloak also provides fine-grained authorization services. This helps organizations to manage permissions for all their services from the Keycloak admin console and gives them the power to define exactly the policies they need.

Clone Github Project

# git clone https://github.com/hhutzler/quarkus-keycloak-authorization-sample

Prerequistes

  • Keycloak server is running on Port 8280 and RBAC realms was sucessfully imported

How it works

To create an acoount via an Http POST a user needs to a have the admin role and the Account-Create Permission must map the following

  • Role: Admin
  • Resource res:account ( maps to URL /account )
  • Path /accounts and Scope scopes:create are mapped to the POST Methode ( see application.properties )
  • Apply Policy: Admin ( maps to to Admin Role )

Quarkus Application Properties Mapping ( see application.properties )

quarkus.keycloak.policy-enforcer.paths.1.path=/accounts
quarkus.keycloak.policy-enforcer.paths.1.methods.1.method=POST
quarkus.keycloak.policy-enforcer.paths.1.methods.1.scopes=scopes:create

Keyclock Setup

Keyclok Setup is described more in detail in following article

You have to options here to prepare the Keyclaok instance

  1. Run all a full Keycloak Database Import by importing Master and RBAC realm
    • Read Chapter 3: Quick Keycloak Setup by running a full database import
    • The above import imports all users, realm and clients
    • You are able to run Quarkus Code and Angular code without changing passwords and secrets. The Code runs out of the box.
  2. Run a Manual Keycloak Setup by reading
    • Setup Angular Client: Chapter 1: Keycloak Setup for Angular Frontend Client
    • Setup Quarkus Client : Chapter 2: Keycloak Setup for Quarkus Backend
    • You need to change passwords / secrets

Deploy the Quarkus App

Clone project

$ git clone https://github.com/hhutzler/quarkus-keycloak-authorization-sample

$ cd quarkus-keycloak-authorization-sample

Validate full DB import Script 
$ ls imports
full-db-export.json

Validate Curl test script 
$ ls scripts
curl-test.sh
 

Validate application.properties file

Start Quarkus Application

D:\dev\Quarkus\Keycloak\keycloak-authorization-sample> mvn   compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] --------< org.acme:security-keycloak-authorization-quickstart >---------
[INFO] Building security-keycloak-authorization-quickstart 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ security-keycloak-authorization-quickstart ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ security-keycloak-authorization-quickstart ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- quarkus-maven-plugin:2.5.0.Final:dev (default-cli) @ security-keycloak-authorization-quickstart ---
[INFO] Invoking org.apache.maven.plugins:maven-resources-plugin:2.6:testResources) @ security-keycloak-authorization-quickstart
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\dev\Quarkus\Keycloak\keycloak-authorization-sample\src\test\resources
[INFO] Invoking org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile) @ security-keycloak-authorization-quickstart
[INFO] Nothing to compile - all classes are up to date
Listening for transport dt_socket at address: 5005
2022-02-04 13:52:33,957 INFO  [io.qua.oid.dep.dev.OidcDevConsoleProcessor] (build-8) OIDC Dev Console: discovering the provider metadata at http://localhost:8280/auth/realms/RBAC/.well-known/openid-configuration
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2022-02-04 13:52:36,243 INFO  [org.key.ada.aut.PolicyEnforcer] (Quarkus Main Thread) Paths provided in configuration.

2022-02-04 13:52:37,055 INFO  [io.quarkus] (Quarkus Main Thread) security-keycloak-authorization-quickstart 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.5.0.Final) started in 5.051s. Listening on: http://localhost:8080
2022-02-04 13:52:37,057 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2022-02-04 13:52:37,062 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, keycloak-authorization, oidc, resteasy, resteasy-jackson, security, smallrye-context-propagation, vertx]
2022-02-04 13:53:58,368 INFO  [org.key.ada.KeycloakDeployment] (executor-thread-0) Loaded URLs from http://localhost:8280/auth/realms/RBAC/.well-known/openid-configuration

--
Tests paused
Press [r] to resume testing, [o] Toggle test output, [h] for more options>

Keycloak Setup

Authorization Scopes

Scopes Setup

Resources

Account Resource
Accounts Resource

Policies

Superadmin Policy
Admin Policy
Agent Policy
Delete Account Permission
ss

Permissions

Delete Account Permission
Manage Account Permission
View Account Permission
View All Accounts Permission

Explore Rest API

  • Invoke Dev UI on localhost:8080/q/dev
  • Goto RESTEasy Reactive -> List Endpoints
Select List Endpoints
Explore Rest APi

Test Rest API with curl scripts

Rest API TESTRequest TypeScriptScript Param1:
Admin user
Script Param 2
Specific UserId
Vertx
Ret- code
Keycloak
Ret-Code
Get all realm usersGET./quarkus_GET_getAllUsers.sh superadmin200200
GETtestadmin200200
GETtestagent200200
GETtestuser403
Get a single User with a valid UserIDGET./quarkus_GET_getUser.shsuperadmind0f151cb-4a39-4cd5-b419-9949065a3eb9200200
GETtestadmind0f151cb-4a39-4cd5-b419-9949065a3eb9200200
GETtestagentd0f151cb-4a39-4cd5-b419-9949065a3eb9200200
GETtestuserd0f151cb-4a39-4cd5-b419-9949065a3eb9403
Get a single User with an invalid UserIDGET./quarkus_GET_getUser.sh testadmind0f151cb200404
Delete single User with an in valid UserIDDELETE./quarkus_DELETE_deleteUser.shsuperadmin3c4d463f-86c6-46cf-aa35-cf3aa8d97244200204
DELETEtestadmin3c4d463f-86c6-46cf-aa35-cf3aa8d97244403
DELETEtestagent3c4d463f-86c6-46cf-aa35-cf3aa8d97244403
DELETEtestuser3c4d463f-86c6-46cf-aa35-cf3aa8d97244403
Enable a single User with a valid UserIDPUT./quarkus_PUT_enableUser.shsuperadmin7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99200204
PUTtestadmin7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99200204
PUTtestagent7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99403
PUTtestuser7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99403
Disable a single User with a valid UserIDPUT./quarkus_PUT_disableUser.shsuperadmin7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99200204
PUTtestadmin7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99200204
PUTtestagent7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99403
PUTtestuser7b7b84e7-00c5-4921-a4ed-7ad0fe78ba99403

Run Permission Evalution for certain Users

UserEvaluation Results
testuser

testagent
testadmin
superadmin

About Secrets

As we run a full database import secrets should work and all commands should run out of the box. If you your are running a realm import you may need to regenerate an new Screct.

After regenerating a new screct you must fix the following secret values in your

application.properties file too !

quarkus.oidc.credentials.secret=0a32b2ad-7b58-4c5b-bffe-7d3673fe70a3

quarkus_GET_getUser.sh

$  grep -i SECRET  quarkus_GET_getUser.sh
SECRET=0a32b2ad-7b58-4c5b-bffe-7d3673fe70a3

JWT Token

  • JWT Payload used by this sample

Testing with DEV UI

Invoke Dev UI on localhost:8080/q/dev

  • Click on Provider Keycloak

Login as testuser

Test URL

  • Use /accounts as service path
  • click on With Access Token
  • HTTP request should return status 200

Reference:

Published inOIDCQuarkus

Be First to Comment

Leave a Reply