Secure REST APIs in Quarkus using Basic Auth

Secure REST APIs in Quarkus using Basic Auth

Securing APIs is an essential part of any serious web applications. Quarkus offers many useful extensions to secure REST APIs in multiple ways. Supported mechanisms are basic auth, JWT, etc. In this article, we go through how to secure REST APIs in Quarkus using Basic Auth.

In the last three articles we’ve built a User REST service, integrated with MySQL, and added Swagger and Swagger UI. The last piece of the puzzle is to secure those APIs. And this post is all about that.

The aim is to restructure and secure the following APIs,

  • GET /v1/users – accessible to users with ADMIN or USER role
  • GET /v1/users/:id – accessible to users with ADMIN or USER role
  • POST /v1/users – open (not secured)
  • PUT /v1/users/:id – accessible to users with ADMIN role only
  • DELETE /v1/users/:id – accessible to users with ADMIN role only

As you can see, we don’t change POST /v1/users endpoint. Because we want new users to signUp.

The authentication mechanism for this example is Basic Auth. So a user has to enter his username and password to interact with any APIs (except sign up). That means the existing user entity ought to be adjusted accordingly (more on that later).

Besides that, we will define two roles USER and ADMIN respectively. This allows us to limit user modification and deletion to the ADMIN role only.

Implementation

Now that we are clear with the problem space, let’s write some code 🙂

Adding quarkus-security-jpa dependency

As mentioned before Quarkus supports multiple authentication mechanisms. There is a dedicated library for each as follows,

ExtensionDescription
quarkus-elytron-security-properties-fileProvides support for simple properties files that can be used for testing security. This supports both embedding user info in application.properties and standalone properties files.
quarkus-security-jpaProvides support for authenticating via JPA.
quarkus-elytron-security-jdbcProvides support for authenticating via JDBC.
quarkus-elytron-security-oauth2Provides support for OAuth2 flows using Elytron. This extension will likely be deprecated soon and replaced by a reactive Vert.x version.
quarkus-smallrye-jwtA MicroProfile JWT implementation that provides support for authenticating using Json Web Tokens. This also allows you to inject the token and claims into the application as per the MP JWT spec.
quarkus-oidcProvides support for authenticating via an OpenID Connect provider such as Keycloak.
quarkus-keycloak-authorizationProvides support for a policy enforcer using Keycloak Authorization Services.
Source: https://quarkus.io/guides/security

To implement Basic Auth with database support (JPA since we use Hibernate), we have to add quarkus-security-jpa dependency to the project.

Changing the User entity

We need to introduce three additional fields to the User entity. These fields are: Username, Password, and Role. For that, let’s change the User entity.

Since we don’t want to store plain raw passwords in the database, we call the hash function in the setPassword method.

Note that the password field is annotated with @JsonbTransient. That’s to prevent returning password hash in the response body. Quarkus uses Jsonb library, and the annotations differ from Jackson. Using @JsonIgnore doesn’t work.

Adding security annotation to User entity

We need to inform Quarkus about the authentication details. So it knows which table and which fields to query on authentication. That sounds complicated, but it’s not. All we have to do is to add some annotations.

  • @UserDefinition indicates User.java is the user entity for authentication
  • @Username defines this field will be used as a username by Quarkus
  • @Password defines this field will be used as a password by Quarkus

Updating UserDTO

There is a static class in UserController called UserDto. It’s used for user creation and edition. This DTO should be updated accordingly to support username, password, and role fields.

Securing the UserController

The next step is to annotate the UserController and secure them. Following what mentioned before we can annotate each endpoint accordingly as follows,

Add authentication to Swagger UI

By now everything should work, except Swagger UI. That needs to be modified to support the authentication AKA login. For that, we have to add the final annotation on top of UserController as follows,

The annotation shows the security name and schema.

Now if you run the project and open localhost:8080/swagger-ui, you should see the REST APIs are secured. And to interact with them you need to have username and password.

You can find some predefined user in this file,

https://github.com/kasramp/quarkus-rest-example/blob/master/docker/db_tables/user.sql

And as usual, the complete implementation is available on GitHub at this link,

https://github.com/kasramp/quarkus-rest-example

That’s all for this post, I hope you have learned how to secure REST APIs in Quarkus using Basic Auth.

Inline/featured images credits