Quarkus + Angular with Keycloak — Pt2

Ricardo Mello
ITNEXT
Published in
5 min readMar 15, 2023

Discover more on YouTube: If you’re looking for video content on technology, programming, and other topics, check out my YouTube channel! Subscribe to stay updated and learn more about these subjects.

Welcome back! In this article, we will continue the development of our daily-quotes application. If you haven’t read the first part yet, you can access it by clicking here.

The main goal of this article is to implement a REST API with Keycloak that will provide create and list quote endpoints.

Quarkus Application

To create the Quarkus backend service for creating and listing quotes through a REST endpoint, follow these steps:

  1. Go to https://code.quarkus.io/
  2. Configure the project with desired extensions and dependencies
  3. Include the following dependencies:
  • Quarkus RESTEasy JAX-RS
  • Quarkus Security Keycloak

4. Download the project

These dependencies enable REST endpoint creation and integration with Keycloak for authentication and authorization:

img 01 — Quarkus initializer

Creating our project structure

We won’t go into too much detail about the architecture, but we’ll create our application using hexagonal architecture and domain-driven design (DDD) principles. Let’s define some packages as follows:

img 02 — Backend structure

Configuring the Database

To initialize our database, we need to define some variables.

  • Open the application.properties file and set the following values:
quarkus.datasource.db-kind=postgresql 
quarkus.datasource.username=postgres
quarkus.datasource.password=postgres
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres
quarkus.datasource.jdbc.max-size=16
quarkus.hibernate-orm.database.generation = drop-and-create

Notice that we have a running Postgres container, which was defined in the docker-compose.yml file.

Defining our Model

  • For this application, we will have a class named Quote that will represent our model:
public class Quote {
private Long id;
private String message;
private String author;
//getters, setters ..
}

Creating QuoteService

QuoteService is an interface that provides two operations for our model.

  • Here is the implementation:
@ApplicationScoped
@Transactional
public class QuoteServiceImpl implements QuoteService {

@Inject
QuoteRepository quoteRepository;

@Override
public Quote create(Quote quote) {
quoteRepository.persist(quote.toEntity());
return quote;
}

@Override
public List<Quote> findAll() {
return quoteRepository.findAll().stream().map(QuoteEntity::toDomain).toList();
}
}

Creating QuoteController

This class will be responsible for exposing our endpoints through the use of JAX-RS annotations.

  • Here is the initial implementation:
@Path("/quote")
public class QuoteController {

@Inject
QuoteService quoteService;

@POST()
@Produces(MediaType.APPLICATION_JSON)
public QuoteResponse create(Quote quote) {
Quote q = quoteService.create(quote);
return new QuoteResponse(q.getMessage(), q.getAuthor());
}

@GET()
public List<Quote> list() {
return quoteService.findAll();
}
}

Above, we injected the service that will communicate with the repository that does the write and read operations.

Note: I haven’t included all the classes, but you can find the full implementation here.

Running the application

  • Let’s run our application and see the results.
$ ./gradlew quarkusDev
img — 03 Quarkus running

Accessing endpoints

Great job😍! We have created our application and defined the /quote route for accessing our endpoints:

/POST:

img04 — Create new quote using postman

/GET:

img05 — get quote request using postman

Protecting our routes

Great! Our application is now responding on the above two endpoints. Now, let’s protect our routes using Quarkus OpenID Connect (OIDC). As we created a client for our frontend application, we need to create one for the backend as well.

  • Open Keycloak console and create a new client named backend like this:
img06 — New Client added
  • After that, we need to enable authentication for this client:
img07 — Enable authentication
  • Nice! Now, we need to get the client secret to use in our requests:
img08 — Client secret authentication

Changing our Application

  • Open the build.gradle.kts file and add the following Keycloak dependencies:
implementation("io.quarkus:quarkus-oidc")
implementation("io.quarkus:quarkus-keycloak-authorization")
  • Now, let’s define some properties in application.properties:
quarkus.oidc.auth-server-url=http://localhost:8188/realms/daily-quotes
quarkus.oidc.client-id=backend
quarkus.oidc.credentials.secret=secret
quarkus.oidc.tls.verification=none
  • Now, open QuoteController and add the authentication annotation @Authenticated on the create method. It should look like this:
    @POST()
@Authenticated
@Produces(MediaType.APPLICATION_JSON)
public QuoteResponse create(Quote quote) {
quoteService.create(quote);
return new QuoteResponse(quote.getMessage(), quote.getAuthor());
}

Nice 😄! When we restart our server, our endpoint will now be protected, meaning that it is necessary to be authenticated to access this method.

Authentication by Token

In this step, we need to retrieve the client registration that we defined in Keycloak (as shown in img08) and use it as the client secret to request an access token.

  • client_secret:
9IB9glonvC2APFdABNGNZUmNWmOkoYhR
  • Let’s create a post request to get access_token:
img09 — Request to get access_token
  • Now we just send the access_token ou Authorization key:
img10 — Request using bearer token

Conclusion

In this article, we learned how to implement authentication in a Quarkus application using Keycloak. In the next and final part, we will consume these endpoints in an Angular application.

If you have any suggestions, comments, or contributions, please feel free to share them. The complete source code for this project can be found on my GitHub.

Thank you! ❤️

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.

Written by Ricardo Mello

Senior Software Engineer, member of the MongoDB Community Creator passionate about travel and football. Oracle Certified Associate, Java SE 8 Programmer