Авторизация через Telegram Login Widget на примере Python и Django

Принцип работы виджета Telegram

6 февраля 2018 года команда Telegram анонсировала запуск Telegram Login Widget для внешних сайтов.

Оценить возможности виджета можно по ссылке: https://testwidgetbot.herokuapp.com/

Виджет предназначен для авторизации на сайте с помощью Telegram.

Виджет представляет собой кнопку с надписью Log in with Telegram. При нажатии на эту кнопку появляется окно, в которое пользователь должен ввести свой номер телефона. Введенный номер телефона не будет сообщен администратору сайта.

После ввода номера телефона пользователю придет уведомление в Telegram от пользователя Telegram следующего содержания:

Андрей, we received a request to log in on testwidgetbot.herokuapp.com with your Telegram account.

To authorize this request, tap the 'Confirm' button below. 

Browser: Firefox on Linux
IP: xx.xx.xx.xx (Russia)

If you didn't request this, tap 'Decline' or ignore this message.

Под сообщением будет две кнопки: Accept и Decline. При нажатии Decline запрос авторизации будет проигнорирован. При нажатии Accept запрос авторизации будет принят.

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

Создание бота Telegram

Для реализации системы авторизации необходимо создать бота.

Для этого необходимо написать в Telegram боту @BotFather. Это служебный бот для создания других ботов.

Создание бота происходит путем отправки ему команды /newbot. Бот запросит имя создаваемого бота, как его будут видеть пользователи. Второй вопрос предполагает ввод username создаваемого бота, @examplebot, t.me/examplebot. Username бота всегда должен заканчиваться на bot или Bot. Это требование Telegram. Пусть наш созданный бот называется @TestWidgetBot.

Если введенное имя уже занято, то будет предложено ввести другое. Если имя свободно, то BotFather пришлет токен созданного бота. Токен представляет собой строку вида xxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx и предназначен для авторизации бота.

Подключение домена

В целях безопасности Telegram требует привязать созданного бота к доменному имени. Для этого нужно отправить боту BotFather команду /setdomain. Бот спросит, к какому боту относится команда (необходимо выбрать созданного ранее бота), после чего ввести домен, к которому будет привязан созданный бот. Например, example.com.

Теперь можно разместить бота на любой странице example.com.

Для корректной работы виджета авторизации необхоидимо размещать сайт на 80 или 443. То есть, если при разработке запускается тестовый сервер, например, http://example.com:5000/, то виджет авторизации работать не будет. Поддомены тоже не работают, то есть разместить виджет на http://demo.example.com/ не получится. Несколько доменов командой /setdomain указать нельзя.

Возможно, эти недочеты будут устранены в дальнейшем.

Генерация кода виджета авторизации

На странице сайта example.com, в том месте страницы, где необходимо разместить виджет авторизации необходимо разместить виджета. Для получения скрипта можно воспользоваться генератором на странице документации Telegram.

В генераторе нужно ввести следующие параметры.

  1. Username бота, без символа @, например TestWidgetBot.

  2. Размер виджета, Small, Medium или Large.

  3. Выбрать тип авторизации.

    При выборе Redirect to URL при успешной авторизации пользователь будет переадресован на страницу с указанным URL. Параметры авторизованного пользователя (username, chat_id, first_name, last_name и пр.) будут переданы в качестве GET-параметров. Я использую именно этот тип авторизации.

    При выборе Callback параметры пользователя будут переданы в качестве аргумента JavaScript функции. Параметры представляют собой JSON-объект.

  4. Request Access необходимо установить, если требуется, чтобы бот мог начинать диалог с пользователем.

В моем случае получился такой код:

<script async src="https://telegram.org/js/telegram-widget.js?2" data-telegram-login="TestWidgetBot" data-size="large" data-auth-url="https://testwidgetbot.herokuapp.com/register/" data-request-access="write"></script>

Сгенерированный код необходимо скопировать и вставить на странице сайта.

Обработка запроса на сервере

При подтверждении пользователем авторизации на сайте, в зависимости от выбранного параметра "тип авторизации", либо выполнится JavaScript-функция, либо пользователь будет перенаправлен на страницу Callback URL. В качестве GET-параметров на эту страницу будут переданы данные пользователя.

Рассмортрим второй вариант.

Callback URL в моем случае https://testwidgetbot.herokuapp.com/register/. Telegram не требует, чтобы этот URL совпадал частично или полностью с доменом, который установлен /setdomain

Рассмотрим на примере. Предположим что клиент с chat_id 8951599, именем Andrey, фамилией S, авторизовался на сайте в момент времени 1518613843. Тогда после подтверждения авторизации он будет перенаправлен на URL:

https://testwidgetbot.herokuapp.com/register/?id=8951599&first_name=Andrey&last_name=S&auth_date=1518613843&hash=1678ace4c395d7adgca63f446d2aedb0fad21c935ffced6315fc524a44cb7fc7.

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

https://github.com/ansmirnov/telegram-testwidgetbot/blob/master/tgwidget/utils.py

Использовать класс следует следующим образом:

from .utils import HashCheck

secret = os.getenv('BOT_TOKEN').encode('utf-8')

if not HashCheck(request.GET, secret).check_hash():
    # Hash не верен
else:
    # Hash верен

Переменная окружения BOT_TOKEN должна содержать токен бота.

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

Заключение

В статье описан общий принцип работы авторичзации пользователя на сайте с использованием Telegram Login Widget. В статье используется технологии Python и Django, однако принцип может быть реализован с применением любых технологий, позволяющий обработать GET-запрос.

Разработан демонстрационный проект. Посмотреть результат можно по ссылке https://testwidgetbot.herokuapp.com/ исходный код проекта доступен на GitHub.