Role Based Access Control in Quarkus

Updated on January 24, 2024
Learning GoalLearn how to build a Quarkus app that uses Role-Based Access Control (RBAC) for authorization.

In this lab, you will learn:

  • How to build a Quarkus app with Java.
  • How to secure your app with OAuth and OpenID Connect.
  • How to use Auth0 Actions to convert Auth0 roles to Quarkus roles.
  • How to secure methods with Quarkus's @RolesAllowed.

Why Quarkus?

Quarkus is a Kubernetes-native Java framework tailored for GraalVM and the JVM, with the goal of making Java the leading platform in Kubernetes and serverless environments, while offering developers a framework to address a wider range of distributed application architectures.

Role-Based Access Control refers to the idea of assigning permissions to users based on their role within an organization. It offers a simple, manageable approach to access management that is less error prone than assigning permissions to users individually.

In this lab, you'll learn how to use Java and Quarkus to build a simple app that's secured with Quarkus OpenID Connect (OIDC) support. You'll also learn how to convert your Auth0 roles to Quarkus roles.

Lab Setup

Set up a development environment

  • Use your favorite text editor or IDE. We recommend using IntelliJ IDEA.
  • Ensure that you have Java 17+ installed in your system. You can easily install it using SDKMAN!.
  • Windows commands in this lab are written for PowerShell.

Create an Auth0 Account

If you already have an Auth0 account, you can log in to your tenant and continue to the next step.

Otherwise, sign up for a free Auth0 account.

During the sign-up process, you create something called an Auth0 Tenant, where you configure your use of Auth0.

Once you sign in, Auth0 takes you to the Auth0 Dashboard, where you can configure and manage Auth0 assets, such as applications, APIs, connections, and user profiles.

Set up the Auth0 CLI

If you are not familiar with the Auth0 CLI, you can follow the "Auth0 CLI Basics" lab to learn how to build, manage, and test your Auth0 integrations from the command line.

There are different ways to install the Auth0 CLI, depending on your operating system.

LOADING...

Test the Auth0 CLI installation

Run the following command to show in the terminal the version of your Auth0 CLI installation:

COMMAND
auth0 --version

You should see the following output:

auth0 version <version-number> <hash>

Install the Quarkus CLI

Use SDKMAN to install the Quarkus CLI:

COMMAND
curl -s "https://get.sdkman.io" | bash
sdk install quarkus

For more installation options, see the Quarkus documentation.

Install HTTPie (Optional)

HTTPie is a command-line HTTP and API testing client that can be used instead of cURL for sending API requests. You can install it using the official installation guide if you are interested.

Creating a Quarkus App

Create a new app with OIDC support:

COMMAND
quarkus create app com.okta.app:quarkus --extension="resteasy-reactive,oidc" --gradle

For Maven support, pass the option --maven instead of --gradle.

Navigate to the new quarkus folder and run your Quarkus app:

QUARKUS CLI
GRADLE
MAVEN
quarkus dev

The application will pull a Keycloak image, and once you see the message "Listening on: http://localhost:8080" in the logs, open the http://localhost:8080/hello URL in your favorite browser. You should see the following message:

Hello from RESTEasy Reactive

Secure Quarkus with OIDC

In a terminal, connect the Auth0 CLI to your Auth0 tenant.

COMMAND
auth0 login
Visit the Access Your Tenant section of the "Auth0 CLI Basics" lab to learn more about the auth0 login command.

Then, run the command below to create an OIDC application:

LOADING...

Copy the domain, client ID, and client secret of your app and paste it into the following input boxes:

When you enter a value in the input fields present on this page, any code snippet that uses such value updates to reflect it. Using the input fields makes copying and pasting code as you follow along easy.

For security, these configuration values are stored in memory and only used locally. They are gone as soon as you refresh the page! As an extra precaution, you should use values from an Auth0 test application instead of a production one.

Create a .env file in the root folder of the project for the sensitive security properties, so you don't accidentally check it into source control:

.env
QUARKUS_OIDC_AUTH_SERVER_URL=https://AUTH0-DOMAIN/
QUARKUS_OIDC_CLIENT_ID=AUTH0-CLIENT-ID
QUARKUS_OIDC_CREDENTIALS_SECRET=AUTH0-CLIENT-SECRET

Now, update the content of the src/main/resources/application.properties file to configure additional security properties:

src/main/resources/application.properties
quarkus.oidc.authentication.scopes=openid,profile,email
quarkus.oidc.application-type=web-app
quarkus.oidc.authentication.redirect-path=/callback
quarkus.oidc.authentication.restore-path-after-redirect=true

Add user information to the hello() method in GreetingResource.java:

src/main/java/com/okta/app/GreetingResource.java
package com.okta.app;
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/hello")
public class GreetingResource {
@Inject
SecurityIdentity securityIdentity;
@GET
@Authenticated
public String hello() {
return "Hello, " + securityIdentity.getPrincipal().getName();
}
}

Open a browser and navigate to http://localhost:8080/hello. Log in with your Auth0 credentials or sign up as a new user and you should see your email displayed. If you don't have a user in your tenant yet, you can sign up with Google or create a new user with the Auth0 CLI:

COMMAND
auth0 users create

Use a Login Action to Add Roles

To add a new Administrator role, use the Auth0 CLI:

COMMAND
auth0 roles create --name Administrator --description "Administrators"

Find your user ID with auth0 users search and enter the email address you used to log in previously.

Assign the role you just created to your user. You must use quotes around the user-id in the command below.

COMMAND
auth0 users roles assign "<user-id>"

