Authentication in Quarkus

Updated on January 24, 2024
Learning GoalLearn how to build a Quarkus app that uses OpenID Connect for authentication.

In this lab, you will learn:

  • How to build a Quarkus app with Java.
  • How to secure your app and log in with OpenID Connect.
  • How to add a logout feature.

Why Use Quarkus to build Apps?

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.

OpenID Connect (OIDC) is an identity layer built on top of the OAuth 2.0 framework. It allows third-party applications to verify the identity of the end-user and to obtain basic user profile information.

In this lab, you'll learn how to use Java and Quarkus to build a simple app that's secured with OIDC.

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.

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, specify --maven instead of --gradle.

Navigate to the new quarkus folder and run the 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

Then, add the following security properties to src/main/resources/application.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.oidc.IdToken;
import io.quarkus.security.Authenticated;
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;
import org.eclipse.microprofile.jwt.JsonWebToken;
@Path("/hello")
public class GreetingResource {
@Inject
@IdToken
JsonWebToken idToken;
@GET
@Authenticated
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello, " + idToken.getName();
}
}

Restart your app if you stopped it. 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

Implement a Profile Page with Logout

Now that you have the users signing in to Quarkus with the help of Auth0, you probably want to support a user-initiated logout. It is easy to support it with Quarkus OIDC.

First, add the Qute dependency to support HTML templates. If you're using Gradle, modify the build.gradle file:

build.gradle
implementation 'io.quarkus:quarkus-resteasy-reactive-qute'

If you're using Maven, update your pom.xml:

pom.xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-qute</artifactId>
</dependency>

Add a template to render the homepage at src/main/resources/templates/home.html with the following code:

src/main/resources/templates/home.html
<html>
<head>
<title>Quarkus + Auth0</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h2>Quarkus + Auth0 Example</h2>
{#if identity.isAnonymous}
<div>
<p>Hello!</p>
<p>If you're viewing this page then you have successfully configured and started this application.</p>
<p>This example shows you how to use the Quarkus OIDC Authorization
Code Flow in your application.</p>
<p>When you click the profile link below, you will be redirected to login. After you
authenticate, you will be returned to this application.</p>
</div>
{#else}
<div>
<p>Welcome home, <span>{identity.principal.name}</span>!</p>
<p>You have successfully authenticated with Auth0, and have been redirected back to this application.</p>
<p>Here are your user's attributes:</p>
<table class="table table-striped">
<thead>
<tr>
<th>Claim</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{#for claim in claims}
<tr>
<td>{claim.key}</td>
<td>{claim.value}</td>
</tr>
{/for}
</tbody>
</table>
</div>
{/if}
{#if identity.isAnonymous}
<a class="link-opacity-100" href="/hello/profile">Profile</a>
{#else}
<form method="post" action="/logout">
<button id="logout" class="btn btn-danger" type="submit">Logout</button>
</form>
{/if}
</div>
</body>
</html>

Update the src/main/resources/application.properties file to configure logout properties:

src/main/resources/application.properties
quarkus.oidc.end-session-path=oidc/logout
quarkus.oidc.logout.path=/logout
quarkus.oidc.logout.post-logout-path=/hello

Modify GreetingResource.java to add a profile() method and update the hello() method to use the template:

src/main/java/com/okta/app/GreetingResource.java
package com.okta.app;
import io.quarkus.oidc.IdToken;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
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;
import org.eclipse.microprofile.jwt.JsonWebToken;
import java.util.Map;
@Path("/hello")
public class GreetingResource {
@Inject
@IdToken
JsonWebToken idToken;
@Inject
SecurityIdentity securityIdentity;
@Inject
Template home;
@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance hello() {
TemplateInstance instance = home.data("identity", securityIdentity);
return instance;
}
@GET
@Path("/profile")
@Authenticated
@Produces(MediaType.TEXT_HTML)
public TemplateInstance profile() {
TemplateInstance instance = home.data("identity", securityIdentity);
if (idToken.getClaimNames() != null) {
Map<String, Object> claims = idToken.getClaimNames().stream().filter(claim -> idToken.getClaim(claim) != null)
.collect(java.util.stream.Collectors.toMap(name -> name, idToken::getClaim));
instance = instance.data("claims", claims);
}
return instance;
}
}

Stop your Quarkus app using Ctrl+C and start it again. Open a private browsing window, access http://localhost:8080/hello, and click the Profile link. Log in with your Auth0 credentials. After returning to your app, you'll see a welcome message with your email and user attributes. Then, click the Logout button to log out. Pretty cool, huh?

Recap

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

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

Be sure to visit the labs Authorization in Quarkus and Role Based Access Control in Quarkus to learn more about Auth0 security integration in Quarkus Java applications.