Авторизация через Telegram на PHP и Laravel — PROG-TIME

Авторизация через Telegram на PHP и Laravel

21.03.2025
Содержание:

Авторизация через Telegram — удобный и безопасный способ входа в систему без необходимости запоминать пароли. Telegram предоставляет встроенный механизм авторизации с использованием бота, который передаёт проверенные данные пользователя.

В этой статье рассмотрим, как реализовать авторизацию через Telegram в PHP и Laravel.

Как работает авторизация через Telegram

Telegram предлагает метод авторизации через Telegram Login Widget. Этот механизм позволяет пользователю войти через свой Telegram-аккаунт и передать данные в ваше приложение.

Процесс авторизации выглядит так:

  1. Пользователь нажимает на кнопку входа через Telegram.
  2. Telegram отображает окно подтверждения.
  3. После успешного входа Telegram перенаправляет пользователя обратно на сайт с его данными.
  4. Сервер проверяет подлинность данных и выполняет авторизацию.

Настройка бота в Telegram

Перед началом работы необходимо создать бота в Telegram:

  1. Открываем @BotFather и отправляем команду /newbot.
  2. Придумываем имя и username для бота.
  3. Получаем токен API бота, который понадобится для верификации данных.
  4. Переходим в настройки бота, в раздел «Bot Settings->Domain» и указываем домен сайта, на котором будем настраивать авторизацию.

Авторизация на чистом PHP

Для настройки авторизации на чистом PHP вам необходимо разместить кнопку, на вашем сайте.

<script async src="https://telegram.org/js/telegram-widget.js?15"
    data-telegram-login="{TELEGRAM_BOT_USERNAME}"
    data-size="large"
    data-auth-url="{путь до файла обработчика}"
    data-request-access="write"></script>

После успешной авторизации, ответ от Telegram бота будет отправлен на указанный скрипт. В ответе вы получите массив с данными о пользователе.

Пример данных:

[
  "id" => "1424126511"
  "first_name" => "Илья"
  "last_name" => "Лящук"
  "username" => "iliyalyachuk"
  "photo_url" => "https://t.me/i/userpic/320/1ICerdfdsfvCa5QqgLqT5RI.jpg"
  "auth_date" => "1742509532"
  "hash" => "9306b4eec36f0asda73ffde3d5fea29a58b1585656a124af"
]

Далее вы записываете данные в БД и фиксируете, что пользователь авторизован.

Настройка авторизации на PHP и Laravel

Для более ООП-ориентированной реализации с учётом лучших практик Laravel, мы можем выделить несколько компонентов, чтобы код был чистым, тестируемым и следовал принципам SOLID.

Для начала нам необходимо занести информации о боте в переменные, в env файл:

TELEGRAM_BOT_TOKEN='7556733496:AAEjTNztVTdbasdjSf8-gt_bMO3QndQrCDFI'
TELEGRAM_BOT_USERNAME='prog_time_auth_bot'

После, создадим сервисный класс, который будет отвечать за логику авторизации.

Создайте класс в папке app/Services/TelegramAuthService.php. Этот сервис будет заниматься валидацией данных от Telegram и регистрацией/авторизацией пользователей.

namespace App\Services;

use Illuminate\Support\Facades\Auth;
use App\Models\User;

class TelegramAuthService
{
    /**
     * Валидирует данные, полученные от Telegram
     * 
     * @param array $data
     * @return bool
     */
    public function validateTelegramData(array $data): bool
    {
        $check_hash = $data['hash'];
        unset($data['hash']);

        ksort($data); // Сортируем массив
        $data_check_string = '';

        foreach ($data as $key => $value) {
            $data_check_string .= "$key=$value\n";
        }

        $bot_token = env('TELEGRAM_BOT_TOKEN');
        $secret_key = hash('sha256', $bot_token, true);
        $hash = hash_hmac('sha256', trim($data_check_string), $secret_key);

        return hash_equals($hash, $check_hash);
    }

