MicroProfile JWT Auth to secure your applications

Last Updated:  October 11, 2020 | Published: September 6, 2019

In today's microservice architecture security is usually based on the following protocols: OAuth2, OpenID Connect, and SAML. These main security protocols use security tokens to propagate the security state from client to server. This stateless approach is usually achieved by passing a JWT token alongside every client request. For convenient use of this kind of token-based authentication, the Eclipse MicroProfile JWT Auth evolved. The specification ensures, that the security token is extracted from the request, validated and a security context is created out of the extracted information.

Learn more about the MicroProfile JWT Auth specification, its annotations, and how to use it in this blog post.

Specification profile: MicroProfile JWT Auth

  • Current version: 1.1 in MicroProfile
  • GitHub repository
  • Latest specification document
  • Basic use case: Provide JWT token-based authentication for your application

Securing a JAX-RS application

First, we have to instruct our JAX-RS application, that we'll use the JWTs for authentication and authorization. You can configure this with the @LoginConfig annotation:

Once an incoming request has a valid JWT within the HTTP Bearer header, the groups in the JWT are mapped to roles.

We can now limit the access for a resource to specific roles and achieve authorization with the Common Security Annotations (JSR-250) (@RolesAllowed, @PermitAll, @DenyAll):

Furthermore, we can inject the actual JWT token (alongside the Principal) with CDI and inject any claim of the JWT in addition:

In this example, I'm injecting the claim administrator_id and access the claim administrator_level via the JWT token. These are not part of the standard JWT claims but you can add any additional metadata in your token.

Always make sure to only inject the JWT token and the claims to @RequestScoped CDI beans, as you'll get a DeploymentExcpetion otherwise:

HINT: Depending on the application server you'll deploy this example, you might have to first declare the available roles with @DeclareRoles({"admin", "chief", "duke"}).

Required configuration for MicroProfile JWT Auth

Achieving validation of the JWT signature requires the public key. Since MicroProfile JWT Auth 1.1, we can configure this with MicroProfile Config (previously it was vendor-specific). The JWT Auth specification allows the following public key formats:

  • PKCS#8 (Public Key Cryptography Standards #8 PEM)
  • JWK (JSON Web Key)
  • JWKS (JSON Web Key Set)
  • JWK Base64 URL encoded
  • JWKS Base64 URL encoded

For this example, I'm using the PKCS#8 format and specify the path of the .pem file containing the public key in the microprofile-config.properties file:

The configuration of the issuer is also required and has to match the iss claim in the JWT. A valid publicKey.pem file might look like the following:

Using JWTEnizer to create tokens for testing

Usually, an identity provider (e.g. Keycloak) issues a JWT. For quick testing, we can use the JWTenizer tool from Adam Bien. This provides a simple way to create a valid JWT token and generates the corresponding public and private keys. Once you downloaded the jwtenizer.jar you can run it for the first time with the following command:

This will now create a jwt-token.json file in the folder you executed the command above. We can adjust this .json file to our needs and model a sample JWT token:

Once you adjusted the raw jwt-token.json, you can run java -jar jwtenizer.jar again and this second run will now pick the existing .json file for creating the JWT. Alongside the JWT token, the tool generates a microprofile-config.properties file, from which we can copy the public key and paste it to our publicKey.pem file.

Furthermore the shell output of running jwtenizer.jar  contains a cURL command we can use to hit our resources:

With a valid Bearer header you should get the following response from the backend:

You can now adjust the jwt-token.json again and remove the admin group and generate a new JWT. With this generated token you shouldn't be able to get a response from the backend. Rather receive 403 Forbidden, as you are authenticated but don't have the correct role.

For further instructions on how to use this tool, have a look at the README on GitHub or the following video of Adam Bien.

YouTube video for using MicroProfile JWT Auth

Watch the following YouTube video of my Getting started with MicroProfile series to see MicroProfile JWT Auth in action:

You can find the source code with further instructions to run this example on GitHub.

Have fun using MicroProfile JWT Auth,

Phil

>