Інтеграція офіційного віджета входу в Telegram дозволяє користувачам автентифікуватися у вебдодатку за допомогою свого облікового запису Telegram. Коли користувач авторизується через віджет, Telegram передає параметри автентифікації (наприклад, id, first_name, username, auth_date і hash) назад на вказану URL-адресу перенаправлення або зворотний виклик JavaScript.
У цьому уроці ми побудуємо механізм валідації бекенду на PHP і реалізуємо його всередині контролера додатків Yii2. Ми обчислимо очікуваний підпис HMAC-SHA-256, виконаємо безпечне за часом порівняння хешів, перевіримо свіжість підпису та зв'яжемо вхідний Telegram ID у вашій базі даних користувачів.
Що охоплює цей посібник: - Побудова data_check_string відповідно до специфікацій віджета входу в Telegram. - Генерація секретного ключа через sha256(bot_token). - Перевірка підписів корисного навантаження за допомогою hash_equals(). - Прив'язка перевіреного запису Telegram ID у Yii2.
Чого цей посібник не охоплює: - Налаштування інтерфейсних віджетів JavaScript або коду вставки HTML. - Верифікація initData Telegram Mini App (яка використовує інший процес отримання секретного ключа).
---
\nАлгоритм верифікації Telegram
\nНа відміну від Mini App initData (який використовує буквальний рядок \"WebAppData\" як ключ HMAC), стандартний віджет входу в Telegram отримує свій секретний ключ, беручи бінарний хеш SHA-256 вашого токена бота.
Кроки алгоритму: 1. Витягніть параметр hash із вхідного корисного навантаження. 2. Відфільтруйте hash від решти ключів. 3. Відсортуйте решту пар ключ-значення в алфавітному порядку за назвою ключа. 4. Відформатуйте кожну пару як key=value і об'єднайте їх символами нового рядка (\\n). 5. Згенеруйте секретний ключ: hash('sha256', $botToken, true). 6. Обчисліть hash_hmac('sha256', $dataCheckString, $secretKey). 7. Перевірте результат за отриманим хешем, використовуючи hash_equals(). 8. Переконайтеся, що auth_date перебуває в межах прийнятного порогу (наприклад, 86 400 секунд).
Ось багаторазовий клас обслуговування PHP, який реалізує цю логіку перевірки:
\n<?php
declare(strict_types=1);
namespace app\components;
final class TelegramLoginValidator
{
public function isValid(array $authData, string $botToken, int $maxAgeSeconds = 86400): bool
{
if (!isset($authData['hash'], $authData['auth_date'])) {
return false;
}
$checkHash = (string)$authData['hash'];
unset($authData['hash']);
// Check payload freshness
$authDate = (int)$authData['auth_date'];
if ((time() - $authDate) > $maxAgeSeconds) {
return false;
}
// Filter non-string values and build key=value list
$dataCheckArr = [];
foreach ($authData as $key => $value) {
if (is_scalar($value)) {
$dataCheckArr[] = $key . '=' . $value;
}
}
// Sort keys alphabetically
sort($dataCheckArr, SORT_STRING);
$dataCheckString = implode("\n", $dataCheckArr);
// Secret key is the raw binary SHA-256 hash of the bot token
$secretKey = hash('sha256', $botToken, true);
$hash = hash_hmac('sha256', $dataCheckString, $secretKey);
return hash_equals($hash, $checkHash);
}
}\n---
\nІнтеграція з контролером Yii2
\nПотім підключіть цей валідатор до дії контролера Yii2. Ми витягуємо токен бота зі змінних оточення або Yii::$app->params, виконуємо перевірку достовірності та або пов'язуємо вхідний Telegram ID із існуючою сесією автентифікованого користувача, або створюємо новий обліковий запис користувача.
Переконайтеся, що таблиця бази даних User має індексований стовпець Telegram ID (BIGINT, nullable, unique).
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\BadRequestHttpException;
use app\models\User;
use app\components\TelegramLoginValidator;
class AuthController extends Controller
{
public function actionTelegramCallback()
{
$requestParams = Yii::$app->request->get();
$botToken = (string)(getenv('TELEGRAM_BOT_TOKEN') ?: (Yii::$app->params['telegramBotToken'] ?? ''));
if (empty($botToken)) {
throw new \LogicException('Telegram bot token is not configured.');
}
$validator = new TelegramLoginValidator();
if (!$validator->isValid($requestParams, $botToken)) {
throw new BadRequestHttpException('Invalid or expired Telegram authentication signature.');
}
$telegramId = (int)$requestParams['id'];
$username = $requestParams['username'] ?? null;
// Check if a user with this telegram_id already exists
$user = User::findOne(['telegram_id' => $telegramId]);
if (!$user) {
// If currently logged in, link telegram_id to current profile
if (!Yii::$app->user->isGuest) {
/** @var User $user */
$user = Yii::$app->user->identity;
$user->telegram_id = $telegramId;
$user->save(false, ['telegram_id']);
Yii::$app->session->setFlash('success', 'Telegram account connected successfully.');
return $this->redirect(['/user/profile']);
}
// Register a new user account bound to this Telegram identity
$user = new User();
$user->telegram_id = $telegramId;
$user->username = $username ?: 'tg_' . $telegramId;
$user->generateAuthKey(); // Sets random auth_key for session security
if (!$user->save()) {
throw new \RuntimeException('Failed to register user account.');
}
}
// Log the user into the Yii2 application session
Yii::$app->user->login($user, 3600 * 24 * 30);
return $this->redirect(['/site/dashboard']);
}
}\n---
\nV. МІРКУВАННЯ ЩОДО ПІДГОТОВКИ ДО ПРОДАКШЕНУ
\n1. Конфігурація змінних оточення: Ніколи не вшивайте токени ботів у код. Зберігайте TELEGRAM_BOT_TOKEN у змінних системного оточення або безпечно завантажуйте з .env файлів з використанням getenv. 2. Захист від повторного використання (Replay Protection): Перевірка auth_date забезпечує максимальне вікно (наприклад, 24 години). Якщо ваш додаток обробляє транзакції високої вартості, розгляньте можливість збереження використаних рядків hash у Redis на час дії вікна закінчення терміну придатності, щоб повністю запобігти повторним атакам. 3. Логіка прив'язки облікового запису: Якщо користувач уже пройшов автентифікацію за допомогою традиційних облікових даних (адреса електронної пошти/пароль), запропонуйте йому зв'язати свій обліковий запис Telegram зі сторінки свого профілю, а не перезаписувати існуючі записи автоматично.
Потрібні кастомні архітектури ботів або спеціалізовані бекенд-інтеграції, створені для продакшен-навантажень? BotCreator — студія, яка створює Telegram-бот / мінідодатки.
"