Реализация аутентификации в telegram-боте через OAuth2 на примере Box API

Что дальше

  1. Привести код бота в порядок: выделить классы, методы,
  2. Сделать конфигурирование бота более удобным,
  3. Реализовать загрузку файлов в облако.

О чём-то из этого постараюсь написать позже.

Исходники для этой заметки можно найти на github.

Corner_radius


Опциональный параметр

corner_radius

принимает целочисленное число от 1 до 20 (это значение по умолчанию). Прямоугольная — 1, закругленная — 20.

Localtunnel

Telegram требует доменное имя для вашего веб-сайта, потому что будет делать запросы на ваш сайт, передавать данные пользователя. Поэтому вам нужен тоннель — веб-сайт в сети, который будет переправлять все запросы на ваш

localhost

Установите пакет localtunnel с помощью npm (убедитесь, что он у вас установлен).

$ npm install -g localtunnel


Запустите

localtunnel

на порту, на котором вы будете поднимать свой сервер

Django

$ lt --port 8000

В ответ вы получите ссылку, например, такую

kqmxkdqitb.localtunnel.me

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

Запустите сервер и убедитесь, что можете достучаться до сервера через тоннель.

$ ./manage.py runserver 0.0.0.0:8000

Receiving authorization data

After a successful authorization, the widget can return data in two ways:

Авторизация под контролем

После каждого входа Telegram отправит вам уведомление о разрешенных вами данных, которые вы передали владельцу веб-сайта. Вы можете отменить авторизацию, нажав соответствующую кнопку.

Telegram начиная с версии 4.8 включает соотвествующий раздел в настройках конфиденциальности и безопасности, в котором перечислены все сайты, на которых вы вошли в систему, используя Telegram.  Пока что данная возможность доступна только на Android. Другие приложения скоро последуют обновлению.

Этот простой на первый взгляд инструмент для авторизации — лишь первый этап проекта Telegram ID, который мы будем реализовывать в течение всего этого года.

6 февраля 2022 года,Команда Telegram

В теории

OpenId Connect (OIDC) — это протокол аутентификации, основанный на семействе спецификаций OAuth 2.0. В нем процесс аутентификации может проходить по различным сценариям, называемым потоками (flow), и включает в себя три стороны:

Получаемая клиентом в результате аутентификации информация о пользователе представляется в виде JWT-токенов (JSON Web Token). Не будем сейчас углубляться в терминологию и детали спецификации OIDC, поскольку и без того есть немало статей, в том числе и на Хабре, позволяющих составить представление о базовых принципах работы OIDC.

Для решения поставленной задачи, помимо реализации основной функциональности бота, нам необходимо реализовать механизм авторизации: при получении каждого нового сообщения от пользователя необходимо проверять наличие и актуальность связки между данным Telegram-пользователем и учеткой в системе SSO. Неавторизованные пользователи при этом должны направляться на страницу аутентификации.

Для начала нам необходимо определиться с тем, какой поток аутентификации мы будем использовать. В спецификации OIDC описано несколько возможных сценариев аутентификации пользователей:

Виджет

Виджет — это внешний

JavaScript

, который принимает ваши аргументы (

data-size

— размер виджета, например), обрабатывает их и отвечает данными пользователя при корректной работе. Также он генерирует «кнопку»

Log in as

Дисклеймер

django-telegram-login

работает для

Python

2 и 3 для актуальных версий

Django

(протестировано на 1.11 и 2.0).

Статья содержит примеры по каждому из пунктов туториала. В конце статьи предоставлены полноценные примеры.

Как работает виджет

