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 <vendre@gmail.com>
This commit is contained in:
Kirk True 2022-12-15 15:37:36 -08:00 committed by Manikumar Reddy
parent 8b045dcbf6
commit eb53c4c8c7
2 changed files with 14 additions and 4 deletions

View File

@ -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);
}

View File

@ -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