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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 361c2daeaa3 CAMEL-22276: camel-http OAuth2.0 body authentication 
(#18757)
361c2daeaa3 is described below

commit 361c2daeaa3129fbc3ca4de7551e5d2bf5d3a92f
Author: Billy <[email protected]>
AuthorDate: Tue Jul 29 15:11:00 2025 +0200

    CAMEL-22276: camel-http OAuth2.0 body authentication (#18757)
    
    * CAMEL-22276: camel-http - add new option for OAuth2 body authentication
    
    * CAMEL-22276: camel-http - add http oauth2 tests for new body 
authentication
    
    * CAMEL-22276: camel-http run mvn clean install for formatting
---
 .../apache/camel/http/common/HttpConfiguration.java  | 14 ++++++++++++++
 .../apache/camel/component/http/HttpComponent.java   |  9 +++++++--
 .../camel/component/http/OAuth2ClientConfigurer.java | 15 +++++++++++----
 .../component/http/HttpOAuth2AuthenticationTest.java | 16 ++++++++++++++++
 .../http/handler/OAuth2TokenRequestHandler.java      | 20 ++++++++++++++++++--
 5 files changed, 66 insertions(+), 8 deletions(-)

diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConfiguration.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConfiguration.java
index 43838911014..e12a60b74ba 100644
--- 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConfiguration.java
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpConfiguration.java
@@ -56,6 +56,9 @@ public class HttpConfiguration implements Serializable {
                             +
                             "If you set this parameter to too small value, you 
can get 4xx http errors because camel will think that the received token is 
still valid, while in reality the token is expired for the Authentication 
server.")
     private long oauth2CachedTokensExpirationMarginSeconds = 5L;
+    @UriParam(label = "producer,security", defaultValue = "false",
+              description = "Whether to use OAuth2 body authentication.")
+    private boolean oauth2BodyAuthentication;
     @Metadata(label = "producer,security", description = "Authentication 
domain to use with NTLM")
     @Deprecated
     private String authDomain;
@@ -346,4 +349,15 @@ public class HttpConfiguration implements Serializable {
     public void setOauth2ResourceIndicator(final String 
oauth2ResourceIndicator) {
         this.oauth2ResourceIndicator = oauth2ResourceIndicator;
     }
+
+    public boolean isOauth2BodyAuthentication() {
+        return oauth2BodyAuthentication;
+    }
+
+    /**
+     * Whether to use OAuth2 body authentication.
+     */
+    public void setOauth2BodyAuthentication(boolean oauth2BodyAuthentication) {
+        this.oauth2BodyAuthentication = oauth2BodyAuthentication;
+    }
 }
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
index d7e67b64d6a..02b8998f11a 100644
--- 
a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponent.java
@@ -257,7 +257,11 @@ public class HttpComponent extends HttpCommonComponent 
implements RestProducerFa
                 "oauth2CachedTokensExpirationMarginSeconds",
                 long.class,
                 configDefaults.getOauth2CachedTokensExpirationMarginSeconds());
-
+        boolean useBodyAuthentication = getParameter(
+                parameters,
+                "oauth2BodyAuthentication",
+                boolean.class,
+                configDefaults.isOauth2BodyAuthentication());
         if (clientId != null && clientSecret != null && tokenEndpoint != null) 
{
             return CompositeHttpConfigurer.combineConfigurers(configurer,
                     new OAuth2ClientConfigurer(
@@ -268,7 +272,8 @@ public class HttpComponent extends HttpCommonComponent 
implements RestProducerFa
                             scope,
                             cacheTokens,
                             cachedTokensDefaultExpirySeconds,
-                            cachedTokensExpirationMarginSeconds));
+                            cachedTokensExpirationMarginSeconds,
+                            useBodyAuthentication));
         }
         return configurer;
     }
diff --git 
a/components/camel-http/src/main/java/org/apache/camel/component/http/OAuth2ClientConfigurer.java
 
b/components/camel-http/src/main/java/org/apache/camel/component/http/OAuth2ClientConfigurer.java
index 10270d080ff..e82a6b2c8dd 100644
--- 
a/components/camel-http/src/main/java/org/apache/camel/component/http/OAuth2ClientConfigurer.java
+++ 
b/components/camel-http/src/main/java/org/apache/camel/component/http/OAuth2ClientConfigurer.java
@@ -52,12 +52,14 @@ public class OAuth2ClientConfigurer extends ServiceSupport 
implements HttpClient
     private final Long cachedTokensDefaultExpirySeconds;
     private final Long cachedTokensExpirationMarginSeconds;
     private final static ConcurrentMap<OAuth2URIAndCredentials, TokenCache> 
tokenCache = new ConcurrentHashMap<>();
+    private final boolean useBodyAuthentication;
     private final String resourceIndicator;
     private HttpClient httpClient;
 
     public OAuth2ClientConfigurer(String clientId, String clientSecret, String 
tokenEndpoint, String resourceIndicator,
                                   String scope, boolean cacheTokens,
-                                  long cachedTokensDefaultExpirySeconds, long 
cachedTokensExpirationMarginSeconds) {
+                                  long cachedTokensDefaultExpirySeconds, long 
cachedTokensExpirationMarginSeconds,
+                                  boolean useBodyAuthentication) {
         this.clientId = clientId;
         this.clientSecret = clientSecret;
         this.tokenEndpoint = tokenEndpoint;
@@ -66,6 +68,7 @@ public class OAuth2ClientConfigurer extends ServiceSupport 
implements HttpClient
         this.cacheTokens = cacheTokens;
         this.cachedTokensDefaultExpirySeconds = 
cachedTokensDefaultExpirySeconds;
         this.cachedTokensExpirationMarginSeconds = 
cachedTokensExpirationMarginSeconds;
+        this.useBodyAuthentication = useBodyAuthentication;
     }
 
     @Override
