You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/10/12 07:31:34 UTC
[camel] branch main updated: OAuth2 authentication with client credentials flow (#11628)
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 2f3acd52eb7 OAuth2 authentication with client credentials flow (#11628)
2f3acd52eb7 is described below
commit 2f3acd52eb79e902280f430aa239557b83da9fbb
Author: Gilvan Filho <gi...@gmail.com>
AuthorDate: Thu Oct 12 04:31:27 2023 -0300
OAuth2 authentication with client credentials flow (#11628)
---
.../catalog/components/atmosphere-websocket.json | 5 +-
.../org/apache/camel/catalog/components/http.json | 7 +-
.../org/apache/camel/catalog/components/https.json | 7 +-
.../websocket/WebsocketEndpointConfigurer.java | 18 +++++
.../websocket/WebsocketEndpointUriFactory.java | 10 ++-
.../atmosphere/websocket/atmosphere-websocket.json | 5 +-
.../camel/http/common/HttpCommonEndpoint.java | 40 ++++++++++
.../camel/http/common/HttpConfiguration.java | 40 ++++++++++
components/camel-http/pom.xml | 4 +
.../component/http/HttpEndpointConfigurer.java | 18 +++++
.../component/http/HttpEndpointUriFactory.java | 9 ++-
.../component/http/HttpTimeoutConverterLoader.java | 50 -------------
.../org/apache/camel/component/http/http.json | 7 +-
.../org/apache/camel/component/http/https.json | 7 +-
.../camel-http/src/main/docs/http-component.adoc | 20 +++++
.../apache/camel/component/http/HttpComponent.java | 15 ++++
.../component/http/HttpCredentialsHelper.java | 10 ++-
.../apache/camel/component/http/HttpEndpoint.java | 11 +--
.../component/http/OAuth2ClientConfigurer.java | 79 ++++++++++++++++++++
.../http/HttpOAuth2AuthenticationTest.java | 87 ++++++++++++++++++++++
.../http/handler/OAuth2TokenRequestHandler.java | 68 +++++++++++++++++
21 files changed, 447 insertions(+), 70 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atmosphere-websocket.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atmosphere-websocket.json
index 8e7ef7688f5..2ac5978912b 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atmosphere-websocket.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/atmosphere-websocket.json
@@ -70,6 +70,9 @@
"optionsEnabled": { "index": 24, "kind": "parameter", "displayName": "Options Enabled", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to enable HTTP OPTIONS for this Servlet consumer. By default OPTIONS is turned off." },
"traceEnabled": { "index": 25, "kind": "parameter", "displayName": "Trace Enabled", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to enable HTTP TRACE for this Servlet consumer. By default TRACE is turned off." },
"bridgeEndpoint": { "index": 26, "kind": "parameter", "displayName": "Bridge Endpoint", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the option is true, HttpProducer will ignore the Exchange.HTTP_URI header, and use the endpoint's URI for request. You may also set the option throwExceptionOnFailure to be false to let the HttpPro [...]
- "lazyStartProducer": { "index": 27, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+ "lazyStartProducer": { "index": 27, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+ "oauth2ClientId": { "index": 28, "kind": "parameter", "displayName": "Oauth2 Client Id", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client id" },
+ "oauth2ClientSecret": { "index": 29, "kind": "parameter", "displayName": "Oauth2 Client Secret", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client secret" },
+ "oauth2TokenEndpoint": { "index": 30, "kind": "parameter", "displayName": "Oauth2 Token Endpoint", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OAuth2 Token endpoint" }
}
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json
index f635c08afc2..b76d5c885a3 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json
@@ -132,7 +132,10 @@
"authMethodPriority": { "index": 46, "kind": "parameter", "displayName": "Auth Method Priority", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "Basic", "Digest", "NTLM" ], "deprecated": false, "autowired": false, "secret": false, "description": "Which authentication method to prioritize to use, either as Basic, Digest or NTLM." },
"authPassword": { "index": 47, "kind": "parameter", "displayName": "Auth Password", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication password" },
"authUsername": { "index": 48, "kind": "parameter", "displayName": "Auth Username", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication username" },
- "sslContextParameters": { "index": 49, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
- "x509HostnameVerifier": { "index": 50, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
+ "oauth2ClientId": { "index": 49, "kind": "parameter", "displayName": "Oauth2 Client Id", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client id" },
+ "oauth2ClientSecret": { "index": 50, "kind": "parameter", "displayName": "Oauth2 Client Secret", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client secret" },
+ "oauth2TokenEndpoint": { "index": 51, "kind": "parameter", "displayName": "Oauth2 Token Endpoint", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OAuth2 Token endpoint" },
+ "sslContextParameters": { "index": 52, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
+ "x509HostnameVerifier": { "index": 53, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
}
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json
index 949ce8ba489..6f86f429003 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json
@@ -132,7 +132,10 @@
"authMethodPriority": { "index": 46, "kind": "parameter", "displayName": "Auth Method Priority", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "Basic", "Digest", "NTLM" ], "deprecated": false, "autowired": false, "secret": false, "description": "Which authentication method to prioritize to use, either as Basic, Digest or NTLM." },
"authPassword": { "index": 47, "kind": "parameter", "displayName": "Auth Password", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication password" },
"authUsername": { "index": 48, "kind": "parameter", "displayName": "Auth Username", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication username" },
- "sslContextParameters": { "index": 49, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
- "x509HostnameVerifier": { "index": 50, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
+ "oauth2ClientId": { "index": 49, "kind": "parameter", "displayName": "Oauth2 Client Id", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client id" },
+ "oauth2ClientSecret": { "index": 50, "kind": "parameter", "displayName": "Oauth2 Client Secret", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client secret" },
+ "oauth2TokenEndpoint": { "index": 51, "kind": "parameter", "displayName": "Oauth2 Token Endpoint", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OAuth2 Token endpoint" },
+ "sslContextParameters": { "index": 52, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
+ "x509HostnameVerifier": { "index": 53, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
}
}
diff --git a/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointConfigurer.java b/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointConfigurer.java
index d817561f479..bd01d94ba11 100644
--- a/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointConfigurer.java
+++ b/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointConfigurer.java
@@ -25,6 +25,12 @@ public class WebsocketEndpointConfigurer extends ServletEndpointConfigurer imple
case "bridgeEndpoint": target.setBridgeEndpoint(property(camelContext, boolean.class, value)); return true;
case "lazystartproducer":
case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "oauth2clientid":
+ case "oauth2ClientId": target.setOauth2ClientId(property(camelContext, java.lang.String.class, value)); return true;
+ case "oauth2clientsecret":
+ case "oauth2ClientSecret": target.setOauth2ClientSecret(property(camelContext, java.lang.String.class, value)); return true;
+ case "oauth2tokenendpoint":
+ case "oauth2TokenEndpoint": target.setOauth2TokenEndpoint(property(camelContext, java.lang.String.class, value)); return true;
case "sendtoall":
case "sendToAll": target.setSendToAll(property(camelContext, boolean.class, value)); return true;
case "usestreaming":
@@ -40,6 +46,12 @@ public class WebsocketEndpointConfigurer extends ServletEndpointConfigurer imple
case "bridgeEndpoint": return boolean.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
+ case "oauth2clientid":
+ case "oauth2ClientId": return java.lang.String.class;
+ case "oauth2clientsecret":
+ case "oauth2ClientSecret": return java.lang.String.class;
+ case "oauth2tokenendpoint":
+ case "oauth2TokenEndpoint": return java.lang.String.class;
case "sendtoall":
case "sendToAll": return boolean.class;
case "usestreaming":
@@ -56,6 +68,12 @@ public class WebsocketEndpointConfigurer extends ServletEndpointConfigurer imple
case "bridgeEndpoint": return target.isBridgeEndpoint();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
+ case "oauth2clientid":
+ case "oauth2ClientId": return target.getOauth2ClientId();
+ case "oauth2clientsecret":
+ case "oauth2ClientSecret": return target.getOauth2ClientSecret();
+ case "oauth2tokenendpoint":
+ case "oauth2TokenEndpoint": return target.getOauth2TokenEndpoint();
case "sendtoall":
case "sendToAll": return target.isSendToAll();
case "usestreaming":
diff --git a/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointUriFactory.java b/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointUriFactory.java
index d011c5aa34a..773fda85f09 100644
--- a/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointUriFactory.java
+++ b/components/camel-atmosphere-websocket/src/generated/java/org/apache/camel/component/atmosphere/websocket/WebsocketEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class WebsocketEndpointUriFactory extends org.apache.camel.support.compon
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(28);
+ Set<String> props = new HashSet<>(31);
props.add("async");
props.add("attachmentMultipartBinding");
props.add("bridgeEndpoint");
@@ -42,6 +42,9 @@ public class WebsocketEndpointUriFactory extends org.apache.camel.support.compon
props.add("mapHttpMessageHeaders");
props.add("matchOnUriPrefix");
props.add("muteException");
+ props.add("oauth2ClientId");
+ props.add("oauth2ClientSecret");
+ props.add("oauth2TokenEndpoint");
props.add("optionsEnabled");
props.add("responseBufferSize");
props.add("sendToAll");
@@ -51,7 +54,10 @@ public class WebsocketEndpointUriFactory extends org.apache.camel.support.compon
props.add("transferException");
props.add("useStreaming");
PROPERTY_NAMES = Collections.unmodifiableSet(props);
- SECRET_PROPERTY_NAMES = Collections.emptySet();
+ Set<String> secretProps = new HashSet<>(2);
+ secretProps.add("oauth2ClientId");
+ secretProps.add("oauth2ClientSecret");
+ SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
MULTI_VALUE_PREFIXES = Collections.emptySet();
}
diff --git a/components/camel-atmosphere-websocket/src/generated/resources/org/apache/camel/component/atmosphere/websocket/atmosphere-websocket.json b/components/camel-atmosphere-websocket/src/generated/resources/org/apache/camel/component/atmosphere/websocket/atmosphere-websocket.json
index 8e7ef7688f5..2ac5978912b 100644
--- a/components/camel-atmosphere-websocket/src/generated/resources/org/apache/camel/component/atmosphere/websocket/atmosphere-websocket.json
+++ b/components/camel-atmosphere-websocket/src/generated/resources/org/apache/camel/component/atmosphere/websocket/atmosphere-websocket.json
@@ -70,6 +70,9 @@
"optionsEnabled": { "index": 24, "kind": "parameter", "displayName": "Options Enabled", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to enable HTTP OPTIONS for this Servlet consumer. By default OPTIONS is turned off." },
"traceEnabled": { "index": 25, "kind": "parameter", "displayName": "Trace Enabled", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Specifies whether to enable HTTP TRACE for this Servlet consumer. By default TRACE is turned off." },
"bridgeEndpoint": { "index": 26, "kind": "parameter", "displayName": "Bridge Endpoint", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the option is true, HttpProducer will ignore the Exchange.HTTP_URI header, and use the endpoint's URI for request. You may also set the option throwExceptionOnFailure to be false to let the HttpPro [...]
- "lazyStartProducer": { "index": 27, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+ "lazyStartProducer": { "index": 27, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produ [...]
+ "oauth2ClientId": { "index": 28, "kind": "parameter", "displayName": "Oauth2 Client Id", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client id" },
+ "oauth2ClientSecret": { "index": 29, "kind": "parameter", "displayName": "Oauth2 Client Secret", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client secret" },
+ "oauth2TokenEndpoint": { "index": 30, "kind": "parameter", "displayName": "Oauth2 Token Endpoint", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OAuth2 Token endpoint" }
}
}
diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
index 6c6a090d693..208c4e55690 100644
--- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
+++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
@@ -153,6 +153,12 @@ public abstract class HttpCommonEndpoint extends DefaultEndpoint implements Head
private String authUsername;
@UriParam(label = "producer,security", secret = true, description = "Authentication password")
private String authPassword;
+ @UriParam(label = "producer,security", secret = true, description = "OAuth2 client id")
+ private String oauth2ClientId;
+ @UriParam(label = "producer,security", secret = true, description = "OAuth2 client secret")
+ private String oauth2ClientSecret;
+ @UriParam(label = "producer,security", description = "OAuth2 Token endpoint")
+ private String oauth2TokenEndpoint;
@UriParam(label = "producer,security", description = "Authentication domain to use with NTML")
private String authDomain;
@UriParam(label = "producer,security", description = "Authentication host to use with NTML")
@@ -774,4 +780,38 @@ public abstract class HttpCommonEndpoint extends DefaultEndpoint implements Head
public void setProxyAuthNtHost(String proxyAuthNtHost) {
this.proxyAuthNtHost = proxyAuthNtHost;
}
+
+ public String getOauth2ClientId() {
+ return this.oauth2ClientId;
+ }
+
+ /**
+ * OAuth2 Client id
+ */
+ public void setOauth2ClientId(String oauth2ClientId) {
+ this.oauth2ClientId = oauth2ClientId;
+ }
+
+ public String getOauth2ClientSecret() {
+ return this.oauth2ClientSecret;
+ }
+
+ /**
+ * OAuth2 Client secret
+ */
+ public void setOauth2ClientSecret(String oauth2ClientSecret) {
+ this.oauth2ClientSecret = oauth2ClientSecret;
+ }
+
+ public String getOauth2TokenEndpoint() {
+ return this.oauth2TokenEndpoint;
+ }
+
+ /**
+ * OAuth2 token endpoint
+ */
+ public void setOauth2TokenEndpoint(String oauth2TokenEndpoint) {
+ this.oauth2TokenEndpoint = oauth2TokenEndpoint;
+ }
+
}
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 cf6a72093f1..4dbc0984414 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
@@ -33,6 +33,12 @@ public class HttpConfiguration implements Serializable {
private String authUsername;
@Metadata(label = "producer,security", secret = true, description = "Authentication password")
private String authPassword;
+ @Metadata(label = "producer,security", secret = true, description = "OAuth2 client id")
+ private String oauth2ClientId;
+ @Metadata(label = "producer,security", secret = true, description = "OAuth2 client secret")
+ private String oauth2ClientSecret;
+ @Metadata(label = "producer,security", description = "OAuth2 token endpoint")
+ private String oauth2TokenEndpoint;
@Metadata(label = "producer,security", description = "Authentication domain to use with NTML")
private String authDomain;
@Metadata(label = "producer,security", description = "Authentication host to use with NTML")
@@ -220,4 +226,38 @@ public class HttpConfiguration implements Serializable {
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
+
+ public String getOauth2ClientId() {
+ return this.oauth2ClientId;
+ }
+
+ /**
+ * OAuth2 Client id
+ */
+ public void setOauth2ClientId(String oauth2ClientId) {
+ this.oauth2ClientId = oauth2ClientId;
+ }
+
+ public String getOauth2ClientSecret() {
+ return this.oauth2ClientSecret;
+ }
+
+ /**
+ * OAuth2 Client secret
+ */
+ public void setOauth2ClientSecret(String oauth2ClientSecret) {
+ this.oauth2ClientSecret = oauth2ClientSecret;
+ }
+
+ public String getOauth2TokenEndpoint() {
+ return this.oauth2TokenEndpoint;
+ }
+
+ /**
+ * OAuth2 token endpoint
+ */
+ public void setOauth2TokenEndpoint(String oauth2TokenEndpoint) {
+ this.oauth2TokenEndpoint = oauth2TokenEndpoint;
+ }
+
}
diff --git a/components/camel-http/pom.xml b/components/camel-http/pom.xml
index 6331c4aaf63..88c3c2e3db9 100644
--- a/components/camel-http/pom.xml
+++ b/components/camel-http/pom.xml
@@ -49,6 +49,10 @@
<groupId>org.apache.camel</groupId>
<artifactId>camel-file</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-util-json</artifactId>
+ </dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
diff --git a/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointConfigurer.java b/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointConfigurer.java
index 801fc56b1cf..aa5159cddb8 100644
--- a/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointConfigurer.java
+++ b/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointConfigurer.java
@@ -83,6 +83,12 @@ public class HttpEndpointConfigurer extends PropertyConfigurerSupport implements
case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
case "maxtotalconnections":
case "maxTotalConnections": target.setMaxTotalConnections(property(camelContext, int.class, value)); return true;
+ case "oauth2clientid":
+ case "oauth2ClientId": target.setOauth2ClientId(property(camelContext, java.lang.String.class, value)); return true;
+ case "oauth2clientsecret":
+ case "oauth2ClientSecret": target.setOauth2ClientSecret(property(camelContext, java.lang.String.class, value)); return true;
+ case "oauth2tokenendpoint":
+ case "oauth2TokenEndpoint": target.setOauth2TokenEndpoint(property(camelContext, java.lang.String.class, value)); return true;
case "okstatuscoderange":
case "okStatusCodeRange": target.setOkStatusCodeRange(property(camelContext, java.lang.String.class, value)); return true;
case "preservehostheader":
@@ -190,6 +196,12 @@ public class HttpEndpointConfigurer extends PropertyConfigurerSupport implements
case "lazyStartProducer": return boolean.class;
case "maxtotalconnections":
case "maxTotalConnections": return int.class;
+ case "oauth2clientid":
+ case "oauth2ClientId": return java.lang.String.class;
+ case "oauth2clientsecret":
+ case "oauth2ClientSecret": return java.lang.String.class;
+ case "oauth2tokenendpoint":
+ case "oauth2TokenEndpoint": return java.lang.String.class;
case "okstatuscoderange":
case "okStatusCodeRange": return java.lang.String.class;
case "preservehostheader":
@@ -298,6 +310,12 @@ public class HttpEndpointConfigurer extends PropertyConfigurerSupport implements
case "lazyStartProducer": return target.isLazyStartProducer();
case "maxtotalconnections":
case "maxTotalConnections": return target.getMaxTotalConnections();
+ case "oauth2clientid":
+ case "oauth2ClientId": return target.getOauth2ClientId();
+ case "oauth2clientsecret":
+ case "oauth2ClientSecret": return target.getOauth2ClientSecret();
+ case "oauth2tokenendpoint":
+ case "oauth2TokenEndpoint": return target.getOauth2TokenEndpoint();
case "okstatuscoderange":
case "okStatusCodeRange": return target.getOkStatusCodeRange();
case "preservehostheader":
diff --git a/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointUriFactory.java b/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointUriFactory.java
index ee87c1e8562..f8f1fbdf858 100644
--- a/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointUriFactory.java
+++ b/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpEndpointUriFactory.java
@@ -22,7 +22,7 @@ public class HttpEndpointUriFactory extends org.apache.camel.support.component.E
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(51);
+ Set<String> props = new HashSet<>(54);
props.add("authDomain");
props.add("authHost");
props.add("authMethod");
@@ -55,6 +55,9 @@ public class HttpEndpointUriFactory extends org.apache.camel.support.component.E
props.add("ignoreResponseBody");
props.add("lazyStartProducer");
props.add("maxTotalConnections");
+ props.add("oauth2ClientId");
+ props.add("oauth2ClientSecret");
+ props.add("oauth2TokenEndpoint");
props.add("okStatusCodeRange");
props.add("preserveHostHeader");
props.add("proxyAuthDomain");
@@ -75,9 +78,11 @@ public class HttpEndpointUriFactory extends org.apache.camel.support.component.E
props.add("userAgent");
props.add("x509HostnameVerifier");
PROPERTY_NAMES = Collections.unmodifiableSet(props);
- Set<String> secretProps = new HashSet<>(4);
+ Set<String> secretProps = new HashSet<>(6);
secretProps.add("authPassword");
secretProps.add("authUsername");
+ secretProps.add("oauth2ClientId");
+ secretProps.add("oauth2ClientSecret");
secretProps.add("proxyAuthPassword");
secretProps.add("proxyAuthUsername");
SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
diff --git a/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpTimeoutConverterLoader.java b/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpTimeoutConverterLoader.java
deleted file mode 100644
index 2cad4863d98..00000000000
--- a/components/camel-http/src/generated/java/org/apache/camel/component/http/HttpTimeoutConverterLoader.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Generated by camel build tools - do NOT edit this file! */
-package org.apache.camel.component.http;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.DeferredContextBinding;
-import org.apache.camel.TypeConverterLoaderException;
-import org.apache.camel.spi.TypeConverterLoader;
-import org.apache.camel.spi.TypeConverterRegistry;
-import org.apache.camel.support.SimpleTypeConverter;
-
-/**
- * Generated by camel build tools - do NOT edit this file!
- */
-@SuppressWarnings("unchecked")
-@DeferredContextBinding
-public final class HttpTimeoutConverterLoader implements TypeConverterLoader, CamelContextAware {
-
- private CamelContext camelContext;
-
- public HttpTimeoutConverterLoader() {
- }
-
- @Override
- public void setCamelContext(CamelContext camelContext) {
- this.camelContext = camelContext;
- }
-
- @Override
- public CamelContext getCamelContext() {
- return camelContext;
- }
-
- @Override
- public void load(TypeConverterRegistry registry) throws TypeConverterLoaderException {
- registerConverters(registry);
- }
-
- private void registerConverters(TypeConverterRegistry registry) {
- addTypeConverter(registry, org.apache.hc.core5.util.Timeout.class, java.lang.String.class, false,
- (type, exchange, value) -> HttpConverters.toTimeout((java.lang.String) value));
- addTypeConverter(registry, org.apache.hc.core5.util.Timeout.class, long.class, false,
- (type, exchange, value) -> HttpConverters.toTimeout((long) value));
- }
-
- private static void addTypeConverter(TypeConverterRegistry registry, Class<?> toType, Class<?> fromType, boolean allowNull, SimpleTypeConverter.ConversionMethod method) {
- registry.addTypeConverter(toType, fromType, new SimpleTypeConverter(allowNull, method));
- }
-
-}
diff --git a/components/camel-http/src/generated/resources/org/apache/camel/component/http/http.json b/components/camel-http/src/generated/resources/org/apache/camel/component/http/http.json
index f635c08afc2..b76d5c885a3 100644
--- a/components/camel-http/src/generated/resources/org/apache/camel/component/http/http.json
+++ b/components/camel-http/src/generated/resources/org/apache/camel/component/http/http.json
@@ -132,7 +132,10 @@
"authMethodPriority": { "index": 46, "kind": "parameter", "displayName": "Auth Method Priority", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "Basic", "Digest", "NTLM" ], "deprecated": false, "autowired": false, "secret": false, "description": "Which authentication method to prioritize to use, either as Basic, Digest or NTLM." },
"authPassword": { "index": 47, "kind": "parameter", "displayName": "Auth Password", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication password" },
"authUsername": { "index": 48, "kind": "parameter", "displayName": "Auth Username", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication username" },
- "sslContextParameters": { "index": 49, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
- "x509HostnameVerifier": { "index": 50, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
+ "oauth2ClientId": { "index": 49, "kind": "parameter", "displayName": "Oauth2 Client Id", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client id" },
+ "oauth2ClientSecret": { "index": 50, "kind": "parameter", "displayName": "Oauth2 Client Secret", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client secret" },
+ "oauth2TokenEndpoint": { "index": 51, "kind": "parameter", "displayName": "Oauth2 Token Endpoint", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OAuth2 Token endpoint" },
+ "sslContextParameters": { "index": 52, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
+ "x509HostnameVerifier": { "index": 53, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
}
}
diff --git a/components/camel-http/src/generated/resources/org/apache/camel/component/http/https.json b/components/camel-http/src/generated/resources/org/apache/camel/component/http/https.json
index 949ce8ba489..6f86f429003 100644
--- a/components/camel-http/src/generated/resources/org/apache/camel/component/http/https.json
+++ b/components/camel-http/src/generated/resources/org/apache/camel/component/http/https.json
@@ -132,7 +132,10 @@
"authMethodPriority": { "index": 46, "kind": "parameter", "displayName": "Auth Method Priority", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "Basic", "Digest", "NTLM" ], "deprecated": false, "autowired": false, "secret": false, "description": "Which authentication method to prioritize to use, either as Basic, Digest or NTLM." },
"authPassword": { "index": 47, "kind": "parameter", "displayName": "Auth Password", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication password" },
"authUsername": { "index": 48, "kind": "parameter", "displayName": "Auth Username", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "Authentication username" },
- "sslContextParameters": { "index": 49, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
- "x509HostnameVerifier": { "index": 50, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
+ "oauth2ClientId": { "index": 49, "kind": "parameter", "displayName": "Oauth2 Client Id", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client id" },
+ "oauth2ClientSecret": { "index": 50, "kind": "parameter", "displayName": "Oauth2 Client Secret", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "OAuth2 client secret" },
+ "oauth2TokenEndpoint": { "index": 51, "kind": "parameter", "displayName": "Oauth2 Token Endpoint", "group": "security", "label": "producer,security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "OAuth2 Token endpoint" },
+ "sslContextParameters": { "index": 52, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "To configure security using SSLContextParameters. Important: Only one instance of org.apache.camel.util.jsse.SSLContextParameters is supported per HttpComponent. If you [...]
+ "x509HostnameVerifier": { "index": 53, "kind": "parameter", "displayName": "X509 Hostname Verifier", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "javax.net.ssl.HostnameVerifier", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom X509HostnameVerifier such as DefaultHostnameVerifier or NoopHostnameVerifier" }
}
}
diff --git a/components/camel-http/src/main/docs/http-component.adoc b/components/camel-http/src/main/docs/http-component.adoc
index ee2bc8f878f..f47e29be15e 100644
--- a/components/camel-http/src/main/docs/http-component.adoc
+++ b/components/camel-http/src/main/docs/http-component.adoc
@@ -342,6 +342,26 @@ adding this URI option: `httpClient.cookieSpec=ignoreCookies`
In order to avoid the `NonRepeatableRequestException`, you need to do the
Preemptive Basic Authentication by adding the option: `authenticationPreemptive=true`
+== OAuth2 Support
+
+In order to get a access token from a Authorization Server and fill that in Authorization header to do requests to protected services, you will need to use `oauth2ClientId`, `oauth2ClientSecret` and `oauth2TokenEndpoint` properties, and those should be defined as specified at RFC 6749 and provided by your Authorization Server.
+
+In below example camel will do a underlying request to `https://localhost:8080/realms/master/protocol/openid-connect/token` using provided credentials (client id and client secret), then will get `access_token` from response and lastly will fill it at `Authorization` header of request which will be done to `https://localhost:9090`.
+
+[source,java]
+------------------------------------------------------------------------------------
+String clientId = "my-client-id";
+String clientSecret = "my-client-secret";
+String tokenEndpoint = "https://localhost:8080/realms/master/protocol/openid-connect/token";
+
+from("direct:start")
+ .to("https://localhost:9090/?oauth2ClientId=" + clientId + "&oauth2ClientSecret=" + clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint);
+------------------------------------------------------------------------------------
+
+NOTE: Camel only provide support for OAuth2 client credentials flow
+
+Important: Camel does not perform any validation in access token. It's up to the underlying service to validate it.
+
== Advanced Usage
If you need more control over the HTTP producer you should use the
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 afb481813c2..9c49a4de718 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
@@ -225,10 +225,25 @@ public class HttpComponent extends HttpCommonComponent implements RestProducerFa
HttpCredentialsHelper credentialsProvider = new HttpCredentialsHelper();
configurer = configureBasicAuthentication(parameters, configurer, credentialsProvider);
configurer = configureHttpProxy(parameters, configurer, secure, credentialsProvider);
+ configurer = configureOAuth2Authentication(parameters, configurer);
return configurer;
}
+ private HttpClientConfigurer configureOAuth2Authentication(
+ Map<String, Object> parameters, HttpClientConfigurer configurer) {
+
+ String clientId = getParameter(parameters, "oauth2ClientId", String.class);
+ String clientSecret = getParameter(parameters, "oauth2ClientSecret", String.class);
+ String tokenEndpoint = getParameter(parameters, "oauth2TokenEndpoint", String.class);
+
+ if (clientId != null && clientSecret != null && tokenEndpoint != null) {
+ return CompositeHttpConfigurer.combineConfigurers(configurer,
+ new OAuth2ClientConfigurer(clientId, clientSecret, tokenEndpoint));
+ }
+ return configurer;
+ }
+
private HttpClientConfigurer configureBasicAuthentication(
Map<String, Object> parameters, HttpClientConfigurer configurer,
HttpCredentialsHelper credentialsProvider) {
diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpCredentialsHelper.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpCredentialsHelper.java
index f51163f93b5..4c605149e0e 100644
--- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpCredentialsHelper.java
+++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpCredentialsHelper.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.http;
+import java.nio.charset.StandardCharsets;
import java.util.Objects;
import org.apache.hc.client5.http.auth.AuthScope;
@@ -23,8 +24,9 @@ import org.apache.hc.client5.http.auth.Credentials;
import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.auth.CredentialsStore;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.utils.Base64;
-final class HttpCredentialsHelper {
+public final class HttpCredentialsHelper {
private final CredentialsStore credentialsProvider;
@@ -40,4 +42,10 @@ final class HttpCredentialsHelper {
return credentialsProvider;
}
+ public static String generateBasicAuthHeader(String user, String pass) {
+ final String auth = user + ":" + pass;
+ final byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.UTF_8));
+ return "Basic " + new String(encodedAuth);
+ }
+
}
diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
index 309ef7ff39c..64edd3ba52c 100644
--- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
+++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java
@@ -269,11 +269,6 @@ public class HttpEndpoint extends HttpCommonEndpoint {
clientBuilder.setUserAgent(userAgent);
}
- HttpClientConfigurer configurer = getHttpClientConfigurer();
- if (configurer != null) {
- configurer.configureHttpClient(clientBuilder);
- }
-
if (isBridgeEndpoint()) {
// need to use noop cookiestore as we do not want to keep cookies in memory
clientBuilder.setDefaultCookieStore(new NoopCookieStore());
@@ -283,7 +278,13 @@ public class HttpEndpoint extends HttpCommonEndpoint {
clientBuilder.setRedirectStrategy(DefaultRedirectStrategy.INSTANCE);
}
+ HttpClientConfigurer configurer = getHttpClientConfigurer();
+ if (configurer != null) {
+ configurer.configureHttpClient(clientBuilder);
+ }
+
LOG.debug("Setup the HttpClientBuilder {}", clientBuilder);
+
return clientBuilder.build();
}
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
new file mode 100644
index 00000000000..23b633f631c
--- /dev/null
+++ b/components/camel-http/src/main/java/org/apache/camel/component/http/OAuth2ClientConfigurer.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.http;
+
+import org.apache.camel.util.json.DeserializationException;
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
+import org.apache.hc.client5.http.classic.HttpClient;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.EntityDetails;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+public class OAuth2ClientConfigurer implements HttpClientConfigurer {
+
+ private final String clientId;
+ private final String clientSecret;
+ private final String tokenEndpoint;
+
+ public OAuth2ClientConfigurer(String clientId, String clientSecret, String tokenEndpoint) {
+ this.clientId = clientId;
+ this.clientSecret = clientSecret;
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ @Override
+ public void configureHttpClient(HttpClientBuilder clientBuilder) {
+ HttpClient httpClient = clientBuilder.build();
+ clientBuilder.addRequestInterceptorFirst((HttpRequest request, EntityDetails entity, HttpContext context) -> {
+
+ final HttpPost httpPost = new HttpPost(tokenEndpoint);
+
+ httpPost.addHeader(HttpHeaders.AUTHORIZATION,
+ HttpCredentialsHelper.generateBasicAuthHeader(clientId, clientSecret));
+ httpPost.setEntity(new StringEntity("grant_type=client_credentials", ContentType.APPLICATION_FORM_URLENCODED));
+
+ httpClient.execute(httpPost, response -> {
+
+ try {
+ String responseString = EntityUtils.toString(response.getEntity());
+
+ if (response.getCode() == 200) {
+ String accessToken = ((JsonObject) Jsoner.deserialize(responseString)).getString("access_token");
+ request.addHeader(HttpHeaders.AUTHORIZATION, accessToken);
+ } else {
+ throw new HttpException("Received error response from token request with Status Code: " + response.getCode());
+ }
+
+ } catch (DeserializationException e) {
+ throw new HttpException("Something went wrong when reading token request response", e);
+ }
+
+ return null;
+ });
+
+ });
+ }
+
+}
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
new file mode 100644
index 00000000000..593180caf58
--- /dev/null
+++ b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpOAuth2AuthenticationTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.http.handler.HeaderValidationHandler;
+import org.apache.camel.component.http.handler.OAuth2TokenRequestHandler;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
+import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class HttpOAuth2AuthenticationTest extends BaseHttpTest {
+
+ private static final String FAKE_TOKEN = "xxx.yyy.zzz";
+ private static String clientId = "test-client";
+ private static String clientSecret = "test-secret";
+
+ private HttpServer localServer;
+
+ @BeforeEach
+ @Override
+ public void setUp() throws Exception {
+ Map<String, String> expectedHeaders = new HashMap<>();
+ expectedHeaders.put("Authorization", FAKE_TOKEN);
+
+ localServer = ServerBootstrap.bootstrap().setHttpProcessor(getBasicHttpProcessor())
+ .setConnectionReuseStrategy(getConnectionReuseStrategy()).setResponseFactory(getHttpResponseFactory())
+ .setSslContext(getSSLContext())
+ .register("/token", new OAuth2TokenRequestHandler(FAKE_TOKEN, clientId, clientSecret))
+ .register("/post",
+ new HeaderValidationHandler(
+ "POST",
+ null,
+ null,
+ null,
+ expectedHeaders))
+ .create();
+
+ localServer.start();
+ super.setUp();
+ }
+
+ @Test
+ public void authorizationHeaderIsPresent() throws Exception {
+
+ String tokenEndpoint = "http://localhost:" + localServer.getLocalPort() + "/token";
+
+ Exchange exchange
+ = template.request("http://localhost:" + localServer.getLocalPort() + "/post?httpMethod=POST&oauth2ClientId="
+ + clientId + "&oauth2ClientSecret=" + clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint,
+ exchange1 -> {
+ });
+
+ assertExchange(exchange);
+
+ }
+
+ protected void assertHeaders(Map<String, Object> headers) {
+ assertEquals(HttpStatus.SC_OK, headers.get(Exchange.HTTP_RESPONSE_CODE));
+ }
+
+ protected String getExpectedContent() {
+ return "";
+ }
+
+}
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
new file mode 100644
index 00000000000..9423dd3a3c1
--- /dev/null
+++ b/components/camel-http/src/test/java/org/apache/camel/component/http/handler/OAuth2TokenRequestHandler.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.http.handler;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.component.http.HttpCredentialsHelper;
+import org.apache.camel.util.json.Jsoner;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+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.io.HttpRequestHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.net.WWWFormCodec;
+
+public class OAuth2TokenRequestHandler implements HttpRequestHandler {
+
+ private String clientId;
+ private String clientSecret;
+ private String expectedToken;
+
+ public OAuth2TokenRequestHandler(String expectedToken, String clientId, String clientSecret) {
+ this.expectedToken = expectedToken;
+ this.clientId = clientId;
+ this.clientSecret = clientSecret;
+ }
+
+ @Override
+ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context)
+ throws HttpException, IOException {
+
+ String requestBody = EntityUtils.toString(request.getEntity());
+ WWWFormCodec.parse(requestBody, StandardCharsets.UTF_8).stream()
+ .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)))
+ throw new HttpException("Invalid credentials");
+
+ Map<String, String> responseEntity = new HashMap<>();
+ responseEntity.put("access_token", expectedToken);
+
+ response.setEntity(new StringEntity(Jsoner.serialize(responseEntity), ContentType.APPLICATION_JSON));
+ }
+
+}