ФронтендБэкендJavaScriptHTML / CSS

Telegram Mini App: получаем пользователя и безопасно проверяем initData

Получаем пользователя Telegram Mini App и проверяем подпись initData на Node.js: HMAC, auth_date, безопасная сессия и защита от подмены данных.

Кодик

Автор

6 мин чтения

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

Объект initDataUnsafe удобен для интерфейса, но пользователь может подменить его в браузере, поэтому сервер не должен доверять этим полям. Поэтому отделим настройку, входные данные, основное действие и проверку. В этой статье вы соберёте серверную функцию проверки hash и auth_date, которая возвращает подтверждённого пользователя. Проверка: настоящая строка проходит, изменённое поле отклоняется, а старые данные получают отдельную ошибку.

1Соберите минимум

передать Telegram.WebApp.initData на сервер. Не расширяйте проект до первого успешного запуска.

2Увидьте данные

data_check_string воспроизводима. Проверяйте значение, а не отсутствие ошибки.

3Измените правило

После успеха добавьте серверную сессию и отдельный ответ для просроченных данных. Так копирование станет практикой.

Как устроен учебный проект Telegram initData

Telegram initData получает входные данные, проверяет их, выполняет одно внешнее действие и сохраняет наблюдаемый результат. Держите ввод, логику и отображение раздельно: тогда каждый этап можно проверить отдельно.

ЭтапДействиеПроверяемый результат
Клиентпередать Telegram.WebApp.initData на серверсырой initData не меняется
Строка проверкиотсортировать пары кроме hashdata_check_string воспроизводима
Подписьвычислить HMAC по правилам TelegramtimingSafeEqual подтверждает hash
Сроксравнить auth_date с текущим временемустаревший запуск отклоняется

Контрольные точки: клиент, строка проверки, подпись и срок. Следующий шаг начинается после совпадения с ожидаемым результатом.

Путь данных в проекте Telegram initData
От входных данных до видимого результата. Сначала проверяется вход, затем действие и только потом интерфейс.

Зафиксируйте первый успех Не отправляйте на сервер initDataUnsafe.user как доказательство личности. Передавайте исходную строку initData. Сохраните команду запуска и ожидаемый вывод.

Собираем рабочий пример шаг за шагом

Материал сверялся с официальной документацией сервиса 21 октября 2026 года. Создайте Node.js проект. BOT_TOKEN храните только на сервере, клиент отправляет initData в теле HTTPS-запроса. Проверьте текущую папку через pwd или Get-Location. Вставьте пример целиком, выполните один раз, затем разбирайте по частям.

import crypto from 'node:crypto'

export function validateInitData(initData, botToken, maxAge = 3600) {
  const params = new URLSearchParams(initData)
  const receivedHash = params.get('hash')
  if (!receivedHash) return { ok: false, reason: 'hash missing' }
  params.delete('hash')
  const dataCheckString = [...params.entries()]
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([key, value]) => key + '=' + value)
    .join('\n')
  const secret = crypto.createHmac('sha256', 'WebAppData')
    .update(botToken).digest()
  const expected = crypto.createHmac('sha256', secret)
    .update(dataCheckString).digest('hex')
  const valid = receivedHash.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(receivedHash), Buffer.from(expected))
  const authDate = Number(params.get('auth_date'))
  const fresh = Number.isFinite(authDate) && Date.now() / 1000 - authDate <= maxAge
  if (!valid) return { ok: false, reason: 'bad hash' }
  if (!fresh) return { ok: false, reason: 'expired' }
  return { ok: true, user: JSON.parse(params.get('user') || 'null') }
}
Что должно произойти после запуска
  • Оригинальная строка возвращает ok: true и разобранного пользователя.
  • Подмена id, имени или auth_date меняет HMAC и приводит к отказу.
  • Повторный запуск даёт тот же предсказуемый результат.
  • Пустой ввод получает понятное сообщение вместо падения.

Главная функция принимает явные аргументы и возвращает данные, которые можно проверить отдельно от интерфейса. Найдите в примере вход, проверку и место формирования результата.

Хрупкий и проверяемый вариант Telegram initData
Что отличает устойчивый проект от случайного запуска. Явные границы делают ошибку локальной и понятной.

Что происходит внутри и почему это работает

Telegram и ваш сервер знают bot token. Из него выводится secret key, затем HMAC подписывает каноническую строку параметров. Сравнение hash доказывает целостность, но свежесть проверяется отдельно. Логику держите отдельно от вывода: функция получает аргумент и возвращает значение, а интерфейс показывает его. Секреты хранятся в переменных окружения и не попадают в исходники, журналы и скриншоты.

