Skip to content

Commit e3c543f

Browse files
Yoni-Weisbergclaude
authored andcommitted
fix(kafka-connect): call .get() on basicAuth Supplier fields in KafkaConnectApiFactory
`KafkaConnectClientConfig.basicAuthUser()` and `basicAuthPassword()` return `Supplier<String>`, not `String`. Concatenating them without `.get()` embeds the lambda `toString()` into the Authorization header, producing an invalid Basic token and HTTP 401 on every request. Adds `KafkaConnectApiFactoryTest` that verifies the header encodes the actual credentials. Fixes #758. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c84605d commit e3c543f

3 files changed

Lines changed: 76 additions & 1 deletion

File tree

providers/jikkou-provider-kafka-connect/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@
6565
<version>1.21.4</version>
6666
<scope>test</scope>
6767
</dependency>
68+
<dependency>
69+
<groupId>com.squareup.okhttp3</groupId>
70+
<artifactId>mockwebserver</artifactId>
71+
<version>${mockwebserver.version}</version>
72+
<scope>test</scope>
73+
</dependency>
6874
<!-- END dependencies for test -->
6975
</dependencies>
7076

providers/jikkou-provider-kafka-connect/src/main/java/io/jikkou/kafka/connect/api/KafkaConnectApiFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public static KafkaConnectApi create(@NotNull KafkaConnectClientConfig config,
7373

7474
@NotNull
7575
private static String getAuthorizationHeader(KafkaConnectClientConfig config) {
76-
String basicAuthInfo = config.basicAuthUser() + ":" + config.basicAuthPassword();
76+
String basicAuthInfo = config.basicAuthUser().get() + ":" + config.basicAuthPassword().get();
7777
return "Basic " + Encoding.BASE64.encode(basicAuthInfo.getBytes(StandardCharsets.UTF_8));
7878
}
7979
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) The original authors
4+
*
5+
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
6+
*/
7+
package io.jikkou.kafka.connect.api;
8+
9+
import io.jikkou.core.config.Configuration;
10+
import io.jikkou.http.client.ssl.SSLConfig;
11+
import java.io.IOException;
12+
import java.nio.charset.StandardCharsets;
13+
import java.util.Base64;
14+
import mockwebserver3.MockResponse;
15+
import mockwebserver3.MockWebServer;
16+
import org.junit.jupiter.api.AfterAll;
17+
import org.junit.jupiter.api.Assertions;
18+
import org.junit.jupiter.api.BeforeAll;
19+
import org.junit.jupiter.api.DisplayName;
20+
import org.junit.jupiter.api.Test;
21+
22+
class KafkaConnectApiFactoryTest {
23+
24+
private static MockWebServer mockServer = new MockWebServer();
25+
26+
@BeforeAll
27+
static void beforeAll() throws IOException {
28+
mockServer = new MockWebServer();
29+
mockServer.start();
30+
}
31+
32+
@AfterAll
33+
static void afterAll() throws IOException {
34+
mockServer.close();
35+
}
36+
37+
@Test
38+
@DisplayName("Should build Authorization header from actual basicAuth credentials")
39+
void shouldBuildBasicAuthHeaderFromActualCredentials() throws InterruptedException {
40+
// Given
41+
mockServer.enqueue(new MockResponse.Builder()
42+
.code(200)
43+
.addHeader("Content-Type", "application/json")
44+
.body("[]")
45+
.build());
46+
KafkaConnectClientConfig config = new KafkaConnectClientConfig(
47+
"test-cluster",
48+
String.format("http://%s:%s", mockServer.getHostName(), mockServer.getPort()),
49+
AuthMethod.BASICAUTH,
50+
() -> "alice",
51+
() -> "secret",
52+
() -> SSLConfig.from(Configuration.empty()),
53+
false
54+
);
55+
56+
// When
57+
try (KafkaConnectApi api = KafkaConnectApiFactory.create(config)) {
58+
api.listConnectors();
59+
}
60+
61+
// Then
62+
String authorization = mockServer.takeRequest().getHeaders().get("Authorization");
63+
String expectedCredentials = Base64.getEncoder()
64+
.encodeToString("alice:secret".getBytes(StandardCharsets.UTF_8));
65+
// result should correspond to base64 encoded string "alice:secret" prefixed with "Basic"
66+
Assertions.assertEquals("Basic " + expectedCredentials, authorization,
67+
"Authorization header must encode the actual credentials, not the Supplier toString()");
68+
}
69+
}

0 commit comments

Comments
 (0)