jwtquarkusquarkus-rest-clientquarkus-qute

Quarkus use both Authorization and Cookie for jwt authorization


I would like to write an app that allows for both RESTful forms of interacting with the data; regular REST CRUD endpoints and a web-ui.

In the past, I have gone the route of implementing much of the functionality of the UI in JS, which would call the regular REST endpoints. This worked fine, but for this application I would like to use Qute to perform much of the basic functionalities of generating page content. However, for me to properly manage the endpoints and ensure proper RBAC control, I need jwt's to be accessed via cookie, rather than normal headers. This seems like it is possible, but not at the same time as my other endpoints that need it in header form.. (Source: https://quarkus.io/guides/security-jwt#microprofile-jwt-configuration )

What might be the best practice here as well? Should I just keep the two apps very separate, and do everything in Javascript?

For reference, on how I am using jwt in code: (example from UI qute generation, but I am using the JWT in the same way for CRUD endpoints)

@Traced
@Slf4j
@Path("/")
@Tags({@Tag(name = "UI")})
@RequestScoped
@Produces(MediaType.TEXT_HTML)
public class Index extends UiProvider {

    @Inject
    Template index;

    @Inject
    JsonWebToken jwt;

    @Inject
    UserService userService;

    @GET
    @PermitAll
    @Produces(MediaType.TEXT_PLAIN)
    public TemplateInstance index(
            @Context SecurityContext securityContext
    ) {
        logRequestContext(jwt, securityContext);

        return index.data("hasToken", hasJwt(jwt));
    }

Relevant extensions:

    implementation 'io.quarkus:quarkus-resteasy-jackson'
    implementation 'io.quarkus:quarkus-resteasy'
    implementation 'io.quarkus:quarkus-smallrye-jwt'
    implementation 'io.quarkus:quarkus-smallrye-jwt-build'
    implementation 'io.quarkus:quarkus-qute'
    implementation 'io.quarkus:quarkus-resteasy-qute'

Attempted Config (using yaml extension), causes jwt processing exception for all rest interactions:

mp:
  jwt:
    token:
      header: Cookie
      cookie: jwt

smallrye:
  jwt:
    always-check-authorization: true

Caused by: org.jose4j.jwt.consumer.InvalidJwtException: JWT processing failed. Additional details: [[17] Unable to process JOSE object (cause: org.jose4j.lang.JoseException: Invalid JOSE Compact Serialization. Expecting either 3 or 5 parts for JWS or JWE respectively but was 23.): function(n){var%20r%2Ce%2Ci%2Ct=this[0]%3Breturn%20arguments.length?(i=m(n)%2Cthis.each(function(e){var%20t%3B1===this.nodeType&&(null==(t=i?n.call(this%2Ce%2CS(this).val()):n)?t=%22%22:%22number%22==typeof%20t?t+=%22%22:Array.isArray(t)&&(t=S.map(t%2Cfunction(e){return%20null==e?%22%22:e+%22%22}))%2C(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&%22set%22in%20r&&void%200!==r.set(this%2Ct%2C%22value%22)||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&%22get%22in%20r&&void%200!==(e=r.get(t%2C%22value%22))?e:%22string%22==typeof(e=t.value)?e.replace(yt%2C%22%22):null==e?%22%22:e:void%200}] It should be noted that the JWT's work fine for me in regular headers, and this error occurred when no cookie or header was set.

I'm on latest Quarkus, 2.4.1.Final

Update: I have tried just swapping to "Cookie" method to test just the ui side with a generated token, and have found that that seems broken... the code was unable to properly parse the token from the cookie. I will, for now, proceed with a full JS implementation, but would still love to hear if this is possible at some point

To reproduce: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/open-qm-base-station and uncomment the lines at https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/blob/main/software/open-qm-base-station/src/main/resources/application.yaml#L70 You will need to publish the library in the parent directory for this to build, and for using most of the REST endpoints it wants a Mongodb instance to talk to.


Solution

  • smallrye.jwt.always-check-authorization=true will ensure that both Authorization and Cookie headers are checked