This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.18.x by this push:
new 2a36b7602632 [backport camel-4.18.x] CAMEL-25564: camel-telegram -
verify the Bot API secret token on webhook updates (#27778)
2a36b7602632 is described below
commit 2a36b7602632bd827cdfc8344ba9d847a6bcabab
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Oct 14 21:21:21 2026 +0200
[backport camel-4.18.x] CAMEL-25564: camel-telegram - verify the Bot API
secret token on webhook updates (#27778)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
---
.../apache/camel/catalog/components/telegram.json | 4 +-
.../telegram/TelegramEndpointConfigurer.java | 12 ++
.../telegram/TelegramEndpointUriFactory.java | 7 +-
.../apache/camel/component/telegram/telegram.json | 4 +-
.../src/main/docs/telegram-component.adoc | 12 ++
.../component/telegram/TelegramConfiguration.java | 30 +++++
.../camel/component/telegram/TelegramEndpoint.java | 52 +++++++-
.../camel/component/telegram/TelegramService.java | 10 ++
.../telegram/TelegramWebhookProcessor.java | 34 ++++-
.../telegram/service/TelegramAsyncHandler.java | 12 +-
.../service/TelegramServiceRestBotAPIAdapter.java | 32 +++--
.../telegram/TelegramWebhookCallTest.java | 82 ++++++++++--
.../telegram/TelegramWebhookSecretTokenTest.java | 132 +++++++++++++++++++
.../TelegramServiceRestBotAPIAdapterErrorTest.java | 139 +++++++++++++++++++++
.../dsl/TelegramEndpointBuilderFactory.java | 59 +++++++++
15 files changed, 594 insertions(+), 27 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/telegram.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/telegram.json
index eab0e6c682ef..7c0ea7163fba 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/telegram.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/telegram.json
@@ -72,6 +72,8 @@
"startScheduler": { "index": 27, "kind": "parameter", "displayName":
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler",
"required": false, "type": "boolean", "javaType": "boolean", "deprecated":
false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Whether the scheduler should be auto started." },
"timeUnit": { "index": 28, "kind": "parameter", "displayName": "Time
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false,
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS",
"DAYS" ], "deprecated": false, "autowired": false, "secret": false,
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and
delay options." },
"useFixedDelay": { "index": 29, "kind": "parameter", "displayName": "Use
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in
JDK for details." },
- "authorizationToken": { "index": 30, "kind": "parameter", "displayName":
"Authorization Token", "group": "security", "label": "security", "required":
true, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true,
"configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "The authorization token
for using the bot (ask the BotFather)" }
+ "authorizationToken": { "index": 30, "kind": "parameter", "displayName":
"Authorization Token", "group": "security", "label": "security", "required":
true, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true,
"configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "The authorization token
for using the bot (ask the BotFather)" },
+ "webhookSecretToken": { "index": 31, "kind": "parameter", "displayName":
"Webhook Secret Token", "group": "security", "label": "consumer,security",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": true, "configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "The secret token that
Telegram sends in the X-Telegram-Bot-Api-Secret-Token [...]
+ "webhookSecretTokenEnabled": { "index": 32, "kind": "parameter",
"displayName": "Webhook Secret Token Enabled", "group": "security", "label":
"consumer,security", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": true, "configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "Whether, in webhook
mode, Camel registers the [...]
}
}
diff --git
a/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointConfigurer.java
b/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointConfigurer.java
index adb41c6ee40e..3a83db6e02f8 100644
---
a/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointConfigurer.java
+++
b/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointConfigurer.java
@@ -77,6 +77,10 @@ public class TelegramEndpointConfigurer extends
PropertyConfigurerSupport implem
case "timeout":
target.getConfiguration().setTimeout(property(camelContext,
java.lang.Integer.class, value)); return true;
case "usefixeddelay":
case "useFixedDelay": target.setUseFixedDelay(property(camelContext,
boolean.class, value)); return true;
+ case "webhooksecrettoken":
+ case "webhookSecretToken":
target.getConfiguration().setWebhookSecretToken(property(camelContext,
java.lang.String.class, value)); return true;
+ case "webhooksecrettokenenabled":
+ case "webhookSecretTokenEnabled":
target.getConfiguration().setWebhookSecretTokenEnabled(property(camelContext,
boolean.class, value)); return true;
default: return false;
}
}
@@ -138,6 +142,10 @@ public class TelegramEndpointConfigurer extends
PropertyConfigurerSupport implem
case "timeout": return java.lang.Integer.class;
case "usefixeddelay":
case "useFixedDelay": return boolean.class;
+ case "webhooksecrettoken":
+ case "webhookSecretToken": return java.lang.String.class;
+ case "webhooksecrettokenenabled":
+ case "webhookSecretTokenEnabled": return boolean.class;
default: return null;
}
}
@@ -200,6 +208,10 @@ public class TelegramEndpointConfigurer extends
PropertyConfigurerSupport implem
case "timeout": return target.getConfiguration().getTimeout();
case "usefixeddelay":
case "useFixedDelay": return target.isUseFixedDelay();
+ case "webhooksecrettoken":
+ case "webhookSecretToken": return
target.getConfiguration().getWebhookSecretToken();
+ case "webhooksecrettokenenabled":
+ case "webhookSecretTokenEnabled": return
target.getConfiguration().isWebhookSecretTokenEnabled();
default: return null;
}
}
diff --git
a/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointUriFactory.java
b/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointUriFactory.java
index 52616c4907c8..110d6dad9a33 100644
---
a/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointUriFactory.java
+++
b/components/camel-telegram/src/generated/java/org/apache/camel/component/telegram/TelegramEndpointUriFactory.java
@@ -23,7 +23,7 @@ public class TelegramEndpointUriFactory extends
org.apache.camel.support.compone
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Map<String, String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(31);
+ Set<String> props = new HashSet<>(33);
props.add("authorizationToken");
props.add("backoffErrorThreshold");
props.add("backoffIdleThreshold");
@@ -55,9 +55,12 @@ public class TelegramEndpointUriFactory extends
org.apache.camel.support.compone
props.add("timeout");
props.add("type");
props.add("useFixedDelay");
+ props.add("webhookSecretToken");
+ props.add("webhookSecretTokenEnabled");
PROPERTY_NAMES = Collections.unmodifiableSet(props);
- Set<String> secretProps = new HashSet<>(1);
+ Set<String> secretProps = new HashSet<>(2);
secretProps.add("authorizationToken");
+ secretProps.add("webhookSecretToken");
SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
Map<String, String> prefixes = new HashMap<>(1);
prefixes.put("schedulerProperties", "scheduler.");
diff --git
a/components/camel-telegram/src/generated/resources/META-INF/org/apache/camel/component/telegram/telegram.json
b/components/camel-telegram/src/generated/resources/META-INF/org/apache/camel/component/telegram/telegram.json
index eab0e6c682ef..7c0ea7163fba 100644
---
a/components/camel-telegram/src/generated/resources/META-INF/org/apache/camel/component/telegram/telegram.json
+++
b/components/camel-telegram/src/generated/resources/META-INF/org/apache/camel/component/telegram/telegram.json
@@ -72,6 +72,8 @@
"startScheduler": { "index": 27, "kind": "parameter", "displayName":
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler",
"required": false, "type": "boolean", "javaType": "boolean", "deprecated":
false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Whether the scheduler should be auto started." },
"timeUnit": { "index": 28, "kind": "parameter", "displayName": "Time
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false,
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS",
"DAYS" ], "deprecated": false, "autowired": false, "secret": false,
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and
delay options." },
"useFixedDelay": { "index": 29, "kind": "parameter", "displayName": "Use
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in
JDK for details." },
- "authorizationToken": { "index": 30, "kind": "parameter", "displayName":
"Authorization Token", "group": "security", "label": "security", "required":
true, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true,
"configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "The authorization token
for using the bot (ask the BotFather)" }
+ "authorizationToken": { "index": 30, "kind": "parameter", "displayName":
"Authorization Token", "group": "security", "label": "security", "required":
true, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true,
"configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "The authorization token
for using the bot (ask the BotFather)" },
+ "webhookSecretToken": { "index": 31, "kind": "parameter", "displayName":
"Webhook Secret Token", "group": "security", "label": "consumer,security",
"required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": true, "configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "The secret token that
Telegram sends in the X-Telegram-Bot-Api-Secret-Token [...]
+ "webhookSecretTokenEnabled": { "index": 32, "kind": "parameter",
"displayName": "Webhook Secret Token Enabled", "group": "security", "label":
"consumer,security", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": true, "configurationClass":
"org.apache.camel.component.telegram.TelegramConfiguration",
"configurationField": "configuration", "description": "Whether, in webhook
mode, Camel registers the [...]
}
}
diff --git a/components/camel-telegram/src/main/docs/telegram-component.adoc
b/components/camel-telegram/src/main/docs/telegram-component.adoc
index 429c296e1ef7..911ab2ff903c 100644
--- a/components/camel-telegram/src/main/docs/telegram-component.adoc
+++ b/components/camel-telegram/src/main/docs/telegram-component.adoc
@@ -346,5 +346,17 @@ You need to ensure that your server is exposed to the
internet and to pass the r
Refer to the *camel-webhook* component documentation for instructions on how
to set it.
+Camel registers the webhook with a secret token, which Telegram sends back in
the `X-Telegram-Bot-Api-Secret-Token`
+header of every webhook request. A webhook request that does not carry the
token is rejected with HTTP 403, and does
+not reach the route. By default, the token is derived from the authorization
token, so it stays the same across
+restarts and replicas. If the webhook is registered outside Camel, set the
`webhookSecretToken` option, and pass the
+same value as the `secret_token` parameter of the `setWebhook` method of the
Telegram Bot API.
+
+The default webhook path is a hash of the endpoint URI, so adding an option to
the URI, such as `webhookSecretToken`,
+changes the path. When the webhook is registered outside Camel, set the path
with the `webhookPath` option of the
+*camel-webhook* component.
+
+Setting `webhookSecretTokenEnabled=false` registers the webhook without a
secret token, and accepts webhook requests
+without verifying them, as earlier versions did.
include::spring-boot:partial$starter.adoc[]
diff --git
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramConfiguration.java
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramConfiguration.java
index 6054e657f123..17ddb70aea68 100644
---
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramConfiguration.java
+++
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramConfiguration.java
@@ -61,6 +61,20 @@ public class TelegramConfiguration {
optionalPrefix = "consumer.", defaultValue = "100", label =
"consumer")
private Integer limit = 100;
+ @UriParam(description = "The secret token that Telegram sends in the
X-Telegram-Bot-Api-Secret-Token header of every webhook request."
+ + " In webhook mode, Camel registers the webhook
with this token, and rejects a webhook request that does not"
+ + " carry it with HTTP 403. Only the characters
A-Z, a-z, 0-9, _ and - are allowed, up to 256 characters."
+ + " When not set, a token derived from the
authorization token is used. Set it when the webhook is"
+ + " registered outside Camel, and register the
webhook with the same secret_token.",
+ label = "consumer,security", secret = true)
+ private String webhookSecretToken;
+
+ @UriParam(description = "Whether, in webhook mode, Camel registers the
webhook with a secret token and rejects a webhook request"
+ + " that does not carry it. Set it to false to
restore the behaviour of earlier versions, where the webhook"
+ + " was registered without a secret token and
webhook requests were not verified.",
+ label = "consumer,security", defaultValue = "true")
+ private boolean webhookSecretTokenEnabled = true;
+
@UriParam(label = "advanced",
description = "Can be used to set an alternative base URI, e.g.
when you want to test the component against a mock Telegram API")
private String baseUri;
@@ -132,6 +146,22 @@ public class TelegramConfiguration {
this.limit = limit;
}
+ public String getWebhookSecretToken() {
+ return webhookSecretToken;
+ }
+
+ public void setWebhookSecretToken(String webhookSecretToken) {
+ this.webhookSecretToken = webhookSecretToken;
+ }
+
+ public boolean isWebhookSecretTokenEnabled() {
+ return webhookSecretTokenEnabled;
+ }
+
+ public void setWebhookSecretTokenEnabled(boolean
webhookSecretTokenEnabled) {
+ this.webhookSecretTokenEnabled = webhookSecretTokenEnabled;
+ }
+
public String getBaseUri() {
return baseUri;
}
diff --git
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramEndpoint.java
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramEndpoint.java
index b3530de0724b..f1f248bb383e 100644
---
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramEndpoint.java
+++
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramEndpoint.java
@@ -19,8 +19,15 @@ package org.apache.camel.component.telegram;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.http.HttpClient;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.util.Base64;
import java.util.Collections;
import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
import org.apache.camel.Category;
import org.apache.camel.Component;
@@ -46,6 +53,7 @@ import org.slf4j.LoggerFactory;
category = { Category.CLOUD, Category.API, Category.CHAT },
headersClass = TelegramConstants.class)
public class TelegramEndpoint extends ScheduledPollEndpoint implements
WebhookCapableEndpoint, EndpointServiceLocation {
private static final Logger LOG =
LoggerFactory.getLogger(TelegramEndpoint.class);
+ private static final Pattern WEBHOOK_SECRET_TOKEN_PATTERN =
Pattern.compile("[A-Za-z0-9_-]{1,256}");
@UriParam
private TelegramConfiguration configuration;
@@ -122,16 +130,56 @@ public class TelegramEndpoint extends
ScheduledPollEndpoint implements WebhookCa
@Override
public Processor createWebhookHandler(Processor next) {
- return new TelegramWebhookProcessor(next);
+ if (!configuration.isWebhookSecretTokenEnabled()) {
+ LOG.warn("The webhook secret token is disabled
(webhookSecretTokenEnabled=false): webhook requests to {} are not"
+ + " verified",
+ this);
+ return new TelegramWebhookProcessor(next, null);
+ }
+ return new TelegramWebhookProcessor(next, resolveWebhookSecretToken());
}
@Override
public void registerWebhook() throws Exception {
- if
(!telegramService.setWebhook(webhookConfiguration.computeFullExternalUrl())) {
+ String url = webhookConfiguration.computeFullExternalUrl();
+ boolean registered = configuration.isWebhookSecretTokenEnabled()
+ ? telegramService.setWebhook(url, resolveWebhookSecretToken())
+ : telegramService.setWebhook(url);
+ if (!registered) {
throw new RuntimeCamelException("The Telegram API refused to
register a webhook");
}
}
+ /**
+ * Returns the secret token of the webhook: the configured one, or else
one derived from the authorization token,
+ * which stays the same across restarts and replicas.
+ */
+ String resolveWebhookSecretToken() {
+ String token = configuration.getWebhookSecretToken();
+ if (token == null) {
+ return
deriveWebhookSecretToken(configuration.getAuthorizationToken());
+ }
+ if (!WEBHOOK_SECRET_TOKEN_PATTERN.matcher(token).matches()) {
+ throw new IllegalArgumentException(
+ "The webhookSecretToken must be 1 to 256 characters long,
using only A-Z, a-z, 0-9, _ and -");
+ }
+ return token;
+ }
+
+ static String deriveWebhookSecretToken(String authorizationToken) {
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ // the authorization token (the secret) is the key, and a fixed
label is the message: the derived token
+ // cannot be computed without the authorization token, and changes
only when the authorization token does
+ mac.init(new
SecretKeySpec(authorizationToken.getBytes(StandardCharsets.UTF_8),
"HmacSHA256"));
+ byte[] digest =
mac.doFinal("camel-telegram-webhook-secret-token".getBytes(StandardCharsets.UTF_8));
+ // base64url without padding only uses the characters that
Telegram allows in a secret token
+ return
Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
+ } catch (GeneralSecurityException e) {
+ throw new RuntimeCamelException("Cannot derive the webhook secret
token", e);
+ }
+ }
+
@Override
public void unregisterWebhook() throws Exception {
if (!telegramService.removeWebhook()) {
diff --git
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramService.java
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramService.java
index 387c4c773156..3610ac29e03e 100644
---
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramService.java
+++
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramService.java
@@ -38,6 +38,16 @@ public interface TelegramService {
boolean setWebhook(String url);
+ /**
+ * Registers the webhook. Telegram sends the given secret token in the
{@code X-Telegram-Bot-Api-Secret-Token}
+ * header of every webhook request.
+ *
+ * @param url the URL of the webhook
+ * @param secretToken the secret token
+ * @return {@code true} if Telegram registered the webhook
+ */
+ boolean setWebhook(String url, String secretToken);
+
boolean removeWebhook();
}
diff --git
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramWebhookProcessor.java
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramWebhookProcessor.java
index 3479555b58b2..2876a708a720 100644
---
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramWebhookProcessor.java
+++
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/TelegramWebhookProcessor.java
@@ -17,6 +17,8 @@
package org.apache.camel.component.telegram;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.camel.AsyncCallback;
@@ -26,21 +28,51 @@ import org.apache.camel.Processor;
import org.apache.camel.component.telegram.model.Update;
import org.apache.camel.support.AsyncProcessorConverterHelper;
import org.apache.camel.support.AsyncProcessorSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import static
org.apache.camel.component.telegram.util.TelegramMessageHelper.populateExchange;
public class TelegramWebhookProcessor extends AsyncProcessorSupport {
+ /**
+ * The header in which Telegram sends the secret token the webhook was
registered with.
+ */
+ public static final String SECRET_TOKEN_HEADER =
"X-Telegram-Bot-Api-Secret-Token";
+
+ private static final Logger LOG =
LoggerFactory.getLogger(TelegramWebhookProcessor.class);
private static final ObjectMapper MAPPER = new ObjectMapper();
private AsyncProcessor next;
+ private final byte[] secretToken;
- public TelegramWebhookProcessor(Processor next) {
+ /**
+ * @param next the processor that receives the updates
+ * @param secretToken the secret token that a webhook request must carry,
or {@code null} to accept every webhook
+ * request without verifying it
+ */
+ public TelegramWebhookProcessor(Processor next, String secretToken) {
this.next = AsyncProcessorConverterHelper.convert(next);
+ this.secretToken = secretToken != null ?
secretToken.getBytes(StandardCharsets.UTF_8) : null;
}
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
+ if (secretToken != null) {
+ String token = exchange.getIn().getHeader(SECRET_TOKEN_HEADER,
String.class);
+ if (token == null || !MessageDigest.isEqual(secretToken,
token.getBytes(StandardCharsets.UTF_8))) {
+ LOG.warn("Rejecting a Telegram webhook request with a missing
or invalid {} header."
+ + " A webhook registered outside Camel must use the
webhookSecretToken as its secret_token.",
+ SECRET_TOKEN_HEADER);
+ exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE,
403);
+ exchange.getMessage().setBody("");
+ callback.done(true);
+ return true;
+ }
+ }
+ // the token is not passed on to the route
+ exchange.getIn().removeHeader(SECRET_TOKEN_HEADER);
+
// Let's process the body and transform it into a Telegram incoming
message
Update update;
try (InputStream source = exchange.getIn().getBody(InputStream.class))
{
diff --git
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramAsyncHandler.java
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramAsyncHandler.java
index 3b180356d1a8..c6b9ad6b4068 100644
---
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramAsyncHandler.java
+++
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramAsyncHandler.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
+import java.net.URI;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
@@ -38,7 +39,8 @@ import org.slf4j.LoggerFactory;
public class TelegramAsyncHandler {
private static final Logger LOG =
LoggerFactory.getLogger(TelegramAsyncHandler.class);
- private final String uri;
+ // describes the request without its URI, which contains the authorization
token
+ private final String request;
private final Class<? extends MessageResult> resultClass;
private final ObjectMapper mapper;
private final Exchange exchange;
@@ -46,7 +48,7 @@ public class TelegramAsyncHandler {
TelegramAsyncHandler(String uri, Class<? extends MessageResult>
resultClass, ObjectMapper mapper, Exchange exchange,
AsyncCallback callback) {
- this.uri = uri;
+ this.request = TelegramServiceRestBotAPIAdapter.describe("POST",
URI.create(uri));
this.resultClass = resultClass;
this.mapper = mapper;
this.exchange = exchange;
@@ -97,7 +99,7 @@ public class TelegramAsyncHandler {
if (success) {
if (LOG.isTraceEnabled()) {
final String body = IOHelper.toString(r);
- LOG.trace("Received body for {}: {}", uri, body);
+ LOG.trace("Received body for {}: {}", request, body);
result = mapper.readValue(body, resultClass);
} else {
result = mapper.readValue(r, resultClass);
@@ -106,12 +108,12 @@ public class TelegramAsyncHandler {
exchange.getMessage().setBody(result);
} else {
throw new RuntimeCamelException(
- uri + " responded: " + response.statusCode() +
IOHelper.toString(r));
+ request + " responded: " + response.statusCode() +
IOHelper.toString(r));
}
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
} catch (IOException ex) {
- throw new RuntimeCamelException("Could not parse the response from
" + uri, ex);
+ throw new RuntimeCamelException("Could not parse the response from
" + request, ex);
} finally {
callback.done(false);
}
diff --git
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapter.java
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapter.java
index e96a3bb184f5..a509dfbb7eb1 100644
---
a/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapter.java
+++
b/components/camel-telegram/src/main/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapter.java
@@ -19,9 +19,11 @@ package org.apache.camel.component.telegram.service;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@@ -152,6 +154,7 @@ public class TelegramServiceRestBotAPIAdapter implements
TelegramService {
}
<T> T sendSyncRequest(final HttpRequest request, Class<T> resultType) {
+ final String description = describe(request.method(), request.uri());
try {
final HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
@@ -159,29 +162,44 @@ public class TelegramServiceRestBotAPIAdapter implements
TelegramService {
if (code >= 200 && code < 300) {
final String responseBody = response.body();
if (LOG.isTraceEnabled()) {
- LOG.trace("Received body for {} {}: {}", request.method(),
request.uri(), responseBody);
+ LOG.trace("Received body for {}: {}", description,
responseBody);
}
return mapper.readValue(responseBody, resultType);
} else {
throw new TelegramException(
- "Could not " + request.method() + " " + request.uri()
+ ": " + response.statusCode() + " "
- + response.body(),
+ "Could not " + description + ": " +
response.statusCode() + " " + response.body(),
response.statusCode(), response.body());
}
} catch (JsonProcessingException e) {
- throw new RuntimeCamelException(
- "Could not parse the response from " + request.method() +
" " + request.uri(), e);
+ throw new RuntimeCamelException("Could not parse the response from
" + description, e);
} catch (IOException e) {
- throw new RuntimeCamelException("Could not request " +
request.method() + " " + request.uri(), e);
+ throw new RuntimeCamelException("Could not request " +
description, e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeCamelException(e);
}
}
+ /**
+ * Describes a request to the Bot API in logs and exception messages by
its HTTP method and the method of the Bot
+ * API, such as {@code GET getUpdates}. The request URI is not used, as it
contains the authorization token.
+ */
+ static String describe(String httpMethod, URI uri) {
+ String path = uri.getPath();
+ return httpMethod + " " + path.substring(path.lastIndexOf('/') + 1);
+ }
+
@Override
public boolean setWebhook(String url) {
- final String uri = baseUri + "/setWebhook?url=" + url;
+ return setWebhook(url, null);
+ }
+
+ @Override
+ public boolean setWebhook(String url, String secretToken) {
+ String uri = baseUri + "/setWebhook?url=" + url;
+ if (secretToken != null) {
+ uri += "&secret_token=" + URLEncoder.encode(secretToken,
StandardCharsets.UTF_8);
+ }
final HttpRequest.Builder request =
HttpRequest.newBuilder().uri(URI.create(uri)).GET();
diff --git
a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookCallTest.java
b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookCallTest.java
index da43e2747376..33418af7ae70 100644
---
a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookCallTest.java
+++
b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookCallTest.java
@@ -28,26 +28,80 @@ import org.apache.camel.component.webhook.WebhookEndpoint;
import org.apache.camel.test.AvailablePortFinder;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
/**
- * Tests a producer that sends media information.
+ * Tests the webhook endpoint that receives the updates from Telegram.
*/
public class TelegramWebhookCallTest extends TelegramTestSupport {
+ private static final String CONFIGURED_SECRET_TOKEN =
"configured_Secret-token-42";
+
private int port;
@Test
public void testWebhookCall() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:endpoint");
+ mock.expectedBodiesReceived("aho");
+
mock.message(0).header(TelegramWebhookProcessor.SECRET_TOKEN_HEADER).isNull();
+
+ Exchange response = call("webhook",
TelegramEndpoint.deriveWebhookSecretToken("mock-token"));
+
+ assertEquals(204,
response.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class));
+ mock.assertIsSatisfied();
+ }
+
+ @Test
+ void testWebhookCallWithConfiguredSecretToken() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:endpoint");
+ mock.expectedBodiesReceived("aho");
+
+ Exchange response = call("webhook-configured-token",
CONFIGURED_SECRET_TOKEN);
+
+ assertEquals(204,
response.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class));
+ mock.assertIsSatisfied();
+ }
+
+ @Test
+ void testWebhookCallWithoutSecretTokenIsRejected() throws Exception {
+ Exchange response = call("webhook", null);
+
+ assertEquals(403,
response.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class));
+ assertEquals(0, getMockEndpoint("mock:endpoint").getReceivedCounter());
+ }
+
+ @Test
+ void testWebhookCallWithWrongSecretTokenIsRejected() throws Exception {
+ Exchange response = call("webhook", CONFIGURED_SECRET_TOKEN);
+
+ assertEquals(403,
response.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class));
+ assertEquals(0, getMockEndpoint("mock:endpoint").getReceivedCounter());
+ }
+
+ @Test
+ void testWebhookCallWithoutSecretTokenWhenDisabled() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:endpoint");
+ mock.expectedBodiesReceived("aho");
+
+ Exchange response = call("webhook-secret-token-disabled", null);
+
+ assertEquals(204,
response.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class));
+ mock.assertIsSatisfied();
+ }
+
+ private Exchange call(String routeId, String secretToken) throws Exception
{
WebhookConfiguration config
- = ((WebhookEndpoint)
context().getRoute("webhook").getConsumer().getEndpoint()).getConfiguration();
+ = ((WebhookEndpoint)
context().getRoute(routeId).getConsumer().getEndpoint()).getConfiguration();
String url = config.computeFullExternalUrl();
try (InputStream content =
getClass().getClassLoader().getResourceAsStream("messages/webhook-call.json")) {
- MockEndpoint mock = getMockEndpoint("mock:endpoint");
- mock.expectedBodiesReceived("aho");
- mock.expectedMinimumMessageCount(1);
-
- template().sendBodyAndHeader("netty-http:" + url, content,
Exchange.CONTENT_TYPE, "application/json");
- mock.assertIsSatisfied();
+ return template().request("netty-http:" + url +
"?throwExceptionOnFailure=false", exchange -> {
+ exchange.getIn().setBody(content);
+ exchange.getIn().setHeader(Exchange.CONTENT_TYPE,
"application/json");
+ if (secretToken != null) {
+
exchange.getIn().setHeader(TelegramWebhookProcessor.SECRET_TOKEN_HEADER,
secretToken);
+ }
+ });
}
}
@@ -69,6 +123,18 @@ public class TelegramWebhookCallTest extends
TelegramTestSupport {
.id("webhook")
.convertBodyTo(String.class)
.to("mock:endpoint");
+
+
from("webhook:telegram:bots?authorizationToken=mock-token&webhookAutoRegister=false&webhookSecretToken="
+ + CONFIGURED_SECRET_TOKEN)
+ .id("webhook-configured-token")
+ .convertBodyTo(String.class)
+ .to("mock:endpoint");
+
+
from("webhook:telegram:bots?authorizationToken=mock-token&webhookAutoRegister=false"
+ + "&webhookSecretTokenEnabled=false")
+ .id("webhook-secret-token-disabled")
+ .convertBodyTo(String.class)
+ .to("mock:endpoint");
}
};
}
diff --git
a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookSecretTokenTest.java
b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookSecretTokenTest.java
new file mode 100644
index 000000000000..2520ec87cb89
--- /dev/null
+++
b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramWebhookSecretTokenTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.telegram;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.telegram.model.WebhookResult;
+import org.apache.camel.component.telegram.util.TelegramTestSupport;
+import org.apache.camel.component.telegram.util.TelegramTestUtil;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.test.AvailablePortFinder;
+import org.junit.jupiter.api.Test;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests the secret token that the webhook is registered with.
+ */
+class TelegramWebhookSecretTokenTest extends TelegramTestSupport {
+
+ private final List<String> setWebhookQueries = new
CopyOnWriteArrayList<>();
+
+ @Test
+ void derivedSecretTokenIsStableAndUsesOnlyTheAllowedCharacters() {
+ String token = TelegramEndpoint.deriveWebhookSecretToken("mock-token");
+
+ assertEquals(token,
TelegramEndpoint.deriveWebhookSecretToken("mock-token"));
+ assertNotEquals(token,
TelegramEndpoint.deriveWebhookSecretToken("another-token"));
+ assertTrue(token.matches("[A-Za-z0-9_-]{43}"), token);
+ }
+
+ @Test
+ void invalidConfiguredSecretTokenIsRefused() {
+ TelegramEndpoint endpoint = context().getEndpoint(
+
"telegram:bots?authorizationToken=mock-token&webhookSecretToken=invalid.token",
TelegramEndpoint.class);
+
+ assertThrows(IllegalArgumentException.class,
endpoint::resolveWebhookSecretToken);
+ }
+
+ @Test
+ void registrationSendsTheDerivedSecretToken() throws Exception {
+ String query =
register("webhook:telegram:bots?webhookPath=/my-test&webhook-external-url=http://my-domain.com");
+
+ assertEquals("url=http://my-domain.com/my-test&secret_token=" +
TelegramEndpoint.deriveWebhookSecretToken("mock-token"),
+ query);
+ }
+
+ @Test
+ void registrationSendsTheConfiguredSecretToken() throws Exception {
+ String query =
register("webhook:telegram:bots?webhookPath=/my-test&webhook-external-url=http://my-domain.com"
+ +
"&webhookSecretToken=configured_Secret-token-42");
+
+
assertEquals("url=http://my-domain.com/my-test&secret_token=configured_Secret-token-42",
query);
+ }
+
+ @Test
+ void registrationSendsNoSecretTokenWhenDisabled() throws Exception {
+ String query =
register("webhook:telegram:bots?webhookPath=/my-test&webhook-external-url=http://my-domain.com"
+ + "&webhookSecretTokenEnabled=false");
+
+ assertEquals("url=http://my-domain.com/my-test", query);
+ }
+
+ /**
+ * Starts a webhook route against a mock Telegram API, and returns the
query of the setWebhook call.
+ */
+ private String register(String webhookUri) throws Exception {
+ WebhookResult result = new WebhookResult();
+ result.setOk(true);
+ result.setResult(true);
+ String response = TelegramTestUtil.serialize(result);
+
+ try (DefaultCamelContext mockContext = new DefaultCamelContext()) {
+ mockContext.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ String api = "netty-http:http://localhost:" + port +
"/botmock-token/";
+ from(api + "setWebhook?httpMethodRestrict=GET")
+ .process(exchange -> setWebhookQueries
+
.add(exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class)))
+ .setBody(constant(response));
+ from(api + "deleteWebhook?httpMethodRestrict=GET")
+ .setBody(constant(response));
+ }
+ });
+ mockContext.start();
+
+ context().addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ restConfiguration()
+ .host("localhost")
+ .port(AvailablePortFinder.getNextAvailable());
+
+ from(webhookUri).to("mock:endpoint");
+ }
+ });
+ context().start();
+ await().atMost(5, TimeUnit.SECONDS).until(() ->
!setWebhookQueries.isEmpty());
+ context().stop();
+ }
+ assertEquals(1, setWebhookQueries.size());
+ return setWebhookQueries.get(0);
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+}
diff --git
a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapterErrorTest.java
b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapterErrorTest.java
new file mode 100644
index 000000000000..9326b8338a0e
--- /dev/null
+++
b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/service/TelegramServiceRestBotAPIAdapterErrorTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.telegram.service;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.net.ssl.SSLSession;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.telegram.TelegramException;
+import org.apache.camel.component.telegram.model.MessageResult;
+import org.apache.camel.component.telegram.util.TelegramMockRoutes;
+import org.apache.camel.component.telegram.util.TelegramTestSupport;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests that the errors of the Bot API requests do not show the request URI,
which contains the authorization token.
+ */
+class TelegramServiceRestBotAPIAdapterErrorTest extends TelegramTestSupport {
+
+ @Test
+ void describeUsesTheMethodOfTheBotApi() {
+ assertEquals("GET getUpdates",
+ TelegramServiceRestBotAPIAdapter.describe("GET",
+
URI.create("https://api.telegram.org/bot123456:authorization-token/getUpdates?offset=1&limit=100")));
+ }
+
+ @Test
+ void errorDoesNotShowTheRequestUri() {
+ TelegramServiceRestBotAPIAdapter adapter = new
TelegramServiceRestBotAPIAdapter(
+ HttpClient.newHttpClient(), "http://localhost:" + port,
"mock-token", 1024);
+
+ TelegramException e = assertThrows(TelegramException.class,
+ () -> adapter.setWebhook("http://my-domain.com/my-test",
"my-secret-token"));
+
+ assertTrue(e.getMessage().startsWith("Could not GET setWebhook: 401"),
e.getMessage());
+ assertFalse(e.getMessage().contains("mock-token"), e.getMessage());
+ assertFalse(e.getMessage().contains("my-secret-token"),
e.getMessage());
+ }
+
+ @Test
+ void asyncErrorDoesNotShowTheRequestUri() {
+ TelegramAsyncHandler handler = new TelegramAsyncHandler(
+ "http://localhost:" + port + "/botmock-token/sendMessage",
MessageResult.class, new ObjectMapper(),
+ new DefaultExchange(context()), doneSync -> {
+ });
+
+ RuntimeCamelException e = assertThrows(RuntimeCamelException.class,
+ () -> handler.handleCompressedResponse(response(400,
"{\"ok\":false}")));
+
+ assertEquals("POST sendMessage responded: 400{\"ok\":false}",
e.getMessage());
+ }
+
+ private static HttpResponse<InputStream> response(int statusCode, String
body) {
+ return new HttpResponse<>() {
+ @Override
+ public int statusCode() {
+ return statusCode;
+ }
+
+ @Override
+ public HttpRequest request() {
+ return null;
+ }
+
+ @Override
+ public Optional<HttpResponse<InputStream>> previousResponse() {
+ return Optional.empty();
+ }
+
+ @Override
+ public HttpHeaders headers() {
+ return HttpHeaders.of(Map.of(), (name, value) -> true);
+ }
+
+ @Override
+ public InputStream body() {
+ return new
ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public Optional<SSLSession> sslSession() {
+ return Optional.empty();
+ }
+
+ @Override
+ public URI uri() {
+ return null;
+ }
+
+ @Override
+ public HttpClient.Version version() {
+ return HttpClient.Version.HTTP_1_1;
+ }
+ };
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() {
+ return getMockRoutes();
+ }
+
+ @Override
+ protected TelegramMockRoutes createMockRoutes() {
+ return new TelegramMockRoutes(port)
+ .addErrorEndpoint("setWebhook", "GET", 401);
+ }
+}
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TelegramEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TelegramEndpointBuilderFactory.java
index 140878e86aa9..31abbbf12546 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TelegramEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TelegramEndpointBuilderFactory.java
@@ -692,6 +692,65 @@ public interface TelegramEndpointBuilderFactory {
doSetProperty("authorizationToken", authorizationToken);
return this;
}
+ /**
+ * The secret token that Telegram sends in the
+ * X-Telegram-Bot-Api-Secret-Token header of every webhook request. In
+ * webhook mode, Camel registers the webhook with this token, and
+ * rejects a webhook request that does not carry it with HTTP 403. Only
+ * the characters A-Z, a-z, 0-9, _ and - are allowed, up to 256
+ * characters. When not set, a token derived from the authorization
+ * token is used. Set it when the webhook is registered outside Camel,
+ * and register the webhook with the same secret_token.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: security
+ *
+ * @param webhookSecretToken the value to set
+ * @return the dsl builder
+ */
+ default TelegramEndpointConsumerBuilder webhookSecretToken(String
webhookSecretToken) {
+ doSetProperty("webhookSecretToken", webhookSecretToken);
+ return this;
+ }
+ /**
+ * Whether, in webhook mode, Camel registers the webhook with a secret
+ * token and rejects a webhook request that does not carry it. Set it
to
+ * false to restore the behaviour of earlier versions, where the
webhook
+ * was registered without a secret token and webhook requests were not
+ * verified.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: security
+ *
+ * @param webhookSecretTokenEnabled the value to set
+ * @return the dsl builder
+ */
+ default TelegramEndpointConsumerBuilder
webhookSecretTokenEnabled(boolean webhookSecretTokenEnabled) {
+ doSetProperty("webhookSecretTokenEnabled",
webhookSecretTokenEnabled);
+ return this;
+ }
+ /**
+ * Whether, in webhook mode, Camel registers the webhook with a secret
+ * token and rejects a webhook request that does not carry it. Set it
to
+ * false to restore the behaviour of earlier versions, where the
webhook
+ * was registered without a secret token and webhook requests were not
+ * verified.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: security
+ *
+ * @param webhookSecretTokenEnabled the value to set
+ * @return the dsl builder
+ */
+ default TelegramEndpointConsumerBuilder
webhookSecretTokenEnabled(String webhookSecretTokenEnabled) {
+ doSetProperty("webhookSecretTokenEnabled",
webhookSecretTokenEnabled);
+ return this;
+ }
}
/**