nakama/moderation/backend-py/utils/telegram_widget.py

103 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Telegram Login Widget validation
"""
import hmac
import hashlib
from typing import Optional, Dict, Any
from config import settings
def validate_telegram_widget(auth_data: Dict[str, Any], bot_token: Optional[str] = None) -> bool:
"""
Validate Telegram Login Widget authentication data
Args:
auth_data: Dictionary with user data and hash from Telegram widget
bot_token: Bot token (uses MODERATION_BOT_TOKEN if not provided)
Returns:
True if validation successful
Raises:
ValueError: If validation fails
"""
print(f"[TelegramWidget] 🔍 Начало валидации виджета")
print(f"[TelegramWidget] Полученные данные: {auth_data}")
token_to_use = bot_token or settings.MODERATION_BOT_TOKEN
if not token_to_use or not isinstance(token_to_use, str) or not token_to_use.strip():
print(f"[TelegramWidget] ❌ Bot token не настроен")
raise ValueError('Bot token модерации не настроен (MODERATION_BOT_TOKEN)')
print(f"[TelegramWidget] Bot token: {token_to_use[:10]}...{token_to_use[-10:]}")
if not auth_data or 'hash' not in auth_data:
print(f"[TelegramWidget] ❌ Отсутствует hash в authData")
raise ValueError('Отсутствует hash в authData')
# Создаем копию, чтобы не изменять оригинал
auth_data_copy = auth_data.copy()
received_hash = auth_data_copy.pop('hash')
print(f"[TelegramWidget] Received hash: {received_hash[:20]}...{received_hash[-20:]}")
print(f"[TelegramWidget] Данные для валидации (без hash): {auth_data_copy}")
# Clean data - remove None, empty strings, and convert all to strings
clean_data = {}
for key, value in auth_data_copy.items():
if value is not None and value != '':
# ВАЖНО: auth_date должен быть числом (int), но в строке для валидации
if key == 'auth_date':
# Преобразуем в int, затем в str для валидации
try:
auth_date_int = int(value)
clean_data[key] = str(auth_date_int)
except (ValueError, TypeError):
print(f"[TelegramWidget] ⚠️ Неверный формат auth_date: {value} (type: {type(value)})")
clean_data[key] = str(value)
else:
clean_data[key] = str(value)
print(f"[TelegramWidget] Очищенные данные: {clean_data}")
# Create data check string (sorted keys)
data_check_arr = sorted(clean_data.items())
data_check_string = '\n'.join(f'{key}={value}' for key, value in data_check_arr)
print(f"[TelegramWidget] Data check string: {repr(data_check_string)}")
# Create secret key
# ВАЖНО: Для Login Widget используется SHA256(bot_token), а НЕ HMAC-SHA256('WebAppData', bot_token)
# Это отличается от WebApp initData!
secret_key = hashlib.sha256(token_to_use.encode('utf-8')).digest()
print(f"[TelegramWidget] Secret key (hex): {secret_key.hex()[:40]}...")
print(f"[TelegramWidget] Bot token для secret key: {token_to_use[:10]}...{token_to_use[-10:]}")
# Calculate hash
calculated_hash = hmac.new(
secret_key,
data_check_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
print(f"[TelegramWidget] Calculated hash: {calculated_hash}")
print(f"[TelegramWidget] Received hash: {received_hash}")
# Compare hashes
is_valid = calculated_hash == received_hash
if not is_valid:
print(f"[TelegramWidget] ❌ Hash mismatch:")
print(f" Calculated: {calculated_hash}")
print(f" Received: {received_hash}")
print(f" Data check string: {repr(data_check_string)}")
print(f" Clean data keys: {list(clean_data.keys())}")
print(f" Clean data values: {list(clean_data.values())}")
else:
print(f"[TelegramWidget] ✅ Hash совпадает!")
return is_valid