diff --git a/.github/workflows/ci-actions-incremental.yml b/.github/workflows/ci-actions-incremental.yml index 075756ff53753..7aeccb5397657 100644 --- a/.github/workflows/ci-actions-incremental.yml +++ b/.github/workflows/ci-actions-incremental.yml @@ -305,6 +305,9 @@ jobs: shell: bash # Despite the pre-calculated run_jvm flag, GIB has to be re-run here to figure out the exact submodules to build. run: ./mvnw $COMMON_MAVEN_ARGS install -Dsurefire.timeout=1200 -pl !integration-tests/gradle -pl !integration-tests/maven -pl !integration-tests/devtools ${{ matrix.java.maven_args }} ${{ needs.build-jdk11.outputs.gib_args }} + - name: Clean Gradle temp directory + shell: bash + run: devtools/gradle/gradlew --stop && rm -rf devtools/gradle/gradle-extension-plugin/build/tmp - name: Prepare failure archive (if maven failed) if: failure() shell: bash diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 0e5fa50195da4..ec8e4d0c883a6 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -44,7 +44,7 @@ 1.6.0 2.5.1 3.1.1 - 3.0.1 + 3.0.3 2.1.15 1.3.4 2.0.1 @@ -90,9 +90,9 @@ 1.15 1.5.1 5.6.0.Final - 1.0.0.CR10 + 1.0.0.Final 6.2.0.Final - 6.0.6.Final + 6.0.7.Final 5.12.0.Final 1.1.1.Final 1.12 @@ -165,7 +165,7 @@ 4.3.3 1.2.1 2.17.0 - 0.33.9 + 0.33.10 3.14.9 5.2.1 0.1.0 diff --git a/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc b/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc index 5173080046f1a..69f6f207f1018 100644 --- a/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc @@ -304,6 +304,10 @@ Additionally, the extension should produce a `io.quarkus.oidc.deployment.devserv Please follow the link:dev-ui[Dev UI] tutorial as well as check the `extensions/oidc/deployment` sources for more ideas. +== Non Application Root Path Considerations + +This document refers to the `http://localhost:8080/q/dev` Dev UI URL in several places where `q` is a default non application root path. If you customize `quarkus.http.root-path` and/or `quarkus.http.non-application-root-path` properties then replace `q` accordingly, please see https://quarkus.io/blog/path-resolution-in-quarkus/[Path Resolution in Quarkus] for more information. + == References * link:dev-ui[Dev UI] diff --git a/docs/src/main/asciidoc/security-openid-connect.adoc b/docs/src/main/asciidoc/security-openid-connect.adoc index ef43599e55ab2..9e70568abac12 100644 --- a/docs/src/main/asciidoc/security-openid-connect.adoc +++ b/docs/src/main/asciidoc/security-openid-connect.adoc @@ -31,7 +31,7 @@ To complete this guide, you need: == Architecture -In this example, we build a very simple microservice which offers three endpoints: +In this example, we build a very simple microservice which offers two endpoints: * `/api/users/me` * `/api/admin` diff --git a/docs/src/main/asciidoc/tika.adoc b/docs/src/main/asciidoc/tika.adoc index 8e2196b165741..b76940061ec8a 100644 --- a/docs/src/main/asciidoc/tika.adoc +++ b/docs/src/main/asciidoc/tika.adoc @@ -11,19 +11,6 @@ This guide explains how your Quarkus application can use https://tika.apache.org https://tika.apache.org/[Apache Tika] is a content analysis toolkit which is used to parse the documents in PDF, Open Document, Excel and many other well known binary and text formats using a simple uniform API. Both the document text and properties (metadata) are available once the document has been parsed. -[NOTE] -==== -If you are planning to run the application as a native executable and parse documents that may have been created with charsets different than the standard ones supported in Java such as `UTF-8` then you should configure Quarkus to get the native image generator include all the charsets available to the JVM: -[source,xml] ----- - - native - true - ----- -==== - - == Prerequisites To complete this guide, you need: diff --git a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/OidcClientConfig.java b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/OidcClientConfig.java index 832a012974abb..975168eaf5abb 100644 --- a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/OidcClientConfig.java +++ b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/OidcClientConfig.java @@ -159,6 +159,12 @@ public void setExpiresInProperty(String expiresInProperty) { @ConfigItem(defaultValue = "true") public boolean earlyTokensAcquisition = true; + /** + * Custom HTTP headers which have to be sent to the token endpoint + */ + @ConfigItem + public Map headers; + public Optional getId() { return id; } @@ -198,4 +204,12 @@ public Optional getRefreshTokenTimeSkew() { public void setRefreshTokenTimeSkew(Duration refreshTokenTimeSkew) { this.refreshTokenTimeSkew = Optional.of(refreshTokenTimeSkew); } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } } diff --git a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java index 63bf8b9805211..27978c01c4908 100644 --- a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java +++ b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java @@ -88,6 +88,11 @@ public Uni get() { HttpRequest request = client.postAbs(tokenRequestUri); request.putHeader(HttpHeaders.CONTENT_TYPE.toString(), HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED.toString()); + if (oidcConfig.headers != null) { + for (Map.Entry headerEntry : oidcConfig.headers.entrySet()) { + request.putHeader(headerEntry.getKey(), headerEntry.getValue()); + } + } if (clientSecretBasicAuthScheme != null) { request.putHeader(AUTHORIZATION_HEADER, clientSecretBasicAuthScheme); } else if (clientJwtKey != null) { diff --git a/extensions/oidc/deployment/src/main/resources/dev-templates/provider.html b/extensions/oidc/deployment/src/main/resources/dev-templates/provider.html index aa40f306396c6..b6e82843f42f1 100644 --- a/extensions/oidc/deployment/src/main/resources/dev-templates/provider.html +++ b/extensions/oidc/deployment/src/main/resources/dev-templates/provider.html @@ -11,6 +11,9 @@ var port = {config:property('quarkus.http.port')}; {#if info:oidcApplicationType is 'service'} + var devRoot = '{devRootAppend}'; + var encodedDevRoot = devRoot.replaceAll("/", "%2F"); + {#if info:oidcGrantType is 'implicit' || info:oidcGrantType is 'code'} var accessToken; var idToken; @@ -81,13 +84,13 @@ {#if info:oidcGrantType is 'implicit'} window.location.href = '{info:authorizationUrl}' + "?client_id=" + '{info:clientId}' - + "&redirect_uri=" + "http%3A%2F%2Flocalhost%3A" + port + "%2Fq%2Fdev%2Fio.quarkus.quarkus-oidc%2Fprovider" + + "&redirect_uri=" + "http%3A%2F%2Flocalhost%3A" + port + encodedDevRoot + "%2Fio.quarkus.quarkus-oidc%2Fprovider" + "&scope=openid&response_type=token id_token&response_mode=query&prompt=login" + "&nonce=" + makeid(); {#else} window.location.href = '{info:authorizationUrl}' + "?client_id=" + '{info:clientId}' - + "&redirect_uri=" + "http%3A%2F%2Flocalhost%3A" + port + "%2Fq%2Fdev%2Fio.quarkus.quarkus-oidc%2Fprovider" + + "&redirect_uri=" + "http%3A%2F%2Flocalhost%3A" + port + encodedDevRoot + "%2Fio.quarkus.quarkus-oidc%2Fprovider" + "&scope=openid&response_type=code&response_mode=query&prompt=login" + "&nonce=" + makeid(); {/if} @@ -166,7 +169,7 @@ localStorage.removeItem('authorized'); window.location.assign('{info:logoutUrl??}' - + "?post_logout_redirect_uri=" + "http%3A%2F%2Flocalhost%3A" + port + "%2Fq%2Fdev%2Fio.quarkus.quarkus-oidc%2Fprovider"); + + "?post_logout_redirect_uri=" + "http%3A%2F%2Flocalhost%3A" + port + encodedDevRoot + "%2Fio.quarkus.quarkus-oidc%2Fprovider"); } function exchangeCodeForTokens(code){ @@ -176,7 +179,7 @@ client: '{info:clientId}', clientSecret: '{info:clientSecret}', authorizationCode: code, - redirectUri: "http://localhost:" + port + "/q/dev/io.quarkus.quarkus-oidc/provider" + redirectUri: "http://localhost:" + port + devRoot + "/io.quarkus.quarkus-oidc/provider" }, function(data, status){ var tokens = JSON.parse(data); @@ -229,7 +232,6 @@ return token; } } - {/if} {/if} diff --git a/extensions/tika/deployment/src/main/java/io/quarkus/tika/deployment/TikaProcessor.java b/extensions/tika/deployment/src/main/java/io/quarkus/tika/deployment/TikaProcessor.java index 182abf341a5cc..d4ff2af0c0607 100644 --- a/extensions/tika/deployment/src/main/java/io/quarkus/tika/deployment/TikaProcessor.java +++ b/extensions/tika/deployment/src/main/java/io/quarkus/tika/deployment/TikaProcessor.java @@ -26,6 +26,7 @@ import io.quarkus.deployment.annotations.ExecutionTime; import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.NativeImageEnableAllCharsetsBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceDirectoryBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; @@ -87,6 +88,11 @@ public void registerPdfBoxResources(BuildProducer echoTokenNonStandardResponseWithoutHeader() { + return tokensWithoutHeader.getTokens().onFailure(OidcClientException.class) + .transform(t -> new WebApplicationException(401)); } @GET diff --git a/integration-tests/oidc-client-wiremock/src/main/resources/application.properties b/integration-tests/oidc-client-wiremock/src/main/resources/application.properties index 33370bbd44517..d7f48a4442734 100644 --- a/integration-tests/oidc-client-wiremock/src/main/resources/application.properties +++ b/integration-tests/oidc-client-wiremock/src/main/resources/application.properties @@ -18,6 +18,19 @@ quarkus.oidc-client.non-standard-response.grant.refresh-token-property=refreshTo quarkus.oidc-client.non-standard-response.grant.expires-in-property=expiresIn quarkus.oidc-client.non-standard-response.grant-options.password.username=alice quarkus.oidc-client.non-standard-response.grant-options.password.password=alice +quarkus.oidc-client.non-standard-response.headers.X-Custom=XCustomHeaderValue + +quarkus.oidc-client.non-standard-response-without-header.auth-server-url=${keycloak.url} +quarkus.oidc-client.non-standard-response-without-header.discovery-enabled=false +quarkus.oidc-client.non-standard-response-without-header.token-path=/non-standard-tokens +quarkus.oidc-client.non-standard-response-without-header.client-id=quarkus-app +quarkus.oidc-client.non-standard-response-without-header.credentials.secret=secret +quarkus.oidc-client.non-standard-response-without-header.grant.type=password +quarkus.oidc-client.non-standard-response-without-header.grant.access-token-property=accessToken +quarkus.oidc-client.non-standard-response-without-header.grant.refresh-token-property=refreshToken +quarkus.oidc-client.non-standard-response-without-header.grant.expires-in-property=expiresIn +quarkus.oidc-client.non-standard-response-without-header.grant-options.password.username=alice +quarkus.oidc-client.non-standard-response-without-header.grant-options.password.password=alice quarkus.oidc-client.refresh.auth-server-url=${keycloak.url} quarkus.oidc-client.refresh.discovery-enabled=false diff --git a/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java b/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java index a8aef8f8c2f1f..93a509926d7e5 100644 --- a/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java +++ b/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java @@ -36,6 +36,7 @@ public Map start() { .withBody( "{\"access_token\":\"access_token_1\", \"expires_in\":4, \"refresh_token\":\"refresh_token_1\"}"))); server.stubFor(WireMock.post("/non-standard-tokens") + .withHeader("X-Custom", matching("XCustomHeaderValue")) .withRequestBody(matching("grant_type=password&username=alice&password=alice")) .willReturn(WireMock .aResponse() diff --git a/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java b/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java index 7d4c45df61bd5..f5a955b8549a4 100644 --- a/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java +++ b/integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java @@ -61,6 +61,13 @@ public void testEchoTokensNonStandardResponse() { .body(equalTo("access_token_n refresh_token_n")); } + @Test + public void testEchoTokensNonStandardResponseWithoutHeader() { + RestAssured.when().get("/frontend/echoTokenNonStandardResponseWithoutHeader") + .then() + .statusCode(401); + } + @Test public void testEchoTokensRefreshTokenOnly() { RestAssured.given().queryParam("refreshToken", "shared_refresh_token") diff --git a/integration-tests/tika/pom.xml b/integration-tests/tika/pom.xml index 3e5c814054ff8..39cf63be151d0 100644 --- a/integration-tests/tika/pom.xml +++ b/integration-tests/tika/pom.xml @@ -99,10 +99,6 @@ native - - - true -