import hashlib import hmac import json import time from urllib.parse import parse_qsl class TelegramAuthError(ValueError): pass def validate_telegram_init_data(init_data: str, bot_token: str, max_age_seconds: int = 86400) -> dict: if not bot_token: raise TelegramAuthError("Telegram bot token is required") pairs = dict(parse_qsl(init_data, keep_blank_values=True)) received_hash = pairs.pop("hash", None) if not received_hash: raise TelegramAuthError("Telegram hash is missing") data_check_string = "\n".join(f"{key}={value}" for key, value in sorted(pairs.items())) secret_key = hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest() expected_hash = hmac.new(secret_key, data_check_string.encode(), hashlib.sha256).hexdigest() if not hmac.compare_digest(expected_hash, received_hash): raise TelegramAuthError("Telegram hash is invalid") auth_date_raw = pairs.get("auth_date") if auth_date_raw: try: auth_date = int(auth_date_raw) except ValueError as exc: raise TelegramAuthError("Telegram auth_date is invalid") from exc if max_age_seconds > 0 and time.time() - auth_date > max_age_seconds: raise TelegramAuthError("Telegram initData is expired") user_raw = pairs.get("user") if not user_raw: raise TelegramAuthError("Telegram user is missing") try: user = json.loads(user_raw) except json.JSONDecodeError as exc: raise TelegramAuthError("Telegram user is invalid") from exc return user