feat(telegram): Mini App embedding enhancements #136
@@ -18,7 +18,8 @@ import (
|
||||
)
|
||||
|
||||
// ErrInvalidInitData is returned when initData fails HMAC validation, is missing
|
||||
// the hash, is malformed, or is older than the freshness window.
|
||||
// the hash, is malformed, is older than the freshness window, or identifies a bot
|
||||
// user (is_bot), which is denied.
|
||||
var ErrInvalidInitData = errors.New("initdata: invalid telegram init data")
|
||||
|
||||
// defaultMaxAge bounds how old a validated initData payload may be.
|
||||
@@ -120,6 +121,7 @@ func parseUser(userJSON string) (User, error) {
|
||||
}
|
||||
var u struct {
|
||||
ID int64 `json:"id"`
|
||||
IsBot bool `json:"is_bot"`
|
||||
Username string `json:"username"`
|
||||
FirstName string `json:"first_name"`
|
||||
LanguageCode string `json:"language_code"`
|
||||
@@ -127,6 +129,12 @@ func parseUser(userJSON string) (User, error) {
|
||||
if err := json.Unmarshal([]byte(userJSON), &u); err != nil || u.ID == 0 {
|
||||
return User{}, ErrInvalidInitData
|
||||
}
|
||||
// Deny bot principals: the HMAC has already proved Telegram signed this payload, so is_bot==true
|
||||
// is Telegram itself attesting the launching user is a bot. A real user opening the Mini App
|
||||
// never carries it, so reject defensively rather than provision an account for a bot.
|
||||
if u.IsBot {
|
||||
return User{}, ErrInvalidInitData
|
||||
}
|
||||
return User{
|
||||
ExternalID: strconv.FormatInt(u.ID, 10),
|
||||
Username: u.Username,
|
||||
|
||||
@@ -83,3 +83,28 @@ func TestValidateRejects(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateBotUser(t *testing.T) {
|
||||
t.Run("is_bot true is denied", func(t *testing.T) {
|
||||
initData := signInitData(testToken, map[string]string{
|
||||
"auth_date": strconv.FormatInt(time.Now().Unix(), 10),
|
||||
"user": `{"id":42,"is_bot":true,"first_name":"Robo"}`,
|
||||
})
|
||||
if _, err := NewHMACValidator(testToken).Validate(initData); !errors.Is(err, ErrInvalidInitData) {
|
||||
t.Errorf("err = %v, want ErrInvalidInitData", err)
|
||||
}
|
||||
})
|
||||
t.Run("is_bot false is allowed", func(t *testing.T) {
|
||||
initData := signInitData(testToken, map[string]string{
|
||||
"auth_date": strconv.FormatInt(time.Now().Unix(), 10),
|
||||
"user": `{"id":42,"is_bot":false,"first_name":"Thomas"}`,
|
||||
})
|
||||
u, err := NewHMACValidator(testToken).Validate(initData)
|
||||
if err != nil {
|
||||
t.Fatalf("validate: %v", err)
|
||||
}
|
||||
if u.ExternalID != "42" || u.FirstName != "Thomas" {
|
||||
t.Errorf("user = %+v, want {42 Thomas}", u)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user