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

103 lines
4.2 KiB
Python
Raw Normal View History

2025-12-15 00:37:34 +00:00
"""
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
"""
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] 🔍 Начало валидации виджета")
print(f"[TelegramWidget] Полученные данные: {auth_data}")
2025-12-15 00:37:34 +00:00
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():
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] ❌ Bot token не настроен")
2025-12-15 00:37:34 +00:00
raise ValueError('Bot token модерации не настроен (MODERATION_BOT_TOKEN)')
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] Bot token: {token_to_use[:10]}...{token_to_use[-10:]}")
2025-12-15 00:37:34 +00:00
if not auth_data or 'hash' not in auth_data:
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] ❌ Отсутствует hash в authData")
2025-12-15 00:37:34 +00:00
raise ValueError('Отсутствует hash в authData')
2025-12-15 01:50:53 +00:00
# Создаем копию, чтобы не изменять оригинал
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}")
2025-12-15 00:37:34 +00:00
# Clean data - remove None, empty strings, and convert all to strings
clean_data = {}
2025-12-15 01:50:53 +00:00
for key, value in auth_data_copy.items():
2025-12-15 00:37:34 +00:00
if value is not None and value != '':
2025-12-15 01:50:53 +00:00
# ВАЖНО: 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}")
2025-12-15 00:37:34 +00:00
# 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)
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] Data check string: {repr(data_check_string)}")
2025-12-15 00:37:34 +00:00
# Create secret key
2025-12-15 01:55:04 +00:00
# ВАЖНО: Для Login Widget используется SHA256(bot_token), а НЕ HMAC-SHA256('WebAppData', bot_token)
# Это отличается от WebApp initData!
secret_key = hashlib.sha256(token_to_use.encode('utf-8')).digest()
2025-12-15 00:37:34 +00:00
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] Secret key (hex): {secret_key.hex()[:40]}...")
2025-12-15 01:55:04 +00:00
print(f"[TelegramWidget] Bot token для secret key: {token_to_use[:10]}...{token_to_use[-10:]}")
2025-12-15 01:50:53 +00:00
2025-12-15 00:37:34 +00:00
# Calculate hash
calculated_hash = hmac.new(
secret_key,
data_check_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
2025-12-15 01:50:53 +00:00
print(f"[TelegramWidget] Calculated hash: {calculated_hash}")
print(f"[TelegramWidget] Received hash: {received_hash}")
2025-12-15 00:37:34 +00:00
# Compare hashes
is_valid = calculated_hash == received_hash
if not is_valid:
2025-12-15 01:50:53 +00:00
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 совпадает!")
2025-12-15 00:37:34 +00:00
return is_valid