sno-quiz/backend/AUTH_GUIDE.md
2025-09-17 22:22:14 +03:00

6.9 KiB
Raw Permalink Blame History

Telegram WebApp Authentication Guide

📋 Обзор

Система аутентификации использует Telegram WebApp initData для безопасной верификации пользователей.

🔧 Как это работает

  1. Frontend получает initData от Telegram WebApp
  2. Backend валидирует HMAC-SHA256 подпись
  3. Success: Пользователь аутентифицирован, данные доступны в handlers
  4. Error: Доступ запрещен (401 Unauthorized)

📝 Требования к переменным окружения

Добавьте в .env файл:

BOT_TOKEN=ваш_токен_бота_от_@BotFather

🛡️ Middleware

Auth Middleware

// Применяется ко всем защищенным маршрутам
app.Use(middleware.AuthMiddleware(middleware.AuthConfig{
    BotToken: cfg.BotToken,
}))

Получение данных пользователя в handler

userData := middleware.GetTelegramUser(c)
if userData == nil {
    return c.Status(fiber.StatusUnauthorized).JSON(...)
}

// Используем userData.ID, userData.FirstName и т.д.

📡 API Эндпоинты

POST /api/auth/validate

Валидация initData без middleware (для инициализации)

Request:

curl -X POST http://localhost:8080/api/auth/validate \
  -H "Content-Type: application/json" \
  -d '{
    "initData": "query_id=AAHdF6IQAAAAAN0XohDhrOrc&user=%7B%22id%22%3AYOUR_TELEGRAM_USER_ID%2C%22first_name%22%3A%22YOUR_FIRST_NAME%22%2C%22last_name%22%3A%22YOUR_LAST_NAME%22%2C%22username%22%3A%22YOUR_USERNAME%22%2C%22language_code%22%3A%22en%22%2C%22is_premium%22%3Atrue%2C%22allows_write_to_pm%22%3Atrue%7D&auth_date=1634567890&hash=YOUR_HASH_HERE..."
  }'

Response (200 OK):

{
  "success": true,
  "message": "Authentication successful",
  "data": {
    "id": YOUR_TELEGRAM_USER_ID,
    "first_name": "John",
    "last_name": "Doe",
    "username": "johndoe",
    "photo_url": "https://t.me/i/userpic/320/johndoe.jpg",
    "auth_date": YOUR_AUTH_DATE,
    "hash": "abcd1234..."
  }
}

GET /api/auth/me

Получение данных текущего аутентифицированного пользователя

Request:

curl -X GET http://localhost:8080/api/auth/me \
  -H "X-Telegram-WebApp-Init-Data: ваш_init_data_здесь"

Response (200 OK):

{
  "success": true,
  "message": "User data retrieved successfully",
  "data": {
    "id": YOUR_TELEGRAM_USER_ID,
    "first_name": "John",
    "last_name": "Doe",
    "username": "johndoe",
    "photo_url": "https://t.me/i/userpic/320/johndoe.jpg",
    "auth_date": YOUR_AUTH_DATE,
    "hash": "abcd1234..."
  }
}

🔒 Защищенные эндпоинты

Все следующие эндпоинты требуют аутентификации:

User Routes

  • GET /api/me - профиль пользователя
  • GET /api/user/transactions - история транзакций
  • GET /api/user/purchases - история покупок

Quiz Routes

  • GET /api/quizzes - список викторин
  • GET /api/quizzes/:id - детали викторины
  • POST /api/quizzes/:id/submit - отправка ответов
  • GET /api/quizzes/:id/can-repeat - проверка возможности повтора

Reward Routes

  • GET /api/rewards - список призов
  • POST /api/rewards/:id/purchase - покупка приза

QR Routes

  • POST /api/qr/validate - валидация QR кода

🔄 Как использовать в фронтенде

1. Получение initData из Telegram WebApp

// В вашем Telegram Mini App
const initData = window.Telegram.WebApp.initData;

2. Отправка на бэкенд

// Вариант 1: Через заголовок (рекомендуется)
const response = await fetch('/api/qr/validate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Telegram-WebApp-Init-Data': initData
  },
  body: JSON.stringify({ payload: 'qr_token_here' })
});

// Вариант 2: Через body для /api/auth/validate
const response = await fetch('/api/auth/validate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ initData })
});

3. Обработка ошибок

if (!response.ok) {
  if (response.status === 401) {
    // Переадресация на страницу аутентификации
    window.location.href = '/auth';
  } else {
    // Другая ошибка
    console.error('Request failed:', response.statusText);
  }
}

⚠️ Важные моменты

  1. Время жизни: initData действителен 5 минут
  2. Безопасность: Всегда проверяйте HMAC подпись на бэкенде
  3. Bot Token: Храните в секрете, никогда в клиентском коде
  4. User ID: Используйте userData.ID как уникальный идентификатор

🔧 Тестирование

Генерация тестового initData

Используйте Telegram WebApp Tools для генерации тестовых initData.

Пример curl с реальными данными

# Замените YOUR_INIT_DATA на реальные данные
curl -X POST http://localhost:8080/api/qr/validate \
  -H "Content-Type: application/json" \
  -H "X-Telegram-WebApp-Init-Data: YOUR_INIT_DATA" \
  -d '{"payload": "test_qr_token"}'

🚀 Production Deployment

  1. HTTPS: Обязательно используйте HTTPS в production
  2. Bot Token: Используйте переменные окружения
  3. Rate Limiting: Добавьте rate limiting для auth эндпоинтов
  4. Logging: Логируйте неудачные попытки аутентификации
  5. Security: Регулярно обновляйте зависимости

🔍 Отладка

Распространенные ошибки

  1. 401 Unauthorized: Неверный initData или просрочен
  2. Hash verification failed: Неверный bot token или поврежденные данные
  3. Missing Telegram init data: Отсутствует заголовок или initData
  4. Auth data expired: Данные старше 5 минут

Debug режим

Для отладки можно временно отключить проверку времени:

// В middleware/auth.go закомментируйте проверку времени
// if time.Since(authTime) > 5*time.Minute {
//     return errors.New("auth data expired")
// }