82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""
|
||
Утилиты для авторизации через Telegram Login Widget.
|
||
"""
|
||
import hashlib
|
||
import hmac
|
||
import time
|
||
from typing import Optional, Dict, Any
|
||
from django.conf import settings
|
||
|
||
|
||
def validate_telegram_data(telegram_data: Dict[str, Any], bot_token: str) -> bool:
|
||
"""
|
||
Валидация данных от Telegram Login Widget.
|
||
|
||
Telegram отправляет данные с полем 'hash', которое является HMAC-SHA256
|
||
подписью всех остальных полей, отсортированных по ключу.
|
||
|
||
Args:
|
||
telegram_data: Данные от Telegram (id, first_name, username, hash, auth_date, etc.)
|
||
bot_token: Токен Telegram бота
|
||
|
||
Returns:
|
||
True если данные валидны, False иначе
|
||
"""
|
||
if 'hash' not in telegram_data:
|
||
return False
|
||
|
||
# Сохраняем hash и auth_date перед удалением
|
||
received_hash = telegram_data.get('hash')
|
||
auth_date = int(telegram_data.get('auth_date', 0))
|
||
|
||
# Создаем копию без hash для проверки
|
||
data_for_check = {k: v for k, v in telegram_data.items() if k != 'hash'}
|
||
|
||
# Сортируем данные по ключу и формируем строку для проверки
|
||
data_check_string = '\n'.join(
|
||
f"{key}={value}"
|
||
for key, value in sorted(data_for_check.items())
|
||
)
|
||
|
||
# Вычисляем секретный ключ из токена бота
|
||
secret_key = hashlib.sha256(bot_token.encode()).digest()
|
||
|
||
# Вычисляем HMAC-SHA256
|
||
calculated_hash = hmac.new(
|
||
secret_key,
|
||
data_check_string.encode(),
|
||
hashlib.sha256
|
||
).hexdigest()
|
||
|
||
# Сравниваем хеши
|
||
if calculated_hash != received_hash:
|
||
return False
|
||
|
||
# Проверяем время (данные не должны быть старше 24 часов)
|
||
current_time = int(time.time())
|
||
|
||
if current_time - auth_date > 86400: # 24 часа
|
||
return False
|
||
|
||
return True
|
||
|
||
|
||
def extract_telegram_user_data(telegram_data: Dict[str, Any]) -> Dict[str, Any]:
|
||
"""
|
||
Извлечение данных пользователя из данных Telegram.
|
||
|
||
Args:
|
||
telegram_data: Данные от Telegram
|
||
|
||
Returns:
|
||
Словарь с данными пользователя
|
||
"""
|
||
return {
|
||
'telegram_id': int(telegram_data.get('id', 0)),
|
||
'first_name': telegram_data.get('first_name', ''),
|
||
'last_name': telegram_data.get('last_name', ''),
|
||
'username': telegram_data.get('username', ''),
|
||
'photo_url': telegram_data.get('photo_url', ''),
|
||
}
|
||
|