null

Привязка корпоративных пользователей к Telegram

Предположим, что в Вашей компании доступ в глобальный Internet не ограничен и использование, например, Telegram не запрещено. Для того, чтобы сотрудники могли найти в telegram своих коллег, и для того, чтобы Ваш бот, при отправке сообщений в какие-то общие чаты, мог использовать @username для уведомления заинтересованных людей необходимо, чтобы в Вашей корпоративной системе каким-то образом хранились имена этих пользователей. А для того, чтобы Ваш бот мог напрямую отправлять сообщение конкретным людям, боту должен быть известен числовой идентификатор этого пользователя. И если с указанием @username всё относительно просто, так как эта информация видна в настройках пользователя, то с получением идентификатора могут возникнуть проблемы, так как для этого надо или использовать сторонние сервисы (боты), или писать своего бота, который будет иметь доступ и к внутренней корпоративной систему, и к сервисам telegram. Также при этом могут возникнуть проблемы с валидацией вводимой пользователем информации.

Всего этого можно избежать, если использовать предлагаемый Telegram вариант с аутентификацией через Login Widget. Чисто формально для этого Вам всё еще необходим telegram бот, но фактически он не будет ничего ни принимать, ни отправлять, нужны только его идентификатор и токен, который будет использовать для валидации полученных данных.

Для этого Вам потребуется на официальную страницу login widget, где Вы увидите инструкцию как привязать Вашего бота к некоторому корпоративному доменному имени, которое никак не валидируется, и будет предложено ввести Bot Username, выбрать Authorization Type и некоторые параметры, связанные с оформлением. Если с Bot Username всё понятно, то для Authorization Type предлагается два значения:

  • Callback
  • Redirect to URL

При выборе Callback необходимо будет написать на Javascript функцию, которая будет обрабатывать результат аутентификации. При выборе второго варианта после успешной аутентификации пользователь будет перенаправлен на указанный Вами URL, а в параметрах метода GET будут указаны интересующие нас id и username. Что характерно, никакой валидации вводимого URL нет, и это вполне может быть ссылкой на внутренний, недоступный из интернет, портал.

Также будет передан параметр hash, содержащий цифровую подпись HMAC-SHA-256​​​, которая формируется с использованием токена Вашего бота, и с помощью которой можно проверить, что данную информацию Вы действительно получили от Telegram, гарантируя тем самым консистентность используемых значений идентификатора и имени telegram пользователя.

Обработка такого запроса довольно проста и не требует глубокого погружения в Bot API Telegram или использования готовых библиотек, и, сопряженных с этим, мук выбора этим самых библиотек, и может быть реализована на таких архаичных языках как PHP.

Если по какой-то причине был выбран PHP, то обработка параметров с информацией о пользователе не должна вызвать каких либо проблем, но, если Вы ранее не имели опыта работа с функциями hash() и hash_hmac(), то могут возникнуть проблемы с подбором правильных параметров для этих функций. Поэтому процитирую полностью код до момента завершения проверки цифровой подписи:

$fields = [
        "id", "first_name", "last_name", "username", "photo_url", "auth_date",
];
sort($fields);

$tginfo = [];
$tginfo4chk = [];

foreach ($fields as $field)
        if (isset($_GET[$field])) {
                $tginfo[$field] = $_GET[$field];
                $tginfo4chk[] = $field . "=" . $_GET[$field];
        }

$hmac1 = $_GET["hash"];
$hmac2 = hash_hmac("sha256",
        implode("\n", $tginfo4chk),
        hash("sha256", TG_TOKEN, $binary = true)
);

if ($hmac1 != $hmac2) {
        http_response_code(400);
        die("Invalid hash received");
}

Некоторые комментарии к коду:

  1. В массиве $fields перечислены имена параметров, которые, согласно документации, могут быть переданы. Если какие-то из перечисленных полей у пользователя не заполнены, их в запросе не будет.
  2. Сортировка массива $fields нужна для корректного вычисления цифровой подписи, так как, согласно документации, она должна вычисляться для всех переданных параметров, перечисленных в алфавитном порядке. При этом в самом запросе эти параметры указаны в другом порядке.
  3. В массив $tginfo сохраняется полученная информация, которую можно использовать далее.
  4. Массив $tginfo4chk используется только для проверки цифровой подписи.
  5. При вызове функции hash() обязательно должен быть установлен параметр $binary в значение true, так как функция hash_hmac() в качестве инициализирующего ключа использует именно двоичные данные, а у самой функции hash_hmac() этот же параметр должен быть установлен в false, так как нас интересует шестнадцатеричное представление контрольной суммы, которое сравнивается со значением переданного параметра hash.

Реализация обработчика на других языках также не должна вызывать проблем. При этом сам способ достаточно простой как с точки зрения обработчика, так и для самих пользователей, и не требует наличия на компьютере пользователя клиента telegram, написания полноценного telegram bot, обработки запросов из небезопасного интернета на внутренних сервисах и других сложностей.

Вперед