Разработка 8 мин чтения

Вход в мини-приложение Telegram и MAX без пароля: как это работает

Мини-приложение узнаёт человека по подписи, которую ставит мессенджер. Объясняю простым языком, как сервер проверяет initData токеном бота, зачем ограничивать срок по auth_date, как склеить профиль из Telegram, MAX и сайта и что делать в PWA.

мини-приложениеTelegramMAXбезопасностьPWA

Коротко (TL;DR)

  • Мини-приложение в Telegram и MAX узнаёт человека без пароля: мессенджер при запуске передаёт строку данных о пользователе, подписанную на основе токена вашего бота.
  • Сервер обязан проверить эту подпись сам. Данным, которые прислал браузер без проверки, верить нельзя: их может подменить кто угодно.
  • Подпись не протухает сама. Срок жизни входа задаёт сервер по полю auth_date, и для этого часы сервера должны идти точно.
  • Номер телефона, которым человек поделился через мессенджер, помогает склеить один профиль из Telegram, MAX и сайта.
  • Вне мессенджера, в PWA или браузере, подписи нет: нужен отдельный вход, например ссылка с кодом через бота.
Нужно мини-приложение для вашего бизнеса?

Сделаю под ключ: разберу задачу, назову срок и цену. Чтобы начать, напишите в Telegram одной фразой.

Разработка мини-приложений Telegram

Вход в мини-приложение без пароля работает так: когда человек открывает приложение внутри Telegram или MAX, мессенджер передаёт ему строку initData с данными пользователя и подписью hash. Приложение отправляет эту строку на ваш сервер, сервер пересчитывает подпись с помощью токена бота и сравнивает. Совпало, значит данные выдал мессенджер и человек тот, за кого себя выдаёт. Не совпало, значит запрос отклоняется.

Почему пароль здесь не нужен

Человек уже вошёл в мессенджер со своего телефона. Заставлять его придумывать ещё один пароль для записи к врачу или для отчёта руководителю значит терять людей на первом экране. Мессенджер может подтвердить личность сам, и владельцу бизнеса остаётся правильно принять это подтверждение.

Я делал такой вход в трёх проектах, и в каждом он решал немного разную задачу. В проекте для врача-косметолога мини-приложение записи открывается из бота в Telegram, и каждый запрос к его API подписан данными запуска, сервер проверяет подпись. В приложении руководителя команды одна схема проверки работает и для Telegram, и для MAX. В учёте для бухгалтерской фирмы вход в мини-приложение тоже идёт по подписи Telegram, и поддельная подпись отклоняется.

Как работает подпись initData

Если совсем просто: у вашего бота есть токен, секретная строка, которую знают только мессенджер и ваш сервер. Мессенджер берёт данные о пользователе (кто он, когда открыл приложение и другие поля) и вычисляет из них и токена контрольную сумму. Подделать её без токена нельзя. Сервер делает то же вычисление у себя и сравнивает результат.

По документации Telegram, на сервер нужно отправлять именно строку из поля Telegram.WebApp.initData, а проверять её на стороне бота (core.telegram.org/bots/webapps, раздел про проверку данных из мини-приложения). В MAX схема описана в разделе про валидацию данных: мессенджер передаёт стартовые параметры при каждом запуске, те же данные доступны как window.WebApp.initData, а параметр hash обязателен (dev.max.ru/docs/webapps/validation).

Техническая врезка для разработчика

Алгоритм в обоих мессенджерах по документации совпадает по смыслу:

  1. Разобрать строку initData на пары «ключ=значение», вынуть hash и запомнить его.
  2. Остальные пары отсортировать по ключу и склеить в строки «ключ=значение» через перевод строки. В MAX документация отдельно напоминает декодировать значения из URL, если платформа этого ещё не сделала.
  3. Секретный ключ: HMAC-SHA256 от токена бота, где ключом служит строка WebAppData.
  4. Подпись: HMAC-SHA256 от склеенной строки на секретном ключе, в шестнадцатеричном виде. Сравнить с hash.
secret = HMAC_SHA256(key = "WebAppData", message = BOT_TOKEN)
check  = hex(HMAC_SHA256(key = secret, message = data_check_string))
if check != hash: ответить 401
if now - auth_date > лимит: ответить 401

У Telegram есть ещё поле signature для проверки третьей стороной по открытому ключу Ed25519, без токена бота. Для собственного сервера достаточно проверки hash.

Почему нельзя верить данным с клиента

