2

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.

Snappawapa
  • 1,697
  • 3
  • 20
  • 42

2 Answers2

2

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

Sergey Beryozkin
  • 688
  • 1
  • 4
  • 9
  • Having that flag set and the `mp.jwt.token.header=Cookie` made any rest call (even opening swagger-ui) cause jwt processing errors, any idea? will update with config info – Snappawapa Nov 09 '21 at 02:10
  • I'd like to see a reproducer please – Sergey Beryozkin Nov 10 '21 at 10:32
  • See this PR for more details: https://github.com/smallrye/smallrye-jwt/pull/189/files. Looks like either the `jwt` cookie contains an invalid value - you can trace it in the browser debug/developer console – Sergey Beryozkin Nov 10 '21 at 10:43
  • Updated question with reproducer. The JWT's I have been creating work fine with regular headers. – Snappawapa Nov 10 '21 at 13:20
  • Nevermind, looks like I was just setting the JWT wrong, Works, thanks! – Snappawapa Nov 10 '21 at 17:14
  • I wonder is there a way to support both headers (Authorization and Cookie) but use them individually for different endpoints (to authorize `/hello` only with Authorization header, and authorize `/world` only with Cookie headers)? – E. Dn May 02 '23 at 05:23
0

This configuration work fine for me : smallrye.jwt.always-check-authorization=true

mp.jwt.token.header=Cookie mp.jwt.token.cookie=jwt

And you should send NewCookie with jwt as key and the token as value to the client when user login.