ЧастьЗа что отвечаетЧто проверить
initDataнесёт параметры и подписьпередаётся без изменения
HMACпроверяет целостность строкиhash сравнивается безопасно
auth_dateограничивает повтор старого запускаесть допустимый возраст

Успешная подпись не означает, что запрос нельзя повторить. Для чувствительных действий создайте серверную сессию, используйте CSRF-защиту по модели приложения и не принимайте платёжное действие только по одному initData. Не прячьте поток в одном обработчике: сохраните вход, проверьте его, вызовите операцию и только затем обновите интерфейс.

Проверьте границу Измените один символ в user, затем уменьшите maxAge до одной секунды. Должны сработать разные причины отказа. Меняйте одно условие за прогон, чтобы видеть причину.

Проверяем проект и добавляем свою функцию

Сделайте endpoint /session, который принимает initData один раз и выдаёт короткую HttpOnly cookie. До правки запишите ожидаемое поведение одним предложением. После граничного теста повторите обычный сценарий.

Проверка своими руками
  1. Сохраните ожидаемый результат: настоящая строка проходит, изменённое поле отклоняется, а старые данные получают отдельную ошибку.
  2. Измените правило: добавьте серверную сессию и отдельный ответ для просроченных данных. Сначала предскажите итог.
  3. Передайте граничное значение и убедитесь, что приложение не падает.
  4. Верните корректные данные и объясните роли трёх основных частей.
Готово, если выполняются все пункты
  • сырой initData не меняется
  • data_check_string воспроизводима
  • timingSafeEqual подтверждает hash
  • устаревший запуск отклоняется

После изменения повторите основной и ошибочный сценарии, чтобы новое поведение не сломало исходный результат. Полезная правка проходит от нового ввода до видимого результата.

Четыре контрольные точки Telegram initData
Четыре проверки перед следующим шагом. Каждый следующий этап начинается после наблюдаемого результата.

Что запомнить и куда двигаться дальше

В интерфейсе можно показывать initDataUnsafe, но все права, баланс и действия проверяйте по подтверждённой серверной личности. Для закрепления откройте в REST API на Express, в первом проекте TypeScript и в WebSocket-чате.

Как изучить тему в Кодике

Сначала разберите формат данных и одну функцию, затем подключайте сеть, интерфейс или внешний сервис. Сначала восстановите главную функцию и проверьте её на трёх значениях.

ШагЧто разобратьМини-проверка
1. ОсноваURLSearchParams, Buffer и модули Node.jsОбъясните вход и выход функции.
2. ИнструментHMAC, каноническую строку и timingSafeEqualПовторите команду по памяти.
3. ПроектEndpoint с проверкой подписи и срокаПроверьте два сценария.
4. РефакторингСессию, cookie и защиту чувствительных действийРазделите ввод, логику и вывод.

Закрепите проект, переписав ключевую функцию по памяти и добавив собственный граничный случай. Базовый синтаксис закрепите через курс JavaScript.

Доверие initDataUnsafe

Эти данные доступны клиенту и могут быть изменены.

Hash включён в строку

Подпись никогда не совпадёт. Удалите hash до сортировки.

Обычное сравнение строк

Используйте timingSafeEqual после проверки длины.

Нет проверки auth_date

Корректную старую строку можно повторять слишком долго.

Сверяйтесь с первичной документацией. Команды и ограничения примера проверены по официальному источнику 1. Если версия инструмента изменилась, официальный источник важнее старого скриншота.

Что получится в итоге

Готовый результат проекта: Telegram Mini App: получаем пользователя и безопасно проверяем initData
Финальный экран показывает результат, состояние запроса и понятное сообщение об ошибке без раскрытия секретов.

Короткие ответы
Что доказывает hash?

Что набор параметров не изменился после формирования Telegram.

Зачем отдельно проверять auth_date?

Подпись не ограничивает срок повторного использования данных.

Что проверять первым, если Telegram initData не запускается?

Версию среды, текущую папку, команду запуска и первую строку ошибки.

Как понять, что проект Telegram initData работает?

Проверьте основной сценарий, неверный ввод, повторный запуск и один граничный случай.

Можно ли начать с готового кода?

Да. Добейтесь результата, измените одно правило и восстановите ключевую функцию без копирования.

Сделайте один осознанный шаг дальше

Выберите одно улучшение и проведите его от ввода до результата.

Если не хватает основы, перейдите курс JavaScript, затем восстановите ключевую функцию без подсказки.