Skip to content

Commit

Permalink
feat(webhook-token): ability to verify webhook secret token inside th…
Browse files Browse the repository at this point in the history
…e bot program
  • Loading branch information
dharsanb committed Jun 18, 2024
1 parent de43730 commit df8ce19
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func main() {

opts := []bot.Option{
bot.WithDefaultHandler(handler),
bot.WithWebhookSecretToken(os.Getenv("EXAMPLE_TELEGRAM_WEBHOOK_SECRET_TOKEN"))
}

b, _ := bot.New(os.Getenv("EXAMPLE_TELEGRAM_BOT_TOKEN"), opts...)
Expand Down Expand Up @@ -181,6 +182,7 @@ b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", opts...)
- `WithSkipGetMe()` - skip call GetMe on bot init
- `WithAllowedUpdates(params AllowedUpdates)` - set [allowed_updates](https://core.telegram.org/bots/api#getupdates) for getUpdates method
- `WithUpdatesChannelCap(cap int)` - set updates channel capacity, by default 1024
- `WithWebhookSecretToken(webhookSecretToken string)` - set X-Telegram-Bot-Api-Secret-Token header sent from telegram servers to confirm validity of update

## Message.Text and CallbackQuery.Data handlers

Expand Down
9 changes: 5 additions & 4 deletions bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ type MatchFunc func(update *models.Update) bool

// Bot represents Telegram Bot main object
type Bot struct {
url string
token string
pollTimeout time.Duration
skipGetMe bool
url string
token string
pollTimeout time.Duration
skipGetMe bool
webhookSecretToken string

defaultHandlerFunc HandlerFunc

Expand Down
4 changes: 3 additions & 1 deletion bot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ func TestBot_StartWebhook(t *testing.T) {
s := newServerMock("xxx")
defer s.Close()

b, err := New("xxx", WithServerURL(s.URL()))
opts := []Option{WithServerURL(s.URL()), WithWebhookSecretToken("zzzz")}
b, err := New("xxx", opts...)
if err != nil {
t.Fatalf("unexpected error %q", err)
}
Expand Down Expand Up @@ -197,6 +198,7 @@ func TestBot_StartWebhook(t *testing.T) {
t.Error(errReq)
return
}
req.Header.Set("X-Telegram-Bot-Api-Secret-Token", "zzzz")

b.WebhookHandler().ServeHTTP(nil, req)

Expand Down
7 changes: 7 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,10 @@ func WithUpdatesChannelCap(cap int) Option {
b.updates = make(chan *models.Update, cap)
}
}

// WithWebhookSecretToken allows setting X-Telegram-Bot-Api-Secret-Token sent from Telegram servers
func WithWebhookSecretToken(webhookSecretToken string) Option {
return func(b *Bot) {
b.webhookSecretToken = webhookSecretToken
}
}
5 changes: 5 additions & 0 deletions webhook_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import (

func (b *Bot) WebhookHandler() http.HandlerFunc {
return func(_ http.ResponseWriter, req *http.Request) {
if b.webhookSecretToken != "" && req.Header.Get("X-Telegram-Bot-Api-Secret-Token") != b.webhookSecretToken {
b.error("invalid webhook secret token received from update")
return
}

body, errReadBody := io.ReadAll(req.Body)
if errReadBody != nil {
b.error("error read request body, %w", errReadBody)
Expand Down

0 comments on commit df8ce19

Please sign in to comment.