Проверка подписи Telegram Mini App без библиотек
Тридцать строк на Python, чтобы сервер верил только настоящим данным из Telegram.
Мини-приложение получает от Telegram строку initData с данными пользователя и подписью. Доверять ей на сервере можно только после проверки - иначе кто угодно пришлет user.id администратора.
import hashlib
import hmac
import time
from urllib.parse import parse_qsl
def check_init_data(init_data: str, bot_token: str, max_age: int = 86400) -> dict | None:
pairs = dict(parse_qsl(init_data, keep_blank_values=True))
received = pairs.pop("hash", None)
if not received:
return None
# Все поля, кроме hash, по алфавиту, через перевод строки.
check_string = "\n".join(f"{k}={v}" for k, v in sorted(pairs.items()))
secret = hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest()
expected = hmac.new(secret, check_string.encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, received):
return None # чужая или подмененная подпись
if time.time() - int(pairs.get("auth_date", 0)) > max_age:
return None # подпись настоящая, но старая
return pairs
Три вещи, на которых обычно ошибаются:
- Ключ - не токен бота. Сначала HMAC от токена с ключом
WebAppData, и уже им подписывается строка. - Сравнение через
compare_digest, а не==: обычное сравнение отвечает быстрее на первом несовпавшем символе, и по времени ответа можно подбирать подпись. - Срок жизни. Без проверки
auth_dateперехваченная однажды строка работает вечно.