JWT токены в PHP: Полное руководство по аутентификации и авторизации

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

JWT токены в PHP: Полное руководство по реализации

JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанных на JSON-формате. В PHP JWT широко используется для реализации бесстатусной аутентификации (stateless authentication) в REST API, одностраничных приложениях (SPA) и микросервисах.

В этой статье мы подробно разберём, как работать с JWT токенами в PHP: от установки библиотеки до создания, проверки и обновления токенов.

Что такое JWT и зачем он нужен?

JWT состоит из трёх частей, разделённых точками:

  • Header (заголовок) — содержит тип токена (JWT) и алгоритм подписи (например, HS256 или RS256).
  • Payload (полезная нагрузка) — содержит утверждения (claims): идентификатор пользователя, роль, время выпуска (iat), срок действия (exp) и другие данные.
  • Signature (подпись) — создаётся путём хеширования заголовка и полезной нагрузки с использованием секретного ключа.

Основные преимущества JWT:

  • Не требует хранения сессий на сервере (stateless).
  • Может содержать любые данные (например, роль пользователя).
  • Работает с разными доменами и мобильными приложениями.
  • Легко проверяется без обращения к базе данных.

Установка библиотеки firebase/php-jwt

Для работы с JWT в PHP мы будем использовать популярную библиотеку firebase/php-jwt. Установка выполняется через Composer:

composer require firebase/php-jwt

После установки в проекте появится автозагрузка Composer, которую нужно подключить:

require_once 'vendor/autoload.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

Создание JWT токена

Для создания токена нужно определить секретный ключ ($secretKey) и сформировать payload. Пример:

use Firebase\JWT\JWT;

$secretKey = 'your-256-bit-secret-key-here';
$issuedAt = time();
$expirationTime = $issuedAt + 3600; // токен живёт 1 час

$payload = [
    'iss' => 'pythonlib.ru',        // издатель
    'iat' => $issuedAt,             // время выпуска
    'exp' => $expirationTime,       // срок действия
    'sub' => 123,                   // идентификатор пользователя
    'role' => 'admin'               // кастомные данные
];

$jwt = JWT::encode($payload, $secretKey, 'HS256');
echo $jwt;

В результате получится строка вида: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJweXRob25saWIucnUiLCJpYXQiOjE3Mjg0MDAwMDAsImV4cCI6MTcyODQwMzYwMCwic3ViIjoxMjMsInJvbGUiOiJhZG1pbiJ9.signature

Проверка и декодирование JWT

При получении токена от клиента (например, из заголовка Authorization: Bearer <token>) его нужно проверить:

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secretKey = 'your-256-bit-secret-key-here';
$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

try {
    $decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
    $userId = $decoded->sub;
    $role = $decoded->role;
    
    echo "Пользователь #{$userId} с ролью {$role} авторизован.";
} catch (\Exception $e) {
    http_response_code(401);
    echo "Ошибка: " . $e->getMessage();
}

Важно: библиотека автоматически проверяет срок действия токена (exp) и время выпуска (iat). Если токен истёк или недействителен, будет выброшено исключение.

Обновление JWT (Refresh Token)

Для повышения безопасности JWT обычно делают короткоживущими (15–60 минут). Для долгой сессии используют Refresh Token — отдельный токен, который хранится в базе данных и позволяет получить новый Access Token без повторного ввода логина/пароля.

Пример реализации refresh:

function refreshAccessToken(string $refreshToken, string $secretKey): ?string {
    // Проверяем refresh token в базе данных (упрощённая логика)
    $storedHash = 'hash_from_database'; // должен быть получен из БД
    if (!password_verify($refreshToken, $storedHash)) {                    

Рекомендаций