OAuth 2.0 и JWT авторизация на PHP: полное руководство

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

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

Начать курс

Введение: зачем нужны OAuth 2.0 и JWT в PHP

Современные веб-приложения редко работают изолированно. Пользователи ожидают единого входа через Google, Facebook или GitHub, а разработчики — безопасного обмена данными между микросервисами. Два ключевых протокола — OAuth 2.0 (делегирование доступа) и JWT (компактный формат токена) — стали стандартом де-факто. В этой статье мы разберём, как реализовать OAuth 2.0 и JWT авторизацию на PHP с нуля, используя только встроенные возможности языка и популярные библиотеки. Вы получите готовые примеры кода для интеграции с внешними провайдерами и создания собственной системы аутентификации.

1. Основы OAuth 2.0: потоки и роли

OAuth 2.0 — это протокол авторизации, который позволяет сторонним приложениям получать ограниченный доступ к ресурсам пользователя без передачи пароля. В нём участвуют четыре роли:

  • Resource Owner — пользователь, владеющий данными.
  • Client — ваше PHP-приложение, запрашивающее доступ.
  • Authorization Server — сервер, выдающий токены (например, Google).
  • Resource Server — API, предоставляющее данные по токену.

Самый популярный поток для веб-приложений — Authorization Code Grant. Он безопасен, так как токен передаётся через серверную часть, а не через браузер. Рассмотрим реализацию на PHP.

1.1. Регистрация приложения и получение Client ID/Secret

Перед написанием кода зарегистрируйте приложение у провайдера (например, в Google Cloud Console). Вы получите client_id и client_secret, а также настроите redirect URI (например, https://вашсайт.ru/callback.php).

1.2. Реализация потока Authorization Code на PHP

Создадим два файла: login.php (перенаправление на сервер авторизации) и callback.php (обработка ответа).

Файл login.php

<?php
session_start();

$client_id = 'ВАШ_CLIENT_ID';
$redirect_uri = 'https://вашсайт.ru/callback.php';
$state = bin2hex(random_bytes(16)); // защита от CSRF
$_SESSION['oauth_state'] = $state;

$params = http_build_query([
    'client_id'     => $client_id,
    'redirect_uri'  => $redirect_uri,
    'response_type' => 'code',
    'scope'         => 'openid email profile',
    'state'         => $state,
]);

header('Location: https://accounts.google.com/o/oauth2/v2/auth?' . $params);
exit;
?>

Файл callback.php

<?php
session_start();

// Проверка state (CSRF)
if ($_GET['state'] !== $_SESSION['oauth_state']) {
    die('Ошибка: неверный state');
}

$client_id = 'ВАШ_CLIENT_ID';
$client_secret = 'ВАШ_CLIENT_SECRET';
$redirect_uri = 'https://вашсайт.ru/callback.php';

// Обмен кода на токен
$ch = curl_init('https://oauth2.googleapis.com/token');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'code'          => $_GET['code'],
    'client_id'     => $client_id,
    'client_secret' => $client_secret,
    'redirect_uri'  => $redirect_uri,
    'grant_type'    => 'authorization_code',
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
$access_token = $data['access_token'] ?? null;

// Получение профиля пользователя
$ch = curl_init('https://www.googleapis.com/oauth2/v2/userinfo');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $access_token]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$userInfo = json_decode(curl_exec($ch), true);
curl_close($ch);

echo 'Привет, ' . htmlspecialchars($userInfo['email']);
?>

Важно: Всегда проверяйте параметр state. Он защищает от подделки запроса (CSRF).

2. JWT (JSON Web Token): структура и создание на PHP

JWT — это компактный и самодостаточный токен, который состоит из трёх частей: Header, Payload и Signature. Он идеально подходит для stateless-авторизации: сервер не хранит сессии, а проверяет подпись токена. На PHP мы можем создать JWT с помощью библиотеки firebase/php-jwt или руками.

2.1. Установка библиотеки через Composer

composer require firebase/php-jwt

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

<?php
require_once 'vendor/autoload.php';

use Firebase\JWT\JWT;

$secret_key = 'ваш-секретный-ключ-длиной-не-менее-32-символа';
$payload = [
    'iss' => 'https://вашсайт.ru',     // издатель
    'iat' => time(),                   // время выпуска
    'exp' => time() + 3600,            // срок действия (1 час)
    'sub' => 123,                      // ID пользователя
    'email' => 'user@example.com',
];

$jwt = JWT::encode($payload, $secret_key, 'HS256');
echo $jwt;
?>

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

<?php
require_once 'vendor/autoload.php';

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

$secret_key = 'ваш-секретный-ключ-длиной-не-менее-32-символа';
$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; // Bearer token из заголовка

try {
    $decoded = JWT::decode($jwt, new Key($secret_key, 'HS256'));
    echo 'Пользователь ID: ' . $decoded->sub;
} catch (\Exception $e) {
    http_response_code(401);
    echo 'Ошибка авторизации: ' . $e->getMessage();
}
?>

Блоги

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