Перейти к содержанию
Innovialabs

Как добавить вход через Telegram на сайт

Практика3 мин

Коротко

Создайте бота, привяжите к нему домен через BotFather, вставьте виджет на сайт, а на сервере проверьте подпись hash с помощью SHA-256 от токена бота и свежесть auth_date — только после этого создавайте сессию.

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

Telegram Login Widget — кнопка «Войти через Telegram», которую Telegram отрисовывает на вашем сайте. Пользователь подтверждает вход в Telegram, а виджет возвращает вам данные:

  • id — постоянный идентификатор пользователя;
  • first_name, last_name, username, photo_url — профиль (часть полей может отсутствовать);
  • auth_date — время авторизации в Unix-формате;
  • hash — подпись, по которой сервер проверяет, что данные пришли от Telegram.

Главное правило: данные из браузера ничего не значат, пока сервер не проверил hash. Подделать JSON с чужим id может кто угодно.

Шаг 1. Бот и домен

  1. Создайте бота в @BotFather или используйте существующего. От его имени будет запрашиваться вход.
  2. Отправьте BotFather команду /setdomain и укажите домен сайта. Виджет работает только на привязанном домене.
  3. Сохраните токен бота в переменных окружения сервера. Он нужен для проверки подписи и не должен попадать во фронтенд.

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

Шаг 2. Виджет на странице

Есть два режима: редирект на ваш URL с данными в query-параметрах или callback в JavaScript.

<script async src="https://telegram.org/js/telegram-widget.js?22"
  data-telegram-login="your_bot"
  data-size="large"
  data-auth-url="https://example.com/auth/telegram"
  data-request-access="write"></script>
  • data-auth-url — Telegram перенаправит пользователя на этот адрес с параметрами id, auth_date, hash и др.
  • Вместо него можно указать data-onauth="onTelegramAuth(user)" и отправить объект user на сервер POST-запросом.
  • data-request-access="write" — запрашивает разрешение боту писать пользователю. Нужно, если планируете уведомления.

Шаг 3. Проверка hash на сервере

Алгоритм:

  1. Возьмите все полученные поля, кроме hash.
  2. Отсортируйте их по ключу и соберите строку key=value, разделяя строки символом \n.
  3. Секретный ключ — SHA-256 от токена бота (сырые байты).
  4. Посчитайте HMAC-SHA-256 строки этим ключом и сравните hex-результат с hash.
  5. Проверьте, что auth_date не слишком старый.
import hashlib, hmac, time

def verify_telegram_login(data: dict, bot_token: str, max_age: int = 86400) -> bool:
    received_hash = data.pop("hash", "")
    check_string = "\n".join(f"{k}={v}" for k, v in sorted(data.items()))
    secret = hashlib.sha256(bot_token.encode()).digest()
    expected = hmac.new(secret, check_string.encode(), hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, received_hash):
        return False
    return time.time() - int(data["auth_date"]) < max_age

Важные детали:

  • Используйте сравнение за постоянное время (hmac.compare_digest, crypto.timingSafeEqual).
  • Включайте в строку все полученные поля, а не только известные вам: Telegram может добавлять новые.
  • Не путайте с Mini App: там секретный ключ считается иначе — через HMAC с ключом WebAppData.

Шаг 4. Привязка аккаунтов

Храните связь по id, а не по username: имя пользователя можно сменить или удалить.

Типовые сценарии:

  • Новый пользователь — создаёте аккаунт с telegram_id.
  • Уже вошёл другим способом — в настройках профиля нажимает «Привязать Telegram», и вы добавляете telegram_id к текущему аккаунту.
  • Есть аккаунт с email, но вошёл через Telegram впервые — не склеивайте автоматически. Виджет не передаёт email и телефон, поэтому совпадение имени ничего не доказывает. Предложите войти старым способом и привязать Telegram.

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

Шаг 5. Сессия

После успешной проверки сервер создаёт свою сессию — Telegram больше не участвует.

  • Cookie с флагами HttpOnly, Secure, SameSite=Lax или Strict.
  • Не используйте hash или auth_date как токен сессии.
  • Ограничьте окно auth_date, чтобы перехваченную ссылку с параметрами нельзя было использовать повторно спустя долгое время.
  • После редиректа уберите параметры из адресной строки, чтобы они не попали в историю браузера и логи.
  • Дайте пользователю возможность выйти и отвязать Telegram.

Частые ошибки

  • Доверие данным из onTelegramAuth без серверной проверки.
  • Токен бота во фронтенд-коде.
  • Проверка только известных полей вместо всех полученных.
  • Отсутствие проверки auth_date.

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

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

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.