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.
- Type -> https://code.quarkus.io/ and create a project similar these:
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:
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
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 ..
}
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:
@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 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
Accessing endpoints
Very good 😍! we create our application and define the /quote route for access.
/POST:
/GET:
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:
After that, we need to enable authentication for this client:
Nice! Now, we need to get the client secret to use in our requests.
Changing our Application
Open build.gradle.kts and add Keycloak dependencies:
implementation("io.quarkus:quarkus-oidc")
implementation("io.quarkus:quarkus-keycloak-authorization")
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
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());
}
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
Let’s create a post request to get access_token:
Now we just send the access_token ou Authorization key:
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)