Виджет имеет следующий вид (рисунок внизу). Вы можете изменять его размеры — маленький (

small

), средний (

medium

) и большой (

large

), закруглять углы (

corner_radius

), убирать фотографию (

Логика конструирования виджетов


На примере функции

create_redirect_login_widget

, которая знает как строить виджет, можно увидеть — в тело виджета вставляются переданные в нее переменные

redirect_url

На практике

Итак, перейдем к реализации, вооружившись следующими инструментами:

Настройка базовой авторизации

Перейдём к настройке базовой авторизации. Сейчас наш класс настройки Web Security выглядит так, но позже он сильно измениться:

Настройки для telegram


Рекомендую прочесть

перед ознакомлением с материалом ниже.

Необходимый минимум об oauth2

Для реализация аутентификации через OAuth2 необходимо выполнить несколько пунктов:

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

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

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

Отображение сгенерированного скрипта на html странице

Сгенерируйте ваш виджет в какой-нибудь

view

и передайте в контекст.

Отправка сообщение в браузер, об успешной авторизации

Последнее, что осталось сделать —

потанцевать с бубном

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

Перепись авторизации на json формат

Наше приложение будет работать по такому алгоритму:
Алгоритм авторизации

Как вы видите, тут проверка пользователя идёт по порядку: спросили одно и ждём ответа, при получении ответа, если надо, спрашиваем второе. Перенаправлять пользователя со страницы на страницу было бы не очень удобно, а вот технологию AJAX применить можно было бы.

Для этого перепишем нашу авторизацию на JSON. Делать мы это будем с помощью AuthenticationSuccessHandler и AuthenticationFailureHandler, но для начала создадим модель, которую будем возвращать в качестве информации об авторизации:

public class AuthenticationInfo {
    private boolean success;
    private String redirectUrl;
    private String errorMessage;
    private Set<RequiredMfa> requiredMfas;

    public enum RequiredMfa {
        TELEGRAM_MFA
    }

    // getters, setters and no args constructor
}

Как вы видите, тут мы используем Set<RequiredMfa> requiredMfas вместо простого boolean askTelegramMfa. Как вы думаете почему?

Теперь напишем RequireTelegramMfaException. Это Exception, который мы будем выбрасывать, если пользователь должен авторизоваться с помощью Telegram. Почему? Пока пользователь не подтвердил авторизацию в Telegram, мы не должны его авторизовать, а значит мы должны выбросить Exception, что бы Spring этого не сделал.

Наш RequireTelegramMfaException обязательно должен наследоваться от AuthenticationException, а выглядеть будет так:

public class RequireTelegramMfaException extends AuthenticationException {
    public RequireTelegramMfaException(String msg) {
        super(msg);
    }
}

Теперь перейдём непосредственно к CustomAuthenticationFailureHandler. Наш код будет выглядеть вот так:

Примеры

Все необходимые настройки —

settings.py

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

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

Регистрация доменного имени


Как сказано в официальной документации Telegram, для вашего веб-сайта нужен Telegram-бот, который будет обрабатывать запросы пользователей на авторизацию. Он должен быть привязан к вашему сайту через адрес.

В дальнейшем нам понадобится юзернейм бота (

Создание и настройка telegram бота

Теперь займёмся самим Telegram ботом. В нашем pom.xml должны быть две зависимости:

наркотическая и никотиновая

Создание проекта

Итак, для начала создадим проект. Для этого я использовал Spring Initializr. Для проекта нам понадобится Spring MVC, Spring Security и Spring WebSocket. В качестве базы данных будем использовать H2. Мои настройки выглядели вот так:
Spring Initializr Settings

Затем в наш pom.xml добавим дополнительные зависимости: библиотека для работы с Telegram и webjars: bootstrap (для красивого дизайна), stomp-websocket и sockjs-client для работы с Spring WebSocket.

В итоге наш pom.xml будет выглядеть вот так.

Шаг 1. подготовка

Для работы понадобятся три внешних библиотеки:

Библиотеки и их версии прописаны в requirements.txt. Установить всё через pip install -r requirements.txt — ничего необычного. Но лучше для этого создать отдельное виртуальное окружение.

Шаг 2. продолжаем подготовку

Теперь надо получить токен для бота. Я уже писал об этом ранее.

Заключение

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

В заключение

Поставленная задача решена, но за кадром остался еще ряд вопросов, которые необходимо решить, прежде, чем катить это в прод. Например, офлайн-токены необходимо держать в персистентном хранилище, это позволит не направлять пользователей на повторную аутентификацию после каждого перезапуска/обновления бота.

Эти вопросы уже решены за нас в более развесистых OAuth-клиентах вроде Spring Security и Google OAuth Client. Но для демонстрационных целей нам и так ок 🙂

Все исходники можно найти на GitHub.

Похожее:  Межрегионгаз Краснодар: вход в ЛК физического лица

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *