Все статьиSecurity

Безопасность Telegram Mini Apps: аутентификация initData

Полный гайд по безопасности Telegram Mini Apps: валидация initData через HMAC-SHA256, защита API и JWT. Доверьте разработку надежных TMA команде EvaLab!

9 мин readОбновлено 28.08.2026
Безопасность Telegram Mini Apps: аутентификация initData — статья блога EvaLab

Telegram Mini Apps (TMA) стали одним из самых быстрорастущих каналов продаж, клиентского обслуживания и Web3-сервисов в 2026 году. Построение веб-приложения внутри экосистемы Telegram позволяет мгновенно получать доступ к аутентифицированному пользователю без необходимости ввода логина и пароля.

Однако кажущаяся простота таит в себе серьезные риски безопасности. Злоумышленник может сэмулировать клиентское окружение Telegram, подделать объект пользователя window.Telegram.WebApp.initData и получить несанкционированный доступ к чужим балансам, персональным данным или админ-панели.

В этой статье эксперты по кибербезопасности из EvaLab детально разоберут архитектуру безопасной аутентификации Telegram Mini Apps с верификацией подписи HMAC-SHA256 на TypeScript.

Векторы атак и особенности архитектуры Telegram Mini Apps

Когда Telegram открывает ваше Mini App внутри iframe или встроенного WebView, он передает в URL или метод инициализации строку initData. Эта строка содержит сведения о пользователе (user), чате, времени создания строки (auth_date) и криптографический хэш (hash).

Главные угрозы при неверной реализации безопасности:

  1. Спуфинг (Spoofing): отправив запрос напрямую к вашему бэкенд API с чужим telegram_id в JSON-теле, злоумышленник может выдать себя за любого пользователя или администратора.
  2. Replay-атаки (Атаки повторного воспроизведения): если бэкенд верифицирует initData без проверки времени жизни auth_date, перехваченная ранее подпись может использоваться бессрочно.
  3. Man-in-the-Middle (MitM): отсутствие валидации и передача данных не по HTTPS.

Криптографический алгоритм подписи initData

Для проверки подлинности данных Telegram использует двухступенчатую схему хэширования на базе HMAC-SHA256:

  1. Создается ключ подписи secret_key путем хэширования токена бота (bot_token) с постоянной строковой меткой "WebAppData": $$\text{secret_key} = \text{HMAC-SHA256}("WebAppData", \text{bot_token})$$
  2. Переданная строка initData разбивается на пары key=value, сортируется по алфавиту по ключам (исключая сам параметр hash) и объединяется через символ перевода строки \n. Получается каноничная строка data_check_string.
  3. Вычисляется итоговый HMAC-SHA256 от data_check_string с использованием secret_key: $$\text{calculated_hash} = \text{HMAC-SHA256}(\text{data_check_string}, \text{secret_key})$$
  4. Если calculated_hash совпадает с полученным из initData хешем hash, данные подлинны и сформированы самим Telegram.

Пошаговая реализация валидации initData на TypeScript (Node.js)

Реализуем модульный сервисный класс безопасности на Node.js с использованием встроенного модуля crypto:

import crypto from 'crypto';

export interface TelegramUser {
  id: number;
  first_name: string;
  last_name?: string;
  username?: string;
  language_code?: string;
  is_premium?: boolean;
}

export interface ValidatedInitData {
  user: TelegramUser;
  auth_date: number;
  query_id?: string;
}

export class TelegramAuthService {
  private botToken: string;
  private maxAgeSeconds: number;

  constructor(botToken: string, maxAgeSeconds: number = 86400) {
    this.botToken = botToken;
    this.maxAgeSeconds = maxAgeSeconds; // По умолчанию сессия валидна 24 часа
  }

  /**
   * Валидирует initData и возвращает распаршенные данные пользователя
   */
  public validateInitData(rawInitData: string): ValidatedInitData {
    const urlParams = new URLSearchParams(rawInitData);
    const hash = urlParams.get('hash');

    if (!hash) {
      throw new Error('Криптографический хэш (hash) отсутствует');
    }

    urlParams.delete('hash');

    // 1. Сортировка пар ключ=значение в алфавитном порядке
    const dataCheckArr: string[] = [];
    urlParams.forEach((value, key) => {
      dataCheckArr.push(`${key}=${value}`);
    });
    dataCheckArr.sort();

    const dataCheckString = dataCheckArr.join('\n');

    // 2. Расчет secret_key
    const secretKey = crypto
      .createHmac('sha256', 'WebAppData')
      .update(this.botToken)
      .digest();

    // 3. Расчет контрольного хэша
    const calculatedHash = crypto
      .createHmac('sha256', secretKey)
      .update(dataCheckString)
      .digest('hex');

    // 4. Безопасное сравнение строк для защиты от timing-атак
    const isHashValid = crypto.timingSafeEqual(
      Buffer.from(calculatedHash, 'hex'),
      Buffer.from(hash, 'hex')
    );

    if (!isHashValid) {
      throw new Error('Подпись initData недействительна. Данные подделаны!');
    }

    // 5. Проверка возраста подписи (Защита от Replay-атак)
    const authDateStr = urlParams.get('auth_date');
    if (!authDateStr) {
      throw new Error('Отсутствует поле auth_date');
    }

    const authDate = parseInt(authDateStr, 10);
    const currentTime = Math.floor(Date.now() / 1000);

    if (currentTime - authDate > this.maxAgeSeconds) {
      throw new Error('Срок действия сессии initData истек');
    }

    const userJson = urlParams.get('user');
    if (!userJson) {
      throw new Error('Объект пользователя отсутствует в initData');
    }

    return {
      user: JSON.parse(userJson) as TelegramUser,
      auth_date: authDate,
      query_id: urlParams.get('query_id') || undefined,
    };
  }
}

[!CAUTION] Всегда используйте crypto.timingSafeEqual() вместо стандартного оператора === при сравнении хэшей. Обычное сравнение строк уязвимо для атак по времени (Timing Attacks), позволяющих злоумышленнику подобрать хэш побайтово!

Сессионная безопасность и архитектура JWT

Постоянно передавать исходный initData в каждом HTTP-запросе к API неэффективно и небезопасно (увеличивается размер сетевых заголовков).

Рекомендуемый паттерн защиты API Telegram Mini App:

sequenceDiagram
    autonumber
    actor User as Telegram App (Frontend)
    participant AuthAPI as Backend Auth API
    participant DB as База Данных
    participant AppAPI as Protected API

    User->>AuthAPI: POST /api/auth/telegram (initData)
    AuthAPI->>AuthAPI: Проверка HMAC-SHA256 & auth_date
    AuthAPI->>DB: Upsert пользователя по telegram_id
    AuthAPI-->>User: Выдача short-lived JWT (Access Token) + HttpOnly Refresh Cookie
    User->>AppAPI: GET /api/user/orders (Header: Bearer JWT)
    AppAPI-->>User: Ответ с данными заказа
  1. Эндпоинт авторизации (/api/auth/telegram): принимает initData, выполняет верификацию HMAC-SHA256 и регистрирует/обновляет профиль пользователя в БД.
  2. Выдача JWT-токена: сервер возвращает короткоживущий Access Token (время жизни 15–30 минут) и устанавливает Refresh Token в HttpOnly, Secure, SameSite=Strict Cookie.
  3. Защита эндпоинтов: последующие API-запросы выполняются через стандартный заголовок Authorization: Bearer <token>.

Чек-лист безопасности при запуске Telegram Mini App в продакшен

  • Серверная валидация HMAC-SHA256 включена для всех входных точек.
  • Настроена строго ограниченная проверка auth_date (не старее 24 часов).
  • Используется безопасное сравнение crypto.timingSafeEqual.
  • Токен бота (BOT_TOKEN) хранится исключительно в переменной окружения сервера (.env.local) и никогда не попадает в JS-бандл фронтенда.
  • Настроены заголовки CORS, Content Security Policy (CSP) и защищенное соединение HTTPS.
  • Реализован Rate Limiting на стороне бэкенда для защиты от брутфорса и DDOS-атак (например, через Redis / Upstash).

Заключение

Telegram Mini Apps — это мощнейший инструмент для развития B2B и B2C бизнеса, но его безопасность напрямую зависит от правильной реализации криптографической проверки initData. Небрежный подход к авторизации открывает критические уязвимости для взлома и утечки клиентских данных.

Нужна профессиональная и защищенная разработка Telegram Mini App, интеграция с платежными системами и бэкендом? Доверьте разработку экспертам EvaLab — мы гарантируем высокую безопасность и отказоустойчивость ваших сервисов!

Следующий шаг

Превратим идею в рабочую систему

Разберём задачу, сопоставим её с целями бизнеса и предложим план внедрения с понятными этапами и критериями результата.