Задать вопрос
@satinktten

Как настроить авторизацию в Telegram Mini Apps?

Нужно настроить авторизацию в Telegram mini app (генерацию токена). Главная проблема в том, что на бэкенде вычисленный хэш не совпадает с тем, что получен с клиента. Токен бота проверяли, если что. В коде бэкенда оставила только кусок до момента сравнения хэша.

Код на фронте:

export const login = async () => {
   try {
      const response = await axios.post(
         `${API_URL}/auth/telegram`,
         {
            initData: window.Telegram?.WebApp?.initData,
         },
         {
            headers: {
               "Content-Type": "application/json",
            },
         }
      );
      localStorage.setItem("token", response.data.access_token);
      axios.defaults.headers.common[
         "Authorization"
      ] = `Bearer ${response.data.access_token}`;
      return response.data;
   } catch (error) {
      console.error("Auth error:", error);
   }
};


Обработка на бэкенде:

# Секретный ключ и алгоритм для генерации JWT-токена
JWT_SECRET = os.getenv("JWT_SECRET", "тут типа ключ")
JWT_ALGORITHM = "HS256"

# Инициализируем маршрутизатор FastAPI с префиксом /auth
router = APIRouter(prefix="/auth", tags=["Auth"])

# Настраиваем логгер для вывода отладочной информации в systemd
logger = logging.getLogger("uvicorn.error")

# Pydantic-модель для структуры тела запроса
class TelegramInitData(BaseModel):
    initData: str  # Ожидаем строку формата query_id=...&user=...&auth_date=...&hash=...

def verify_telegram_hash(init_data: str) -> dict[str, str]:
    # Парсим строку initData
    try:
        parsed_data = dict(urllib.parse.parse_qsl(init_data))
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Неверный формат initData")

    # Проверяем наличие обязательных параметров
    required_keys = {'query_id', 'user', 'auth_date', 'hash'}
    if not required_keys.issubset(parsed_data.keys()):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Отсутствуют обязательные параметры: {required_keys - set(parsed_data.keys())}")

    # Копируем параметры
    params = parsed_data.copy()

    # Извлекаем hash
    received_hash = params.pop("hash", None)
    if not received_hash:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Отсутствует параметр hash")

    # Формируем data_check_string
    data_check_string = "\n".join(
        f"{k}={v}" for k, v in sorted(params.items(), key=itemgetter(0))
    )

    # Проверяем наличие BOT_TOKEN
    if not BOT_TOKEN:
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Ошибка конфигурации: нет BOT_TOKEN")

    # Вычисляем secret_key
    secret_key = hmac.new(
        key=b"WebAppData", msg=BOT_TOKEN.encode(), digestmod=hashlib.sha256
    )

    # Вычисляем хеш
    calculated_hash = hmac.new(
        key=secret_key.digest(), msg=data_check_string.encode(), digestmod=hashlib.sha256
    ).hexdigest()

    # Сравниваем хеши
    if not hmac.compare_digest(calculated_hash, received_hash):
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Неверные данные аутентификации Telegram")
  • Вопрос задан
  • 94 просмотра
Подписаться 2 Средний 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы