Secure access control in Quarkus web applications

7 April 2022

Access control security for Quarkus web apps

Secure a Quarkus web app with Keycloak using SecuRole®

Quarkus is an ultra-fast Java framework and modern programming platform for developers that replaced Thorntail in the microservices area in 2020. In fact, it is described by Red Hat as the “next-generation Kubernetes-native Java framework”.

To ensure secure programming in Quarkus, it is important to equip the web application with appropriate access control, which is possible using the open source software Keycloak. However, Keycloak by itself is not enough to give programmers the correct and exclusive access to their areas in Quarkus. From a modern security point of view, the separation of authentication and authorisation is recommended. For this purpose, the authorisation framework SecuRole® is a good choice, which is an extension of Keycloak.

 

The profile – short introduction to SecuRole:

  • What is SecuRole®?
    • SecuRole® is an innovative approach for agile role management to overcome limitations of existing approaches and enable fine-grained access control through optional parameters.
  • ZeroTrust Approach from SecuRole® (end-to-end security on authorisation information):
    • SecuRole® provides a secure process to transport authorisation information about users, and the data they are allowed to access, to a client application.
      The client application can then verify every request by checking the signature of the authorising authority. In contrast to transporting authorisation information using a classic OAuth2 or SAML2 enabled SSO system, this provides end-to-end security. In a world where identity providers are becoming more and more interconnected, it is important to have a reliable way of proving a user’s authorisations.
  • Technical Implementation:
    • Transported as a JWT
Giovanni Baruzzi invented SecuRole® technology as an extension to Keycloak, primarily to handle higher numbers of users in web applications. It also simplifies or eliminates the need for provisioning in cloud environments. It can also be used to implement options for fine-grained authorisation in applications.
Let’s take a look at Quarkus and Keycloak first, followed by a brief guide on how to integrate the two:

How to integrate Quarkus & Keycloak?

Setup your Quarkus web application as explained in the following guides:

Once the application and Keycloak are configured, accessing a page protected by Keycloak – when not already logged in – should redirect the user to the login page.

Standard Keycloak login page
Are Quarkus and Keycloak set-up and ready? Then it’s time for SecuRole integration.

Getting the SecuRole

As described above, SecuRole is a signed JWT that contains a lot of information. To manage access to a resource, it is possible to use the annotation @RoleAllowed or to set the property quarkus.security.jaxrs.default-roles-allowed. Both methods require the name of the role.

Quarkus offers a very flexible way to customise the SecurityIdentity. With a SecurityIdentityAugmentor, we can add new information to it and thus add the SecuRole.

Map the attribute in Keycloak

Let’s assume that the SecuRole is stored as a user attribute in Keycloak.

SecuRole saved “userRoles” as a user attribute in Keycloak.
Keycloak offers the possibility to transfer user information to the client applications. This happens by using mappers that will add the information to the access token, the ID token or to the information retrievable from the UserInfo end point. Due to the way it’s built, the SecuRole can become very large. Even having a small set of roles can become problematic, since the tokens are technically saved into cookies, which are limited in size (4kb). In order to avoid data-loss or errors, it’s better to exclusively transmit the SecuRole through the UserInfo endpoint. In our case, Quarkus will call it automatically and save the data in an object that can be injected in a SecurityIdentityAugmentor.
To do so, a mapper has to be defined for the client to authenticate the users:

OIDC mapper configuration page

The configuration of the application should be modified by adding the following:

quarkus:

oidc:

authentication:

user-info-required: true

Now Quarkus will automatically fill the attribute “userinfo” of the SecurityIdentity object by calling the corresponding endpoint, and Keycloak will provide the content of the userRole attribute. At this point, the name of the roles are still not directly accessible, since a SecuRole given by the mapper looks like this; a list of “##”-separated strings:

loginalliance:MUSCA:MUSCA_ACCESS:eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNVVNDQSIsInZlciI6IjEuMC4wIiwibmJmIjoxNjI0NjE0NjU1LCJpc3MiOiJpbnRlbnNpb24gZ21iaCIsInJsZSI6Ik1VU0NBX0FDQ0VTUyIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiNyJ9.EkjuC5ZALxOb8Z-dwCpsmxq7ieMS3bg48BukVG-qJ3qWVvr6F8yMbiKa5T3yHujmyuzzMuJulf7pcY8x4mnBmxvxeA_74GbZ-FEkVN7R3-T7po4Ubl9xMtzWhVQgWoqKv2IsAs3Y2OXtwM7v1E5gOqBH5ExAcZNr3xfczasL8u2GnzPHcYbNkKztxId8cizXPWykKGAwz-STvCCTmSeXlOBK14-V3Zr2kQmqw_cVJsiIS2tBtyHB1oNzddLEj4qpFMMES–v1AFISl8w6pcG-ZuBbXKI0SOrhHebYhQ2Ep-HBtol6zf3a8J9qFNcbtsFkUmSqg86gfYBQ9UzeK9_sw##loginalliance:DEMO:APPLICATION_ACCESS:eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJERU1PIiwidmVyIjoiMS4wLjAiLCJuYmYiOjE2MjQ2MTQ3MDksImlzcyI6ImludGVuc2lvbiBnbWJoIiwicmxlIjoiQVBQTElDQVRJT05fQUNDRVNTIiwicHJtIjoiVGhpcyByb2xlIGlzIGJvdW5kIHRvIHRoZSBlbnZpcm9ubWVudCBvZiBpbnRlbnNpb24gZ21iaCIsImV4cCI6NDc4Mzg0MDI4NywiaWF0IjoxNjI0NjE0NzEzLCJqdGkiOiI5In0.XE0Zp-iSuFhgQZ3Z4wOCg9VPdNtBqfFlimKmr5bS4_orRHDYCdVNaHYpTGzYgjejN8Ad6kM67MziH-PuNckzrv8mKqEFsfy2jq_mW508VYW8iDIkY6BaJ5_kir3E7_DkeUNDs3YUr2w5RWo-bLlr6C0N0tEcPjiWtAi2xn_D6U2mnXlFnMNvuD-fGbfmtlC08zWQOHX_wMkR-WcnSUrtY5gBxcNgzkWVtIVNi1ue9VMfSWbUtoeKL8RKdc0bkGVoGYutA59nLmbr9qyOwjytyW1HVcujwVzBsKrGtVzwHyi142iZTBt765_Gy1V-xEksrZot-CEymD9BCURJPG6UEw##loginalliance:MyProfile:LOGIN:eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNeVByb2ZpbGUiLCJ2ZXIiOiIxLjAuMCIsIm5iZiI6MTYyNDYxNDY1NSwiaXNzIjoiaW50ZW5zaW9uIGdtYmgiLCJybGUiOiJMT0dJTiIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiOCJ9.D5CN-i2EFeZshl8d8oMLFK80-M9jzDPM-qHvjyqtLBlLEmCRyNgJumj-99eExE1ifF9wH2GgHu7FC_QJ6A2Ma1XtZd1eqIJ0-BY6mxylHYBfMHHgA–B58SRz_MCRozNCPM2WtQhFXkCsD6LzzXmBm9GOLasYenHEz5hSRvS_QDeHsjB7Cfy-7rNGBU3enI-V4uY0rlTV8ygwWq6NzjYMzjio6WV18I7HqRbUFFKTj6rEgIBYJIRT5n87QqAOvVaZN-A8i_KSuhRbTqVkLFzUHcNYIqNseDzMTDptOHpHTbXyqQrOKX6GEQ_xkXHNe49duLZg97NfcbJ0y66ustNtw