В мини-приложении есть удобный объект initDataUnsafe: те же данные, уже разобранные в JSON. Им пользуются, чтобы показать имя на экране. Обе документации прямо предупреждают, что для проверки он не годится. У Telegram сказано, что данным из этого поля не стоит доверять и использовать на сервере можно только initData после проверки. У MAX, что объект нельзя использовать для валидации данных (dev.max.ru/docs/webapps/bridge).

Причина простая. Всё, что пришло из браузера, можно отправить вручную: открыть адрес API и подставить чужой идентификатор пользователя. Если сервер берёт id из тела запроса и верит ему, любой человек прочитает чужие записи или поставит поручение от имени руководителя. Поэтому правило у меня жёсткое: личность определяется только на сервере, только из проверенной строки, а права проверяются при каждом действии.

Если вы заказываете мини-приложение и хотите понять, сделано ли так у вас, попросите разработчика показать, где именно сервер проверяет hash. Это пять минут разговора. Если сомнения остаются, такую проверку я делаю в рамках технического аудита.

Срок auth_date и часы сервера

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

Без такой проверки перехваченная строка запуска остаётся рабочей сколько угодно. С ней появляется другая забота: часы сервера. Если сервер спешит или отстаёт, свежая подпись вдруг выглядит старой, и пользователи получают отказ без видимой причины. Время на сервере я синхронизирую автоматически и при отказе пишу в журнал разницу между auth_date и текущим временем, чтобы такую ошибку было видно сразу.

Склейка профиля по номеру телефона

Telegram и MAX дают разные идентификаторы пользователя. Если часть команды сидит в одном мессенджере, а часть в другом, или один человек заходит из обоих, без склейки у вас появятся два профиля одного сотрудника.

Склеивать удобно по номеру телефона, которым человек сам поделился. В Telegram для этого есть метод WebApp.requestContact: мессенджер показывает своё окно с просьбой поделиться номером, и номер получает бот. В MAX есть window.WebApp.requestContact(): он возвращает телефон вместе с authDate и hash, и сервер проверяет этот hash токеном бота так же, как initData. Номер, набранный вручную в поле формы, для склейки я не использую: его никто не подтвердил.

Так сделано в приложении для руководителя команды: номер телефона склеивает профили одного человека из двух мессенджеров и сайта, а поручения и сводка общие. Про то, что ещё отличает мини-приложение в MAX, я писал в статье о мини-аппах в MAX для бизнеса.

Что делать в PWA и браузере

Когда приложение открывают с компьютера в браузере или иконкой на главном экране телефона, мессенджера рядом нет и подписи тоже нет. Тут нужен отдельный вход, и я использую два варианта.

  • Вход через бота. Сайт показывает ссылку с одноразовым кодом, человек открывает её в мессенджере, нажимает «Поделиться номером», и сайт сам понимает, что вход подтверждён. Так устроен вход на сайт в приложении руководителя команды.
  • Логин и пароль, если с системой работают сотрудники за компьютером. В учёте для бухгалтерской фирмы так входят бухгалтеры: пароли хранятся через PBKDF2, на вход даётся пять попыток за десять минут. Клиенты фирмы при этом заходят из бота по подписи.

Само веб-приложение в обоих случаях одно: кабинет на компьютере, PWA на телефоне и мини-приложение в мессенджере. Как сделать из сайта PWA, разбирал в отдельной статье.

Типичные ошибки

  • 401 на каждый запрос. Чаще всего строку проверяют не в том виде: декодировали дважды, потеряли поле, отсортировали не по ключу или считают ключ из токена другого бота. Проверьте, что токен тот же, что у бота, который открывает приложение.
  • 401 через несколько минут или у части людей. Слишком короткий лимит на auth_date или неточные часы сервера.
  • Доверие initDataUnsafe. Интерфейс работает, но безопасности нет: сервер берёт id из запроса как есть.
  • Токен в журналах. В запросах к API бота токен стоит прямо в адресе, и HTTP-библиотека пишет его в лог. В двух проектах мне пришлось приглушить журнал такой библиотеки. Утёкший токен ломает всю схему: им можно подписать любые данные.
  • Telegram Desktop и адрес страницы. Telegram дописывает к адресу свой фрагмент с данными запуска, и роутер на хешах в учёте для бухфирмы ломался. Пришлось чистить адрес и водить переходы по-своему. Ещё окно Telegram может держать старую версию страницы после выкладки.

