Как добавить вход через Telegram на сайт
Практика3 минРедакция Innovialabs
Коротко
Создайте бота, привяжите к нему домен через 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. Бот и домен
- Создайте бота в @BotFather или используйте существующего. От его имени будет запрашиваться вход.
- Отправьте BotFather команду
/setdomainи укажите домен сайта. Виджет работает только на привязанном домене. - Сохраните токен бота в переменных окружения сервера. Он нужен для проверки подписи и не должен попадать во фронтенд.
Для локальной разработки виджету нужен настоящий домен, поэтому обычно используют туннель или тестовый поддомен.
Шаг 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 на сервере
Алгоритм:
- Возьмите все полученные поля, кроме
hash. - Отсортируйте их по ключу и соберите строку
key=value, разделяя строки символом\n. - Секретный ключ — SHA-256 от токена бота (сырые байты).
- Посчитайте HMAC-SHA-256 строки этим ключом и сравните hex-результат с
hash. - Проверьте, что
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.