There is already some information in clear text, but actually, the secured part is contained in the JWT, e.g.:

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNVVNDQSIsInZlciI6IjEuMC4wIiwibmJmIjoxNjI0NjE0NjU1LCJpc3MiOiJpbnRlbnNpb24gZ21iaCIsInJsZSI6Ik1VU0NBX0FDQ0VTUyIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiNyJ9.EkjuC5ZALxOb8Z-dwCpsmxq7ieMS3bg48BukVG-qJ3qWVvr6F8yMbiKa5T3yHujmyuzzMuJulf7pcY8x4mnBmxvxeA_74GbZ-FEkVN7R3-T7po4Ubl9xMtzWhVQgWoqKv2IsAs3Y2OXtwM7v1E5gOqBH5ExAcZNr3xfczasL8u2GnzPHcYbNkKztxId8cizXPWykKGAwz-STvCCTmSeXlOBK14-V3Zr2kQmqw_cVJsiIS2tBtyHB1oNzddLEj4qpFMMES–v1AFISl8w6pcG-ZuBbXKI0SOrhHebYhQ2Ep-HBtol6zf3a8J9qFNcbtsFkUmSqg86gfYBQ9UzeK9_sw

 

 

    1. The first part specifies the used algorithm:
      eyJhbGciOiJSUzI1NiJ9
    2. {
    3. “alg”: “RS256”
      }
    4. Then the payload, which actually contains the name of the role:
      eyJzdWIiOiI5NTczNjUwMzE0NjQ1OTciLCJhdWQiOiJNVVNDQSIsInZlciI6IjEuMC4wIiwibmJmIjoxNjI0NjE0NjU1LCJpc3MiOiJpbnRlbnNpb24gZ21iaCIsInJsZSI6Ik1VU0NBX0FDQ0VTUyIsInBybSI6IlRoaXMgcm9sZSBpcyBib3VuZCB0byB0aGUgZW52aXJvbm1lbnQgb2YgaW50ZW5zaW9uIGdtYmgiLCJleHAiOjQ3ODM4NDAyODcsImlhdCI6MTYyNDYxNDY1NSwianRpIjoiNyJ9
    5. {
    6. “sub”: “957365031464597”,
    7. “aud”: “MUSCA”,
    8. “ver”: “1.0.0”,
    9. “nbf”: 1624614655,
    10. “iss”: “intension gmbh”,
    11. “rle”: “MUSCA_ACCESS”,
    12. “prm”: “This role is bound to the environment of intension gmbh”,
    13. “exp”: 4783840287,
    14. “iat”: 1624614655,
    15. “jti”: “7”

}

  1. Finally the signature:
    EkjuC5ZALxOb8Z-dwCpsmxq7ieMS3bg48BukVG-qJ3qWVvr6F8yMbiKa5T3yHujmyuzzMuJulf7pcY8x4mnBmxvxeA_74GbZ-FEkVN7R3-T7po4Ubl9xMtzWhVQgWoqKv2IsAs3Y2OXtwM7v1E5gOqBH5ExAcZNr3xfczasL8u2GnzPHcYbNkKztxId8cizXPWykKGAwz-STvCCTmSeXlOBK14-V3Zr2kQmqw_cVJsiIS2tBtyHB1oNzddLEj4qpFMMES–v1AFISl8w6pcG-ZuBbXKI0SOrhHebYhQ2Ep-HBtol6zf3a8J9qFNcbtsFkUmSqg86gfYBQ9UzeK9_sw

Check signature

It is now possible to extract the role out of the payload and verify the signature of the JWT to be sure that it has not been manipulated. To do this, it is possible to use the Nimbus JOSE + JWT library that permits an easy check of the signature against a provided public key.

This article was about: Make access to web applications like Quarkus more secure with Keycloak and its SecuRole® extension.

If you have any questions, get in touch with us through our contact form.