""" 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 secret_key = hmac.new( 'WebAppData'.encode('utf-8'), token_to_use.encode('utf-8'), hashlib.sha256 ).digest() print(f"[TelegramWidget] Secret key (hex): {secret_key.hex()[:40]}...") # 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