    /**
     * Авторизует пользователя или создает нового
     * 
     * @param array $data
     * @return \App\Models\User
     */
    public function authenticateOrCreateUser(array $data): User
    {
        // Ищем пользователя по Telegram ID, если нет — создаем
        return User::firstOrCreate([
            'telegram_id' => $data['id'],
        ], [
            'name' => $data['first_name'] ?? 'Unknown',
            'email' => $data['email'] ?? 'telegram@user.ru',
            'username' => $data['username'] ?? null,
            'avatar' => $data['photo_url'] ?? null,
            'password' => Hash::make(Str::random(16)),
        ]);
    }
}

Важный момент! Если вы используете стандартную схему таблицы users от Laravel, то система будет выдать ошибку связанную с обязательным заполнением поле «email» и «пароль» . Вы можете сгенерировать данные для этих полей в процессе добавления пользователя или изменить обязательность полей в БД.

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

Выполните команду для создания контроллера:

php artisan make:controller TelegramAuthController

В файле app/Http/Controllers/TelegramAuthController.php будет следующий код:

namespace App\Http\Controllers;

use App\Services\TelegramAuthService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class TelegramAuthController extends Controller
{
    protected $telegramAuthService;

    public function __construct(TelegramAuthService $telegramAuthService)
    {
        $this->telegramAuthService = $telegramAuthService;
    }

    /**
     * Обрабатывает callback от Telegram и выполняет авторизацию
     * 
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function callback(Request $request)
    {
        $data = $request->all();

        // Валидируем данные от Telegram
        if (!$this->telegramAuthService->validateTelegramData($data)) {
            abort(403, 'Данные недействительны');
        }

        // Авторизуем пользователя или создаем нового
        $user = $this->telegramAuthService->authenticateOrCreateUser($data);

        // Авторизация пользователя в системе
        Auth::login($user);

        return redirect()->route('dashboard'); // Перенаправление на главную страницу
    }
}

Теперь необходимо добавить маршрут в routes/web.php

use App\Http\Controllers\AuthController;
use App\Http\Controllers\TelegramAuthController;
use Illuminate\Support\Facades\Route;

/* принимает ответ от Telegram */
Route::get('/auth/telegram/callback', [TelegramAuthController::class, 'callback'])->name('auth.telegram.callback');

/* страница авторизации */
Route::get('/login', [AuthController::class, 'showLoginPage'])->name('login');

/* страница админки, доступная только для авторизованных */
Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware('auth')->name('dashboard');

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

php artisan make:migration add_telegram_fields_to_users_table

Миграция в файле database/migrations/xxxx_xx_xx_xxxxxx_add_telegram_fields_to_users_table.php

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->bigInteger('telegram_id')->unique()->nullable();
        $table->string('username')->nullable();
        $table->string('avatar')->nullable();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn(['telegram_id', 'username', 'avatar']);
    });
}

Применяем миграцию:

php artisan migrate

Теперь сделаем страницу авторизации.

Для начала создадим контроллер:

namespace App\Http\Controllers;

use Illuminate\Contracts\View\View;

class AuthController extends Controller
{

    /**
     * Показывает страницу входа
     * @return View
     */
    public function showLoginPage(): View
    {
        return view('auth.telegram-login');
    }
}

Далее создаём представление resources/views/auth/telegram-login.blade.php, для страницы авторизации

...
<div class="container">
    <h2>Вход через Telegram</h2>
    <p>Нажмите кнопку ниже, чтобы войти:</p>

    <script async src="https://telegram.org/js/telegram-widget.js?15"
            data-telegram-login="{{ env('TELEGRAM_BOT_USERNAME') }}"
            data-size="large"
            data-auth-url="{{ route('auth.telegram.callback') }}"
            data-request-access="write"></script>
</div>
...

Разбор параметров:

  • data-telegram-login — имя вашего бота.
  • data-size — размер кнопки (small, medium, large).
  • data-auth-url — URL, куда будут отправлены данные после успешной авторизации.
  • data-request-access — запрашиваемые разрешения (по умолчанию write).

После нажатия на кнопку пользователю будет предложено войти в Telegram и подтвердить вход.

Последним этапом, создаём представление для страницы, которая будет открываться после авторизации. Но это уже на ваше усмотрение!

Итог

Теперь у вас есть готовая авторизация через Telegram в Laravel. Пользователь нажимает кнопку входа, Telegram передаёт данные, Laravel проверяет их и создаёт пользователя.

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

Попробуйте внедрить этот метод в своё приложение и упростите процесс авторизации для пользователей!

Материалы курса