Create a Login Action:

COMMAND
auth0 actions create --name "Add Roles" --trigger post-login

When the editor opens, use the following code in the onExecutePostLogin() function. This will set a https://quarkus.example.com/roles claim in both the ID and access token.

ACTION
exports.onExecutePostLogin = async (event, api) => {
const namespace = 'https://quarkus.example.com';
if (event.authorization) {
api.idToken.setCustomClaim('preferred_username', event.user.email);
api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
}
};
You can change the text editor used for editing templates, rules, and actions. Set the environment variable EDITOR to your preferred editor. For example export EDITOR="nano"

Save the file using your editor. List the available actions with the following command:

COMMAND
auth0 actions list

Save your action ID into an environment variable and deploy the action you just created:

LOADING...

Once the action is deployed, you must attach it to the login flow. You can do this with Auth0 Management API for Actions:

LOADING...

Update application.properties to let Quarkus know the claim name containing the roles, that you defined in your action.

application.properties
quarkus.oidc.roles.role-claim-path="https://quarkus.example.com/roles"
The path to the roles claim is in double quotes because the claim is namespace qualified.

Update your GreetingsResource.java class to add the roles() method returning Quarkus roles in the response:

src/main/java/com/okta/app/GreetingResource.java
package com.okta.app;
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
@Inject
SecurityIdentity securityIdentity;
@GET
@Authenticated
public String hello() {
return "Hello, " + securityIdentity.getPrincipal().getName();
}
@GET
@Produces(MediaType.TEXT_PLAIN)
@Authenticated
@Path("roles")
public String roles() {
return securityIdentity.getRoles().toString();
}
}

Navigate again to http://localhost:8080/hello and you should see your email displayed. Navigate to http://localhost:8080/hello/roles and you should see your roles displayed.

This example proves that your Auth0 roles have been included in your ID token and assigned by Quarkus to the SecurityIdentity.

Secure Methods with @RolesAllowed

Now that you have Quarkus roles mapped from Auth0 roles, you can use Quarkus's @RolesAllowed annotation to secure methods.

Secure the roles() method by requiring the Administrator role:

src/main/java/com/okta/app/GreetingResource.java
@GET
@Produces(MediaType.TEXT_PLAIN)
@RolesAllowed("Administrator")
@Path("roles")
public String roles() {
return securityIdentity.getRoles().toString();
}

The roles() method requires you to be authenticated and have an Administrator role. Log in again in a private window, and confirm you can access http://localhost:8080/hello/roles successfully.

This example demonstrates how Quarkus roles can be used for RBAC (Role-Based Access Control).

Verify Roles are in your Access Token

To prove that roles have been added to your access token, create a new access token with the Auth0 CLI:

COMMAND
auth0 test token -a https://AUTH0-DOMAIN/api/v2/ -s openid

Select any available client when prompted. You will be prompted to open a browser window and log in with a user credential.

Paste the access token value in the following field so that you can use it to test your resource server:

Then, use it to access your /hello/roles endpoint. You will receive an HTTP 302 response, which means OIDC is redirecting you to log in.

HTTPIE
UNIX
WINDOWS
http :8080/hello/roles "Authorization: Bearer AUTH0-ACCESS-TOKEN"

This is because the application does not support OIDC Bearer Token Authentication yet (only OIDC Authorization Code Flow). Update your application.properties and set application-type to hybrid:

application.properties
quarkus.oidc.application-type=hybrid

Now access the /hello/roles endpoint again: it should display the roles.

Create a new method profile() in GreetingResource.java:

src/main/java/com/okta/app/GreetingResource.java
@Inject
JsonWebToken accessToken;
@GET
@Path("/profile")
@RolesAllowed("profile")
@Produces(MediaType.TEXT_PLAIN)
public Map<String, Object> profile() {
return accessToken.getClaimNames().stream()
.collect(java.util.stream.Collectors.toMap(name -> name, accessToken::getClaim));
}

Update application.properties to declare the scope claim also as a role claim:

application.properties
quarkus.oidc.roles.role-claim-path="https://quarkus.example.com/roles",scope

If you try to access the /hello/profile endpoint, it won't work:

HTTPIE
UNIX
WINDOWS
http :8080/hello/profile Authorization:"Bearer AUTH0-ACCESS-TOKEN"

This is because your access token wasn't created with the profile scope. Create a new access token with this scope:

COMMAND
auth0 test token -a https://AUTH0-DOMAIN/api/v2/ -s openid,profile

Paste the access token value in the following field so that you can use it to test your application:

Try again with the updated access token:

HTTPIE
UNIX
WINDOWS
http :8080/hello/profile Authorization:"Bearer AUTH0-ACCESS-TOKEN"

You will see the access token's claims in your terminal. Congratulations!

Stop your Quarkus app using Ctrl+C.

Recap

In this lab, you learned how to build a Quarkus app with Java, secure it with Quarkus OIDC, and add Auth0 roles so they're converted to Quarkus roles. It's pretty sweet how you can create and configure a Quarkus app with Auth0 so fast!

quarkus create app com.okta.app:quarkus --extension="resteasy-reactive,oidc" --gradle
auth0 apps create \
--name "Quarkus App" \
--description "Quarkus App Example" \
--type regular \
--callbacks "http://localhost:8080/callback" \
--logout-urls "http://localhost:8080" \
--reveal-secrets

Be sure to visit the labs Authentication in Quarkus and Authorization in Quarkus to learn more about Auth0 security integration in Quarkus Java applications. To level-up your authorization game, check out this tutorial about how to use OpenFGA with Quarkus.