@@ -106,9 +109,13 @@ public class OAuth2ClientConfigurer extends ServiceSupport 
implements HttpClient
         }
 
         final HttpPost httpPost = new HttpPost(tokenEndpoint);
-
-        httpPost.addHeader(HttpHeaders.AUTHORIZATION,
-                HttpCredentialsHelper.generateBasicAuthHeader(clientId, 
clientSecret));
+        if (useBodyAuthentication) {
+            bodyStr += "&client_id=" + clientId;
+            bodyStr += "&client_secret=" + clientSecret;
+        } else {
+            httpPost.addHeader(HttpHeaders.AUTHORIZATION,
+                    HttpCredentialsHelper.generateBasicAuthHeader(clientId, 
clientSecret));
+        }
         if (null != resourceIndicator) {
             bodyStr = String.join(bodyStr, "&resource=" + resourceIndicator);
         }
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2AuthenticationTest.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2AuthenticationTest.java
index 223b53457b1..fb29678eed2 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2AuthenticationTest.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2AuthenticationTest.java
@@ -98,6 +98,22 @@ public class HttpOAuth2AuthenticationTest extends 
BaseHttpTest {
 
     }
 
+    @Test
+    public void bodyAuthenticationIsPresent() {
+        String tokenEndpoint = "http://localhost:"; + 
localServer.getLocalPort() + "/token";
+
+        Exchange exchange
+                = template.request("http://localhost:"; + 
localServer.getLocalPort() + "/post?httpMethod=POST&oauth2ClientId="
+                                   + clientId + "&oauth2ClientSecret=" + 
clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint
+                                   +
+                                   "&oauth2BodyAuthentication=true",
+                        exchange1 -> {
+                        });
+
+        assertExchange(exchange);
+
+    }
+
     protected void assertHeaders(Map<String, Object> headers) {
         assertEquals(HttpStatus.SC_OK, 
headers.get(Exchange.HTTP_RESPONSE_CODE));
     }
diff --git 
a/components/camel-http/src/test/java/org/apache/camel/component/http/handler/OAuth2TokenRequestHandler.java
 
b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/OAuth2TokenRequestHandler.java
index cb649223f79..6d2ae6b606b 100644
--- 
a/components/camel-http/src/test/java/org/apache/camel/component/http/handler/OAuth2TokenRequestHandler.java
+++ 
b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/OAuth2TokenRequestHandler.java
@@ -28,6 +28,7 @@ import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.io.HttpRequestHandler;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
 import org.apache.hc.core5.http.io.entity.StringEntity;
@@ -54,8 +55,12 @@ public class OAuth2TokenRequestHandler implements 
HttpRequestHandler {
                 .filter(pair -> pair.getName().equals("grant_type") && 
pair.getValue().equals("client_credentials"))
                 .findAny().orElseThrow(() -> new HttpException("Invalid or 
missing grant_type"));
 
-        if (request.getHeader(HttpHeaders.AUTHORIZATION) == null || 
!request.getHeader(HttpHeaders.AUTHORIZATION).getValue()
-                
.equals(HttpCredentialsHelper.generateBasicAuthHeader(clientId, clientSecret)))
+        Map<String, String> bodyCredentials = new HashMap<>();
+        WWWFormCodec.parse(requestBody, StandardCharsets.UTF_8).stream()
+                .filter(pair -> pair.getName().equals("client_id") || 
pair.getName().equals("client_secret"))
+                .forEach(pair -> bodyCredentials.put(pair.getName(), 
pair.getValue()));
+
+        if (!hasValidHeaderAuthentication(request) && 
!hasValidBodyAuthentication(bodyCredentials))
             throw new HttpException("Invalid credentials");
 
         Map<String, String> responseEntity = new HashMap<>();
@@ -64,4 +69,15 @@ public class OAuth2TokenRequestHandler implements 
HttpRequestHandler {
         response.setEntity(new StringEntity(Jsoner.serialize(responseEntity), 
ContentType.APPLICATION_JSON));
     }
 
+    private boolean hasValidHeaderAuthentication(ClassicHttpRequest request) 
throws ProtocolException {
+        return request.containsHeader(HttpHeaders.AUTHORIZATION) && 
request.getHeader(HttpHeaders.AUTHORIZATION).getValue()
+                
.equals(HttpCredentialsHelper.generateBasicAuthHeader(clientId, clientSecret));
+    }
+
+    private boolean hasValidBodyAuthentication(Map<String, String> 
credentials) {
+        if (null == credentials || credentials.isEmpty())
+            return false;
+        return clientId.equals(credentials.get("client_id")) && 
clientSecret.equals(credentials.get("client_secret"));
+    }
+
 }

Reply via email to