This is an automated email from the ASF dual-hosted git repository.

FrankChen021 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new f92bf482993 Add configurable clientAuthenticationMethod to druid-pac4j 
OIDC configuration (#19020)
f92bf482993 is described below

commit f92bf4829935dc05f84597cdc6ca56cf112c11ce
Author: Lukas Krug <[email protected]>
AuthorDate: Sat Apr 25 08:34:00 2026 +0200

    Add configurable clientAuthenticationMethod to druid-pac4j OIDC 
configuration (#19020)
---
 docs/development/extensions-core/druid-pac4j.md    |  1 +
 .../apache/druid/security/pac4j/OIDCConfig.java    | 13 +++++++++-
 .../druid/security/pac4j/Pac4jAuthenticator.java   |  5 ++++
 .../druid/security/pac4j/OIDCConfigTest.java       | 28 ++++++++++++++++++++++
 4 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/docs/development/extensions-core/druid-pac4j.md 
b/docs/development/extensions-core/druid-pac4j.md
index 243350cc51f..a81752cb66a 100644
--- a/docs/development/extensions-core/druid-pac4j.md
+++ b/docs/development/extensions-core/druid-pac4j.md
@@ -55,6 +55,7 @@ druid.auth.authenticator.jwt.type=jwt
 |`druid.auth.pac4j.oidc.discoveryURI`|discovery URI for fetching OP metadata 
[see this](http://openid.net/specs/openid-connect-discovery-1_0.html).|none|Yes|
 
|`druid.auth.pac4j.oidc.oidcClaim`|[claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims)
 that will be extracted from the ID Token after validation.|name|No|
 |`druid.auth.pac4j.oidc.scope`| scope is used by an application during 
authentication to authorize access to a user's details.|`openid profile 
email`|No|
+|`druid.auth.pac4j.oidc.clientAuthenticationMethod`|The client authentication 
method to use when communicating with the OIDC provider. Supported values: 
`client_secret_basic`, `client_secret_post`, `client_secret_jwt`, 
`private_key_jwt`, `none`. If not specified, pac4j will auto-detect the method 
from the provider's discovery document. Set this explicitly if you need to use 
a specific method (e.g., when your provider advertises multiple methods but you 
want to use a particular one).|Auto [...]
 
 :::info
 Users must set a strong passphrase to ensure that an attacker is not able to 
guess it simply by brute force.
diff --git 
a/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/OIDCConfig.java
 
b/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/OIDCConfig.java
index 50b04455dbc..d83e04717a0 100644
--- 
a/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/OIDCConfig.java
+++ 
b/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/OIDCConfig.java
@@ -44,13 +44,17 @@ public class OIDCConfig
   @JsonProperty
   private final String scope;
 
+  @JsonProperty
+  private final String clientAuthenticationMethod;
+
   @JsonCreator
   public OIDCConfig(
       @JsonProperty("clientID") String clientID,
       @JsonProperty("clientSecret") PasswordProvider clientSecret,
       @JsonProperty("discoveryURI") String discoveryURI,
       @JsonProperty("oidcClaim") String oidcClaim,
-      @JsonProperty("scope") @Nullable String scope
+      @JsonProperty("scope") @Nullable String scope,
+      @JsonProperty("clientAuthenticationMethod") @Nullable String 
clientAuthenticationMethod
   )
   {
     this.clientID = Preconditions.checkNotNull(clientID, "null clientID");
@@ -58,6 +62,7 @@ public class OIDCConfig
     this.discoveryURI = Preconditions.checkNotNull(discoveryURI, "null 
discoveryURI");
     this.oidcClaim = oidcClaim == null ? DEFAULT_SCOPE : oidcClaim;
     this.scope = scope;
+    this.clientAuthenticationMethod = clientAuthenticationMethod;
   }
 
   @JsonProperty
@@ -89,4 +94,10 @@ public class OIDCConfig
   {
     return scope;
   }
+
+  @JsonProperty
+  public String getClientAuthenticationMethod()
+  {
+    return clientAuthenticationMethod;
+  }
 }
diff --git 
a/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/Pac4jAuthenticator.java
 
b/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/Pac4jAuthenticator.java
index ef30f4c7e69..59a6fa0782f 100644
--- 
a/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/Pac4jAuthenticator.java
+++ 
b/extensions-core/druid-pac4j/src/main/java/org/apache/druid/security/pac4j/Pac4jAuthenticator.java
@@ -27,6 +27,7 @@ import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.common.primitives.Ints;
 import com.google.inject.Provider;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
 import com.nimbusds.oauth2.sdk.http.HTTPRequest;
 import org.apache.druid.server.security.AuthenticationResult;
 import org.apache.druid.server.security.Authenticator;
@@ -132,6 +133,10 @@ public class Pac4jAuthenticator implements Authenticator
     oidcConf.setSecret(oidcConfig.getClientSecret().getPassword());
     oidcConf.setDiscoveryURI(oidcConfig.getDiscoveryURI());
     oidcConf.setScope(oidcConfig.getScope());
+    if (oidcConfig.getClientAuthenticationMethod() != null) {
+      oidcConf.setClientAuthenticationMethod(
+          
ClientAuthenticationMethod.parse(oidcConfig.getClientAuthenticationMethod()));
+    }
     oidcConf.setExpireSessionWithToken(true);
     oidcConf.setUseNonce(true);
     
oidcConf.setReadTimeout(Ints.checkedCast(pac4jCommonConfig.getReadTimeout().getMillis()));
diff --git 
a/extensions-core/druid-pac4j/src/test/java/org/apache/druid/security/pac4j/OIDCConfigTest.java
 
b/extensions-core/druid-pac4j/src/test/java/org/apache/druid/security/pac4j/OIDCConfigTest.java
index c4192c020df..0b6128e61bb 100644
--- 
a/extensions-core/druid-pac4j/src/test/java/org/apache/druid/security/pac4j/OIDCConfigTest.java
+++ 
b/extensions-core/druid-pac4j/src/test/java/org/apache/druid/security/pac4j/OIDCConfigTest.java
@@ -46,6 +46,7 @@ public class OIDCConfigTest
     Assert.assertEquals("testdiscoveryuri", conf.getDiscoveryURI());
     Assert.assertEquals("name", conf.getOidcClaim());
     Assert.assertEquals("testscope", conf.getScope());
+    Assert.assertNull(conf.getClientAuthenticationMethod());
   }
 
   @Test
@@ -72,4 +73,31 @@ public class OIDCConfigTest
     Assert.assertEquals("email", conf.getOidcClaim());
     Assert.assertEquals("testscope", conf.getScope());
   }
+
+  @Test
+  public void testSerdeWithClientAuthenticationMethod() throws Exception
+  {
+    ObjectMapper jsonMapper = new ObjectMapper();
+
+    String jsonStr = "{\n"
+                     + "  \"clientID\": \"testid\",\n"
+                     + "  \"clientSecret\": \"testsecret\",\n"
+                     + "  \"discoveryURI\": \"testdiscoveryuri\",\n"
+                     + "  \"oidcClaim\": \"email\",\n"
+                     + "  \"scope\": \"testscope\",\n"
+                     + "  \"clientAuthenticationMethod\": 
\"client_secret_post\"\n"
+                     + "}\n";
+
+    OIDCConfig conf = jsonMapper.readValue(
+        jsonMapper.writeValueAsString(jsonMapper.readValue(jsonStr, 
OIDCConfig.class)),
+        OIDCConfig.class
+    );
+
+    Assert.assertEquals("testid", conf.getClientID());
+    Assert.assertEquals("testsecret", conf.getClientSecret().getPassword());
+    Assert.assertEquals("testdiscoveryuri", conf.getDiscoveryURI());
+    Assert.assertEquals("email", conf.getOidcClaim());
+    Assert.assertEquals("testscope", conf.getScope());
+    Assert.assertEquals("client_secret_post", 
conf.getClientAuthenticationMethod());
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to