Авторизация через Telegram в Django и Python
Предисловие
В начале февраля Павел Дуров анонсировал, что у Telegram появился так называемый Telegram Login Widget. Проще говоря, теперь любой желающий может встроить авторизацию на своем сайте через Telegram, наряду с уже удобными способами входа через привычные для всех Google, Twitter, Facebook и так далее.
В этой заметке я хочу рассказать и наглядно показать как это сделать, используя Django. Исходный код свободно доступен в моем репозитории на GitHub. Пользуйтесь на здоровье.
Те, кто уже имеет опыт работы с Django Framework, знают, что он предоставляет готовую User модель для авторизации, более того, ее очень легко расширить или написать свою. Я решил пойти другим путём, дабы не городить своих велосипедов, воспользовался готовым и хорошо зарекомендовавшим себя пакетом для авторизации в различных сервисах — python-social-auth. Для тех, кто не в курсе, social-auth это набор готовых библиотек для авторизации через такие сайты как Twitter, Facebook, Instagram, Google, VK и многие других. Проект разбит на модули, где основным является social-core, там хранится набор т.н. бэкендов для авторизации. Помимо social-core, есть ряд пакетов для конкретных фреймворков. Для Django это social-app-django, для Tornado соответственно social-app-tornado и так далее. Покрыты практически все известные веб-фрейморки для Python. Так вот к чему это я?
Решил я внести свой вклад в развитие Open Source, и написал backend для авторизации через Telegram в основной модуль social-core. Готовый к слиянию Pull Request можно посмотреть здесь. Правда загвоздка в том, что автор проекта не спешит его сливать в master ветку, на сообщения не реагирует, поэтому пример кода будет базироваться на моем форке social-core. Будем надеяться, что PR примут. Вы можете внести свой вклад, оставив комментарий автору проекта в Issue, который я открыл по случаю готового PR.
Мой проект будет использовать Python 3.6 и Django 2.0.3. Если вам не нравится Django, то вы без труда можете использовать python-social-auth с любым другим фреймворком для реализации авторизации через Telegram для своего сайта.
Создание бота Telegram
Telegram Login Widget работает через бота, который предварительно нужно создать. Для его создания необходимо обратиться к Его Величеству @BotFather. Я уже писал статью про то как это сделать. Для нашего примера я создал бота с “привлекательным” названием @DjangoTelegramAuthBot. Кстати, после того как пользователь войдет на ваш сайт через свой Telegram аккаунт, у бота будет возможность инициировать диалог первым (при указании соответствующего разрешения).
Настройка параметров
После создания бота, необходимо сформировать js-скрипт для встраивания на сайт. А перед этим прописать будущий домен вашего сайта командой /setdomain в диалоге с @BotFather. Для удобного тестирования веб-приложения, предлагаю использовать утилиту ngrok. Поставить её можно через npm сразу в global:
npm install ngrok -g
Задача js-скрипта, сгенерированного на странице настроек, показать на сайте кнопку для входа. Вот такую:
Настройки можно задать на официальной странице Telegram. Они простые, разобраться нетрудно. Но обратите внимание на 2 параметра:
В Authorization Type необходимо выбрать способ авторизации пользователя:
- Callback. Вызов произвольной JS функции после авторизации пользователя. Если выбрать этот параметр, то в скрипте виджета появится пример такой функции, вызывающий alert с именем, фамилией, псевдонимом и id.
- Redirect to URL. Стандартный способ авторизации через редирект на заданный URL. Именно его в примере я и буду использовать. Сюда позже укажем URL через домен, полученный с помощью ngrok.
Создаем веб-приложение
Итак, склонируйте мой репозиторий. Для проекта желательно создать отдельное виртуальное окружения, чтобы не засорять системный Python и не хапнуть конфликтных ситуаций между зависимостями (а вдруг?). Установите все зависимости из requirements.txt.
Теперь необходимо рядом с settings.py создать .env файл из шаблона .env-template. Можно просто переименовать .env-template в .env. Переменной SOCIAL_AUTH_TELEGRAM_BOT_TOKEN присвойте токен вашего бота, полученный при создании в диалоге с @BotFather. SECRET_KEY в этом примере неважен, но при деплое на продакшен обязательно укажите сложный ключ.
Обратите внимание, что в моем проекте-шаблоне в качестве базы данных используется SQLite 3, это сделано для простоты первичной настройки и демонстрации. Следом выполните команду migrate:
python manage.py migrate
Это необходимо сделать для создания таблиц в базе данных для корректной работы приложения.
Теперь запускаем проект привычной командой:
python manage.py runserver
В отдельном окне терминала получим внешний адрес для сайта путем создания туннеля через утилиту ngrok.
ngrok http 8000
Как видно из скриншота моему приложению был присвоен домен e019b6e6.ngrok.io. Его необходимо прописать в настройках бота у всё того же @BotFather:
Теперь возвращаемся на страницу настройки виджета, где необходимо задать Redirect URL. Полный адрес будет выглядеть вот так:
e019b6e6.ngrok.io/auth/complete/telegram
Возникает вопрос, а как я получил такой путь? Дело в том, что путь /auth/ был задан в urls.py моего проекта для модуля urls.py пакета social_django:
urlpatterns = [
path('admin/', admin.site.urls),
path('auth/', include('social_django.urls', namespace='social')),
path('profile/', TemplateView.as_view(template_name='profile.html'), name='profile'),
path('', TemplateView.as_view(template_name='login.html')),
]
А /complete/telegram это уже стандартный шаблон для редиректа после авторизации в бэкенд-сервисе.
# код social_django.urls
urlpatterns = [
# authentication / association
url(r'^login/(?P<backend>[^/]+){0}$'.format(extra), views.auth,
name='begin'),
url(r'^complete/(?P<backend>[^/]+){0}$'.format(extra), views.complete,
name='complete'),
# disconnection
url(r'^disconnect/(?P<backend>[^/]+){0}$'.format(extra), views.disconnect,
name='disconnect'),
url(r'^disconnect/(?P<backend>[^/]+)/(?P<association_id>\d+){0}$'
.format(extra), views.disconnect, name='disconnect_individual'),
]
Более подробно о пакете python-social-auth можно почитать в документации.
Теперь полученный на странице настроек виджета JS-код копируйте в шаблон login.html (вместо моего кода вставьте туда свой). После открывайте браузер и заходите на страницу e019b6e6.ngrok.io (помните, что ваш домен может отличаться).
Если вы всё сделали правильно, то увидите примерно вот такую картинку:
Смело кликайте на виджет, разрешите доступ на авторизацию, и при успешном входе вас перекинет на страницу profile
Поздравляю! Вы успешно авторизовались на сайте через Telegram. Теперь у вас есть время, чтобы разобраться как это работает, посмотрите код моего проекта. В основном необходимо взглянуть на settings.py, всю “грязную” работу за вас делают пакеты social-auth и social-app-django. Если вам интересно как работает процесс авторизации, то изучите мой Pull Request и официальный гайд от Telegram.