uchill/backend/apps/users/telegram_auth.py

82 lines
2.7 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.
"""
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', ''),
}