Categories
Java Quarkus Swagger

Handling Quarkus Security with React via Swagger

When you come to defining security in your project, there’s always two points to consider: how to secure the app, and how to handle security from a frontend(whether it’s web ui, mobile or other types).

We already created some basic API and consumed it with Swagger on your React app. It’s now time to define security and authentication method.

This article covers:

  1. Define simple JWT security on Quarkus backend
  2. Use Quarkus OpenAPI annotations to define authentication method
  3. Authenticate user from React app via Swagger

Other articles of this Series:

  1. Build, run and deploy React app with Quarkus
  2. Setting up Swagger with Quarkus and React
  3. This article

Initial setup

This article requires either having a Quarkus project that already has endpoints and OpenAPI enabled, as well as React setup. You can use the final result of the previous article by cloning next branch:

git clone --single-branch --branch feature/swagger-complete https://github.com/quarkifynet/quarkus-react.git && cd quarkus-react

If you want to see final version of this article, use next command:

git clone --single-branch --branch feature/security-complete https://github.com/quarkifynet/quarkus-react.git && cd quarkus-react

Add simple Security

First of all, you need to have some security present in your project.

Use git checkout feature/security to bypass this section

JWT

For this article, we gonna use JWT auth because it’s probably more popular option.

If you don’t know how to do it, you can visit our article about simple jwt token auth. Follow this guide and get back once you have it ready.

Besides new TokenUtils and TokenService from the guide above, we added two more lines to our User object:

@Entity
public class User extends PanacheEntity {
    public String name;
    public String email;
    public String password; // Use e.g Bcrypt to encrypt password, don't store it as plain text :)
    @JsonbTransient
    @OneToMany
    public List<JobPost> posts;
    @JsonbTransient
    @OneToMany
    public List<JobProposal> proposals;
}

And also modified our UserResource to following:

Now we have super simplified user registration and login processes.

We also changed JobPostResource to store user which invokes the method and @RolesAllowed("User") annotation for all the methods to guard it for only registered users(full class):

@Context
SecurityContext securityContext;

@POST
@RolesAllowed("User")
@Transactional
public JobPost submit(JobPost post) {
    final String email = securityContext.getUserPrincipal().getName();
    post.user = User.find("email", email).firstResult();
    post.persistAndFlush();
    return post;
}

Checkout with next command to apply all these changes to code:

git checkout feature/security

Quarkus annotations for security

I like this Quarkus and React series because it really shows how simple it is to setup Quarkus. As in previous article, we only need to add few lines of code. Specifically, we’ll create Application instance that will have Swagger annotations.

Let me explane how it works.

  1. We declare @OpenAPIDefinition annotation that aggregates some more annotations along the way. This annotation will be read on the build and all the metadata will be put into OpenAPI schema.
  2. @Info is not related to our topic, but it’s always good to specify what is this API about, whether this will read frontend developer, or maybe dozen of hundreds of other developers struggling to integrate their solution with your service
  3. Next, in a @Components scope we specify one @SecurityScheme, this scheme describes the type of security(HTTP), type of scheme(bearer), and format of this bearer(JWT). This line only describes that we have such security under the belt, but that doesn’t mean that we use it.
  4. Finally, @SecurityRequirement specifies what security do we use. This annotation refers securitySchemeName in @SecurityScheme

The code above, basically, says “Hey, send me a Authorization: Bearer ${TOKEN} in a header and I’ll verify it.

Authenticate user from React app via Swagger

Now that we have all the backend parts ready, it’s time to use authentication from the React app. For this, we will create a simple auth form with login and register functionality.

In short, this component shows super simple registration or authentication form, you can switch between them via a checkbox. Once the user hit Submit button, we do request to the backend: if it’s registration we submit user body if it’s login, we submit few attributes and receive a token, which we then store into local storage under id_token. It also calls callback to the main screen once you logged it(instead of attaching redux library).

Networking.js also upgraded a little bit. Now we have security object, that is set by default:

static getDefaultSecurity = () => {
  let token = localStorage.getItem("id_token");
  return token == null ? {} : {
    securities: {
      authorized: {
        bearerAuth: {
          value: token
        }
      }
    }
  }
}

static exec = ({
                 endpoint,
                 attributes,
                 data,
                 success,
                 failure = res => console.log('failed on api call: ' + res),
                 security = this.getDefaultSecurity()
               }) => {
  this.client.then(
      client => endpoint(client)(attributes, {...data, ...security}),

You can find full class here.

This will set bearer auth if we have one, empty otherwise. We set this value on each call, this way we’ll always have a fresh token.

And, finally, App.js also changed a little bit:

We now have isAuthenticated() method, once the app is loaded, we check if the user is authenticated or not, and if he’s not, we show Auth view:

isAuthenticated() ? ...
: 
<div>
<Auth authCallback={() => window.location.reload(false)}/>
</div>

When callback fires, we just reload a page

Test

Start both React and Quarkus with next commands:

./mvnw quarkus:dev
# Other terminal
cd ./src/main/webapp && npm start

Go to http://localhost:3000/ and look at the new login screen

I’m really open for design contribution 🙂 As long as it’s won’t harm simplicity

Click the Register checkbox, and click submit. As you can see, we already have filled out test account data.

After you see success message, click the checkbox and Submit button again. You’ll see list of available posts:

Write something in input at Create new job section and click Submit Job.

As a result, you’ll se Submitted by: test sign. Which means, firstly, that it identified us, and, secondly, our security working

In conclusion

Swagger is a really handy tool. Not only it will help you simplify API, but it will help you handle security with a few additional lines of code.

After this article, you already have a toolbelt large enough to start working with React and Quarkus at the same time. But there’s a lot more to cover, for example, GraphQL.

By the way, thank you for reading! Currently, it’s the most popular series on this website. Let me know below in the comments what will be a great continuation of this series. I would love to write a topic that people interested in

Weekly Quarkus Newsletter

Our newsletter saves your precious time with curated list of top news, guides and articles of the week

Marketing by

2 replies on “Handling Quarkus Security with React via Swagger”

Leave a Reply

Connect with




Your email address will not be published. Required fields are marked *