42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
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
|