69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
"""
|
|
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
|
|
"""
|
|
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():
|
|
raise ValueError('Bot token модерации не настроен (MODERATION_BOT_TOKEN)')
|
|
|
|
if not auth_data or 'hash' not in auth_data:
|
|
raise ValueError('Отсутствует hash в authData')
|
|
|
|
received_hash = auth_data.pop('hash')
|
|
|
|
# Clean data - remove None, empty strings, and convert all to strings
|
|
clean_data = {}
|
|
for key, value in auth_data.items():
|
|
if value is not None and value != '':
|
|
clean_data[key] = str(value)
|
|
|
|
# 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)
|
|
|
|
# Create secret key
|
|
secret_key = hmac.new(
|
|
'WebAppData'.encode('utf-8'),
|
|
token_to_use.encode('utf-8'),
|
|
hashlib.sha256
|
|
).digest()
|
|
|
|
# Calculate hash
|
|
calculated_hash = hmac.new(
|
|
secret_key,
|
|
data_check_string.encode('utf-8'),
|
|
hashlib.sha256
|
|
).hexdigest()
|
|
|
|
# Compare hashes
|
|
is_valid = calculated_hash == received_hash
|
|
|
|
if not is_valid:
|
|
print(f"[TelegramWidget] Hash mismatch:")
|
|
print(f" Calculated: {calculated_hash[:20]}...")
|
|
print(f" Received: {received_hash[:20]}...")
|
|
print(f" Data check string: {data_check_string}")
|
|
|
|
return is_valid
|
|
|