Как я это делаю

Мой порядок для любого мини-приложения с входом:

  1. Одна функция проверки подписи на сервере для Telegram и MAX, через неё проходит каждый запрос к API.
  2. Лимит на auth_date и синхронизация времени на сервере, отказ пишется в журнал с причиной.
  3. Права проверяются на сервере при каждом действии. Интерфейс только прячет кнопки.
  4. Склейка профилей по подтверждённому номеру телефона, если входов больше одного.
  5. Отдельный вход для браузера и PWA: через бота или по паролю с ограничением попыток.
  6. Токен бота не попадает в логи, автотесты проверяют, что поддельная и просроченная подпись отклоняются.

Если нужно мини-приложение для команды или клиентов, посмотрите разработку мини-приложений Telegram; под MAX делаю на той же базе.

Сколько стоит

Цены по моему прайсу:

  • Бот в мессенджере: от 30 000 ₽, от 1 недели.
  • Бот для бизнеса с мини-приложением, оплатой, записью или CRM: от 80 000 ₽, от 2 недель.
  • PWA-приложение с кабинетом в браузере и на телефоне: от 150 000 ₽, от 1 месяца.
  • Технический аудит готового приложения, включая проверку входа и прав: от 50 000 ₽, от 1 недели.
  • Разработка по часам, если нужно только поправить проверку подписи: от 3 000 ₽ в час.

Частые вопросы

Человеку нужно что-то вводить при входе?

В мессенджере нет. Он открывает приложение из бота, и сервер узнаёт его по подписи. Номер телефона спрашивается одной кнопкой, только если он нужен для склейки профилей или для связи.

Одинаково ли это работает в Telegram и MAX?

По документации обоих мессенджеров схема проверки одна: HMAC-SHA256 с ключом WebAppData и токеном бота. Детали передачи данных отличаются, поэтому код проверки я тестирую на живых клиентах каждого мессенджера.

Что будет, если украдут токен бота?

Тогда можно подделать подпись любого пользователя. Токен нужно сразу перевыпустить, а сервер обновить. Поэтому токен хранится только на сервере и не пишется в журналы.

Можно ли войти с компьютера без мессенджера?

Да, через отдельный вход: ссылка с кодом через бота или логин и пароль. Данные при этом общие с мини-приложением.

Коротко о главном

Вход без пароля в мини-приложение держится на одной проверке: сервер пересчитывает подпись initData токеном бота и не верит ничему, что пришло из браузера без подписи. Срок жизни входа задаёт сервер по auth_date, и для этого его часы должны идти точно. Номер телефона, подтверждённый мессенджером, склеивает профили, а для PWA и браузера нужен свой вход.

Если хотите проверить вход в своём мини-приложении или сделать новое, напишите мне в Telegram слово «ПОДПИСЬ».

Всё о мессенджере MAX в одном месте

Эта статья — часть кластера материалов о MAX: разработка ботов и мини-аппов, продвижение канала, воронки, отраслевые сценарии и кейсы с реальными результатами.

Обсудим вашу задачу

Мини-приложение с надёжным входом

Напишите одной фразой, что нужно. Отвечу, что подойдёт, сколько займёт и сколько стоит. Сообщение уже подготовлено.

  • Проверка подписи initData на сервере для Telegram и MAX
  • Один профиль по номеру телефона из двух мессенджеров и сайта
  • Вход в PWA и браузере через бота или по паролю
  • Аудит входа и прав в готовом приложении
Пишу о разработке, ИИ и законах для бизнеса

Разборы, кейсы и практика — без воды. Выходит регулярно, читать 3–5 минут.

Готовые решения под ключTurnkey solutionsSoluciones llave en mano交钥匙解决方案Түлхүүр гардуулах шийдэл 451 готовых IT-решений для бизнеса451 ready-made IT solutions for business451 soluciones IT listas para empresas451 个面向企业的现成 IT 解决方案Бизнест зориулсан 451 бэлэн IT шийдэл Автоматизация, боты, AI, 152-ФЗ и платформы · бесплатная консультацияAutomation, bots, AI, data privacy and platforms · free consultationAutomatización, bots, IA, privacidad de datos y plataformas · consulta gratis自动化、机器人、AI、数据合规与平台 · 免费咨询Автоматжуулалт, бот, AI, өгөгдлийн хамгаалалт ба платформ · үнэгүй зөвлөгөө Смотреть каталогView catalogVer catálogo查看目录Каталог үзэх