DEV Community

Cover image for Quarkus + Angular with Keycloak — Pt2
Ricardo Mello
Ricardo Mello

Posted on

Quarkus + Angular with Keycloak — Pt2

On this article, we 'll continue the development of our daily-quotes application. If you haven’t seen the first part, click here.

The main goal here is to implement REST API with Keycloak that will provide create and list quote endpoints.


Quakus Application

The Quarkus backend service will be responsible for create and list quotes through a REST endpoint. To get started, let’s create the project and provide some dependencies.

Image description

Creating our project structure
I won’t go deep about architecture, therefore, we 'll be create our application using the hexagonal architecture and DDD. Let’s define some packages like this:

Image description

Configuring database
Let’s define some variable to initialize our database. Open application.properties and set:

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
Enter fullscreen mode Exit fullscreen mode

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

Defining our model
This application will have a class named Quote that will represents our model.

public class Quote {
    private Long id;
    private String message;
    private String author;

   //getters, setters ..
}
Enter fullscreen mode Exit fullscreen mode

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();
    }
}
Enter fullscreen mode Exit fullscreen mode

Creating QuoteController
This class will be responsible for exposing our endpoints:

@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();
    }
}
Enter fullscreen mode Exit fullscreen mode

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

Note: I didn’t mention 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

Enter fullscreen mode Exit fullscreen mode

Image description

Accessing endpoints
Very good 😍! we create our application and define the /quote route for access.

/POST:

Image description

/GET:

Image description

Protecting our routes
Very well! our application is responding on the above two endpoints. Now let’s protect our routes using Quarkus OpenID Connect (OIDC). As like we created our frontend client, we need to do it for backend.

Creating Keycloak Client
Open Keycloak console and create a new client named backend like this:

Image description

After that, we need to enable authentication for this client:

Image description

Nice! Now, we need to get the client secret to use in our requests.

Image description

Changing our Application
Open build.gradle.kts and add Keycloak dependencies:

implementation("io.quarkus:quarkus-oidc")
implementation("io.quarkus:quarkus-keycloak-authorization")
Enter fullscreen mode Exit fullscreen mode

Now, let's define some properties on 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
Enter fullscreen mode Exit fullscreen mode

As you can see, we are saying to our application that it needs to connect to Keycloak using a client-id named backend.

Now, open QuoteController and put authentication annotation on create method. It should be like this:

    @POST()
    @Authenticated
    @Produces(MediaType.APPLICATION_JSON)
    public QuoteResponse create(Quote quote) {
        quoteService.create(quote);
        return new QuoteResponse(quote.getMessage(), quote.getAuthor());
    }
Enter fullscreen mode Exit fullscreen mode

Nice 😄!! When we restart our server, we 'll see that now our endpoint is protected, so it's necessary to be authenticated to access this method.

Authentication by Token

In this step, we need to get the client registration that we defined in the Keycloak (img08) and use it on client_secret to request access_token:

client_secret:

9IB9glonvC2APFdABNGNZUmNWmOkoYhR

Enter fullscreen mode Exit fullscreen mode

Let’s create a post request to get access_token:

Image description

Now we just send the access_token ou Authorization key:

Image description


Conclusion
On this article we saw how to implement an authenticate Quarkus application. On the third and last post, we 'll consume those endpoints in Angular application.

Feel comfortable to suggest, comment and contribute with this project. You can find the complete source here on my GitHub.

Thanks ❤️

Top comments (0)