This is an automated email from the ASF dual-hosted git repository. manikumar pushed a commit to branch KAFKA-14496-fix-oauth-encoder in repository https://gitbox.apache.org/repos/asf/kafka.git
commit eb53c4c8c7e5eb1e8a39139a1f7d3e0d1860fe67 Author: Kirk True <[email protected]> AuthorDate: Thu Dec 15 15:37:36 2022 -0800 KAFKA-14496: Wrong Base64 encoder used by OIDC OAuthBearerLoginCallbackHandler The OAuth code to generate the Authentication header was incorrectly using the URL-safe base64 encoder. For client IDs and/or secrets with dashes and/or plus signs would not be encoded correctly, leading to the OAuth server to reject the credentials. This change uses the correct base64 encoder, per RFC-7617. Co-authored-by: Endre Vig <[email protected]> --- .../internals/secured/HttpAccessTokenRetriever.java | 3 ++- .../internals/secured/HttpAccessTokenRetrieverTest.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetriever.java b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetriever.java index 78917de6f1e..2e61449304d 100644 --- a/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetriever.java +++ b/clients/src/main/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetriever.java @@ -344,7 +344,8 @@ public class HttpAccessTokenRetriever implements AccessTokenRetriever { clientSecret = sanitizeString("the token endpoint request client secret parameter", clientSecret); String s = String.format("%s:%s", clientId, clientSecret); - String encoded = Base64.getUrlEncoder().encodeToString(Utils.utf8(s)); + // Per RFC-7617, we need to use the *non-URL safe* base64 encoder. See KAFKA-14496. + String encoded = Base64.getEncoder().encodeToString(Utils.utf8(s)); return String.format("Basic %s", encoded); } diff --git a/clients/src/test/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetrieverTest.java b/clients/src/test/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetrieverTest.java index a193545fd38..5086a1dab29 100644 --- a/clients/src/test/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetrieverTest.java +++ b/clients/src/test/java/org/apache/kafka/common/security/oauthbearer/internals/secured/HttpAccessTokenRetrieverTest.java @@ -173,10 +173,19 @@ public class HttpAccessTokenRetrieverTest extends OAuthBearerTest { @Test public void testFormatAuthorizationHeader() throws IOException { - String expected = "Basic " + Base64.getUrlEncoder().encodeToString(Utils.utf8("id:secret")); + assertAuthorizationHeader("id", "secret"); + } - String actual = HttpAccessTokenRetriever.formatAuthorizationHeader("id", "secret"); - assertEquals(expected, actual); + @Test + public void testFormatAuthorizationHeaderEncoding() throws IOException { + // See KAFKA-14496 + assertAuthorizationHeader("SOME_RANDOM_LONG_USER_01234", "9Q|0`8i~ute-n9ksjLWb\\50\"AX@UUED5E"); + } + + private void assertAuthorizationHeader(String clientId, String clientSecret) throws IOException { + String expected = "Basic " + Base64.getEncoder().encodeToString(Utils.utf8(clientId + ":" + clientSecret)); + String actual = HttpAccessTokenRetriever.formatAuthorizationHeader(clientId, clientSecret); + assertEquals(expected, actual, String.format("Expected the HTTP Authorization header generated for client ID \"%s\" and client secret \"%s\" to match", clientId, clientSecret)); } @Test
