diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 9cbb5b6717837..2c6c91e907af2 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -112,7 +112,7 @@ 2.6.5.Final 2.2.3.Final 3.9.1 - 4.5.32 + 4.5.33 4.5.14 4.4.16 4.1.5 @@ -221,7 +221,7 @@ 1.0.11 0.28.0.RELEASE - 1.23.1 + 1.23.2 3.8.7 diff --git a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java index 44405ea2fc33e..6b13893b36601 100644 --- a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java +++ b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java @@ -845,6 +845,10 @@ public static JsonObject decodeJwtContent(String jwt) { public static String getJwtContentPart(String jwt) { StringTokenizer tokens = new StringTokenizer(jwt, "."); + if (!tokens.hasMoreTokens()) { + // An empty or delimiter-only token has no parts at all. + return null; + } // part 1: skip the token headers tokens.nextToken(); if (!tokens.hasMoreTokens()) { diff --git a/extensions/oidc-common/runtime/src/test/java/io/quarkus/oidc/common/runtime/OidcCommonUtilsTest.java b/extensions/oidc-common/runtime/src/test/java/io/quarkus/oidc/common/runtime/OidcCommonUtilsTest.java index 5599523c5ad51..74291bccedfa2 100644 --- a/extensions/oidc-common/runtime/src/test/java/io/quarkus/oidc/common/runtime/OidcCommonUtilsTest.java +++ b/extensions/oidc-common/runtime/src/test/java/io/quarkus/oidc/common/runtime/OidcCommonUtilsTest.java @@ -1,6 +1,7 @@ package io.quarkus.oidc.common.runtime; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import java.net.URI; import java.nio.charset.StandardCharsets; @@ -194,6 +195,37 @@ public static String getJwtContentPart(String jwt) { return encodedContent; } + @Test + public void testDecodeJwtContentWithNoParts() { + // An empty or delimiter-only bearer token has zero StringTokenizer tokens. + // These used to throw NoSuchElementException out of getJwtContentPart, which + // escaped BearerAuthenticationMechanism as a non-AuthenticationFailedException + // and surfaced as HTTP 500 instead of a 401 challenge. + assertNull(OidcCommonUtils.decodeJwtContent("")); + assertNull(OidcCommonUtils.decodeJwtContent(".")); + assertNull(OidcCommonUtils.decodeJwtContent("..")); + assertNull(OidcCommonUtils.decodeJwtContent("...")); + assertNull(OidcCommonUtils.decodeJwtContent("....")); + } + + @Test + public void testGetJwtContentPartWithNoParts() { + assertNull(OidcCommonUtils.getJwtContentPart("")); + assertNull(OidcCommonUtils.getJwtContentPart(".")); + assertNull(OidcCommonUtils.getJwtContentPart("..")); + assertNull(OidcCommonUtils.getJwtContentPart("...")); + } + + @Test + public void testGetJwtContentPartStillRejectsWrongPartCounts() { + // Regression guard: the new zero-token check must not change how tokens + // with the wrong number of parts are treated. + assertNull(OidcCommonUtils.getJwtContentPart("onlyonepart")); + assertNull(OidcCommonUtils.getJwtContentPart("two.parts")); + assertNull(OidcCommonUtils.getJwtContentPart("a.b.c.d")); + assertEquals("b", OidcCommonUtils.getJwtContentPart("a.b.c")); + } + private static JsonObject decodeAsJsonObject(String encodedContent) { try { return new JsonObject(base64UrlDecode(encodedContent)); diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java index 6d9982708ea64..0685507217795 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java @@ -239,11 +239,17 @@ public static String decodeJwtContentAsString(String jwt) { public static JsonObject decodeJwtHeaders(String jwt) { StringTokenizer tokens = new StringTokenizer(jwt, "."); + if (!tokens.hasMoreTokens()) { + return null; + } return decodeAsJsonObject(tokens.nextToken()); } public static String decodeJwtHeadersAsString(String jwt) { StringTokenizer tokens = new StringTokenizer(jwt, "."); + if (!tokens.hasMoreTokens()) { + return null; + } return base64UrlDecode(tokens.nextToken()); } diff --git a/independent-projects/resteasy-reactive/pom.xml b/independent-projects/resteasy-reactive/pom.xml index a614616deea30..5b1a9459a168d 100644 --- a/independent-projects/resteasy-reactive/pom.xml +++ b/independent-projects/resteasy-reactive/pom.xml @@ -58,7 +58,7 @@ 3.1.0 3.21.6 2.13.9 - 4.5.32 + 4.5.33 5.5.6 1.0.0.Final 2.21.4 diff --git a/independent-projects/vertx-utils/pom.xml b/independent-projects/vertx-utils/pom.xml index 6a0086a214b51..dd4586beaca1c 100644 --- a/independent-projects/vertx-utils/pom.xml +++ b/independent-projects/vertx-utils/pom.xml @@ -17,7 +17,7 @@ 3.6.1.Final - 4.5.32 + 4.5.33