Skip to content

[improve][client] Implement tls_client_auth for AuthenticationOAuth2#25538

Open
izumo27 wants to merge 8 commits intoapache:masterfrom
izumo27:add_tls-client-auth
Open

[improve][client] Implement tls_client_auth for AuthenticationOAuth2#25538
izumo27 wants to merge 8 commits intoapache:masterfrom
izumo27:add_tls-client-auth

Conversation

@izumo27
Copy link
Copy Markdown
Contributor

@izumo27 izumo27 commented Apr 16, 2026

Motivation

Currently, the Client Credentials Flow in AuthenticationOAuth2 supports only authentication using client_secret.
This PR adds tls_client_auth using a certificate.
https://datatracker.ietf.org/doc/rfc8705/

Modifications

Added TlsClientAuthFlow class for the flow using a certificate.

Verifying this change

This change added tests and can be verified as follows:

  • Added tests for tls_client_auth
  • Modify existing tests for cilent_sercre

Does this pull request potentially affect one of the following parts:

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

Copy link
Copy Markdown
Member

@lhotari lhotari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! I added some review comments.

@izumo27 izumo27 force-pushed the add_tls-client-auth branch 2 times, most recently from fabfb85 to 587959e Compare April 17, 2026 15:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends Pulsar’s OAuth2 client-credentials authentication to support RFC 8705 tls_client_auth (mutual TLS client authentication) alongside the existing client_secret_post mechanism.

Changes:

  • Added a new TlsClientAuthFlow and TokenEndpointAuthMethod to support mTLS-based token exchange.
  • Extended OAuth2 configuration and factory builder APIs to select token endpoint auth method and provide TLS cert/key inputs.
  • Updated TokenClient request construction plus added/updated tests for both auth methods.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenEndpointAuthMethod.java Introduces enum for token endpoint auth methods and parsing.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/ClientCredentialsExchangeRequest.java Adds authMethod field to drive token request formatting.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenClient.java Conditionally includes client_secret based on auth method.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/TlsClientAuthFlow.java New flow implementation for tls_client_auth.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/FlowBase.java Adds TLS client cert configuration and periodic SSL context refresh scheduling.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/ClientCredentialsFlow.java Wires auth method selection and passes TLS settings into FlowBase.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationOAuth2.java Adds config param to select token endpoint auth method and chooses the appropriate flow.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2.java Extends builder to configure mTLS client auth inputs and flow selection.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenClientTest.java Updates/adds tests for request construction and exchange under both auth methods.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/TlsClientAuthFlowTest.java Adds test for defaulting clientId when omitted in mTLS flow.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/OAuth2MockHttpClient.java Adds test helper to mock SSL factory + async HTTP client construction.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationOAuth2Test.java Adds tests validating config-driven flow selection for mTLS.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2Test.java Adds builder tests for mTLS flow selection and required parameter validation.

return;
}
sslRefreshScheduler = Executors.newSingleThreadScheduledExecutor(
new ExecutorProvider.ExtendedThreadFactory("oauth2-tls-cert-refresher"));
bodyMap.put("grant_type", "client_credentials");
bodyMap.put("client_id", req.getClientId());
bodyMap.put("client_secret", req.getClientSecret());
if (req.getAuthMethod() == TokenEndpointAuthMethod.CLIENT_SECRET_POST) {
Comment on lines +82 to +84
long autoCertRefreshSeconds = getParameterDurationToSeconds(CONFIG_PARAM_AUTO_CERT_REFRESH_DURATION,
autoCertRefreshDuration, DEFAULT_AUTO_CERT_REFRESH_DURATION);
scheduleSslContextRefreshIfEnabled(autoCertRefreshSeconds);
return value;
}

public static TokenEndpointAuthMethod fromValue(String value) {
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for OAuth2 tls_client_auth (RFC 8705) in the Pulsar Java client’s AuthenticationOAuth2 client-credentials flow, enabling mutual-TLS authentication to the token endpoint in addition to the existing client_secret_post.

Changes:

  • Introduces TokenEndpointAuthMethod and routes OAuth2 client-credentials configuration to either ClientCredentialsFlow (client secret) or new TlsClientAuthFlow (mTLS).
  • Extends OAuth2 flow HTTP client setup to support client cert/key and periodic SSL context refresh.
  • Adds/updates unit tests for TLS client auth configuration and token exchange behavior.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2.java Extends builder to select token endpoint auth method and configure TLS cert/key + refresh interval.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationOAuth2.java Adds config parameter to select token endpoint auth method and instantiates the correct flow.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/ClientCredentialsFlow.java Passes auth method into token exchange request; plumbs TLS cert/key + refresh duration parameters.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/FlowBase.java Adds mTLS HTTP client configuration and scheduled SSL context refresh support.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/TlsClientAuthFlow.java New flow implementing client-credentials token exchange using TLS client authentication.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/ClientCredentialsExchangeRequest.java Adds token_endpoint_auth_method field to token exchange request model.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenClient.java Omits client_secret in the request body for non-client_secret_post methods.
pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenEndpointAuthMethod.java New enum defining supported token endpoint authentication methods.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2Test.java Adds coverage for builder selection of TLS flow and required TLS parameters.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationOAuth2Test.java Adds coverage for configure() selecting TLS flow; uses SSL factory/http client construction mocking.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/OAuth2MockHttpClient.java New test utility to mock SSL factory and async HTTP client construction.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/TlsClientAuthFlowTest.java New test for defaulting clientId when not provided.
pulsar-client/src/test/java/org/apache/pulsar/client/impl/auth/oauth2/protocol/TokenClientTest.java Adds TLS-client-auth exchange tests and updates existing tests to set auth method.

Comment on lines +36 to +41
OAuth2MockHttpClient.withMockedSslFactory(() -> {
TlsClientAuthFlow flow = TlsClientAuthFlow.fromParameters(params);
Field clientIdField = flow.getClass().getDeclaredField("clientId");
clientIdField.setAccessible(true);
assertEquals((String) clientIdField.get(flow), "pulsar-client");
flow.close();
Comment on lines +46 to +47
@JsonProperty("token_endpoint_auth_method")
private TokenEndpointAuthMethod authMethod;
Comment on lines 58 to 65
String buildClientCredentialsBody(ClientCredentialsExchangeRequest req) {
Map<String, String> bodyMap = new TreeMap<>();
bodyMap.put("grant_type", "client_credentials");
bodyMap.put("client_id", req.getClientId());
bodyMap.put("client_secret", req.getClientSecret());
if (req.getAuthMethod() == TokenEndpointAuthMethod.CLIENT_SECRET_POST) {
bodyMap.put("client_secret", req.getClientSecret());
}
// Only set audience and scope if they are non-empty.

protected static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ofSeconds(10);
protected static final Duration DEFAULT_READ_TIMEOUT = Duration.ofSeconds(30);
protected static final Duration DEFAULT_AUTO_CERT_REFRESH_DURATION = Duration.ofSeconds(300);
Comment on lines +118 to +122
* @param tokenEndpointAuthMethod the token endpoint auth method
* @return the builder
*/
public ClientCredentialsBuilder tokenEndpointAuthMethod(TokenEndpointAuthMethod tokenEndpointAuthMethod) {
this.tokenEndpointAuthMethod = tokenEndpointAuthMethod;
@izumo27
Copy link
Copy Markdown
Contributor Author

izumo27 commented Apr 21, 2026

@lhotari PTAL, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants