quarkusgraalvmquarkus-oidc

Quarkus JWT authentication doesn't work as a native app


I created a new Quarkus app using the following command:

mvn io.quarkus:quarkus-maven-plugin:1.13.7.Final:create \
    -DprojectGroupId=com.okta.rest \
    -DprojectArtifactId=quarkus \
    -DclassName="com.okta.rest.quarkus.HelloResource" \
    -Dpath="/hello" \
    -Dextensions="smallrye-jwt"

Then, I modified the generated HelloResource to print out the user's name.

package com.okta.rest.quarkus;

import io.quarkus.security.Authenticated;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
import java.security.Principal;

@Path("/hello")
public class HelloResource {

    @GET
    @Path("/")
    @Authenticated
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext context) {
        Principal userPrincipal = context.getUserPrincipal();
        return "Hello, " + userPrincipal.getName() + "!";
    }

}

To make this work with Okta, I added a couple of properties to application.properties:

mp.jwt.verify.publickey.location=https://dev-1309757.okta.com/oauth2/default/v1/keys
mp.jwt.verify.issuer=https://dev-1309757.okta.com/oauth2/default

I fixed the HelloResourceTest so it expects a 401 now.

package com.okta.rest.quarkus;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class HelloResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/hello")
          .then()
             .statusCode(401);
    }

}

Then, I ran ./mvnw quarkus:dev. I'm able to generate a valid access token using OIDC Debugger and access this API using HTTPie.

http :8080/hello Authorization:"Bearer $TOKEN"

Response is:

HTTP/1.1 200 OK
Content-Length: 28
Content-Type: text/plain;charset=UTF-8

Hello, matt.raible@okta.com!

However, if I build it as a native image using ./mvnw package -Pnative and try to run it, I'm unable to access the API.

I'm not sure if the Unable to get GraalVM version error is something to be worried about when building.

[INFO] --- quarkus-maven-plugin:1.13.7.Final:build (default) @ quarkus ---
[INFO] [org.jboss.threads] JBoss Threads version 3.2.0.Final
[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building native image source jar: /Users/mraible/graalvm-java/quarkus/target/quarkus-1.0.0-SNAPSHOT-native-image-source-jar/quarkus-1.0.0-SNAPSHOT-runner.jar
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /Users/mraible/graalvm-java/quarkus/target/quarkus-1.0.0-SNAPSHOT-native-image-source-jar/quarkus-1.0.0-SNAPSHOT-runner.jar
[ERROR] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Unable to get GraalVM version from the native-image binary.
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] /Users/mraible/.sdkman/candidates/java/21.1.0.r11-grl/bin/native-image ...

Running ./target/quarkus-1.0.0-SNAPSHOT-runner starts everything just fine.

2021-06-14 16:19:10,616 INFO  [io.quarkus] (main) quarkus 1.0.0-SNAPSHOT native (powered by Quarkus 1.13.7.Final) started in 0.020s. Listening on: http://0.0.0.0:8080
2021-06-14 16:19:10,617 INFO  [io.quarkus] (main) Profile prod activated.
2021-06-14 16:19:10,617 INFO  [io.quarkus] (main) Installed features: [cdi, mutiny, resteasy, security, smallrye-context-propagation, smallrye-jwt, vertx, vertx-web]

However, I'm unable to access the /hello endpoint with a valid access token.

$ http :8080/hello Authorization:"Bearer $TOKEN"
HTTP/1.1 401 Unauthorized
content-length: 0
www-authenticate: Bearer {token}

If I stop the native app and run ./mvnw quarkus:dev, the same command works.

$ http :8080/hello Authorization:"Bearer $TOKEN"
HTTP/1.1 200 OK
Content-Length: 28
Content-Type: text/plain;charset=UTF-8

Hello, matt.raible@okta.com!

Solution

  • Please enable the quarkus-smallrye-jwt TRACE logging to see why the tokens are rejected. And indeed, as you have also found out, https protocol needs to be enabled in the native image, which can be done, as you have shown :-), by adding <quarkus.native.additional-build-args>--enable-url-protocols=https</quarkus.native.additional-build-args> to the native profile's properties in pom.xml.

    This PR will ensure adding it manually won't be required.

    thanks