Введение в OAuth 2.0 и JWT на PHP
Современные веб-приложения редко обходятся без систем авторизации. Два самых популярных протокола — OAuth 2.0 и JWT (JSON Web Token) — позволяют разработчикам создавать безопасные и масштабируемые решения. В этой статье мы разберём, как реализовать OAuth 2.0 и JWT авторизацию на PHP с нуля. Материал ориентирован на начинающих, поэтому все концепции будут объяснены простым языком с практическими примерами.
OAuth 2.0 — это протокол делегированного доступа. Он позволяет пользователям давать третьим лицам ограниченный доступ к своим ресурсам без передачи пароля. JWT, в свою очередь, — это компактный формат токена, который содержит всю необходимую информацию о пользователе и его правах.
Что такое JWT и как он работает?
JWT (JSON Web Token) — это открытый стандарт (RFC 7519), который определяет компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Токен состоит из трёх частей, разделённых точками:
- Header — содержит информацию о типе токена и алгоритме шифрования (обычно HS256 или RS256).
- Payload — содержит "утверждения" (claims): данные пользователя, время выпуска (iat), время истечения (exp) и другие.
- Signature — подпись, созданная на основе header, payload и секретного ключа. Гарантирует целостность данных.
Вот как выглядит типичный JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ItCQ0L3QsNGC0L7Qu9C40LkiLCJpYXQiOjE1MTYyMzkwMjJ9.4vGJ7qF6b0Q9l8z3X5p2Rk1h7t9y2w4z6x8c0v2b4n6m8
Преимущество JWT в том, что серверу не нужно хранить сессии в базе данных — вся информация уже закодирована в токене. Это делает систему легко масштабируемой.
Установка библиотеки для работы с JWT в PHP
Для работы с JWT в PHP мы будем использовать популярную библиотеку firebase/php-jwt. Установите её через Composer:
composer require firebase/php-jwt
Создание и верификация JWT токена
Рассмотрим базовый пример создания токена при входе пользователя и его проверку при запросе к защищённому ресурсу.
1. Генерация токена (login.php):
<?php
require_once 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secretKey = 'ваш-секретный-ключ-длиной-не-менее-32-символов';
// Данные пользователя после успешной аутентификации
$payload = [
'iss' => 'pythonlib.ru', // Издатель токена
'sub' => $userId, // ID пользователя
'name' => $userName, // Имя пользователя
'role' => 'user', // Роль
'iat' => time(), // Время выпуска
'exp' => time() + 3600 // Токен истекает через 1 час
];
$jwt = JWT::encode($payload, $secretKey, 'HS256');
// Отправляем токен клиенту
echo json_encode(['token' => $jwt]);
?>
2. Проверка токена (profile.php):
<?php
require_once 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secretKey = 'ваш-секретный-ключ-длиной-не-менее-32-символов';
// Получаем токен из заголовка Authorization
$headers = getallheaders();
$authHeader = $headers['Authorization'] ?? '';
if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
$jwt = $matches[1];
try {
$decoded = JWT::decode($jwt, new Key($secretKey, 'HS256'));
// Токен валиден, получаем данные пользователя
$userId = $decoded->sub;
$userName = $decoded->name;
// Возвращаем защищённые данные
echo json_encode(['status' => 'success', 'user' => $decoded]);
} catch (Exception $e) {
// Токен недействителен или истёк
http_response_code(401);
echo json_encode(['error' => 'Unauthorized: ' . $e->getMessage()]);
}
} else {
http_response_code(401);
echo json_encode(['error' => 'No token provided']);
}
?>
Что такое OAuth 2.0 и как он работает?
OAuth 2.0 — это протокол авторизации, который позволяет приложениям получать ограниченный доступ к ресурсам пользователя без раскрытия его учётных данных. В отличие от JWT, который является форматом токена, OAuth 2.0 определяет целый поток (flow) взаимодействия между четырьмя участниками:
- Resource Owner — пользователь, владеющий данными.
- Client — приложение, которое хочет получить доступ к данным.
- Authorization Server — сервер, выдающий токены после аутентификации.
- Resource Server — сервер, хранящий данные пользователя.
Самый популярный поток — Authorization Code Grant. Он используется, когда клиент (например, веб-приложение) может безопасно хранить секретный ключ.
Реализация OAuth 2.0 Authorization Code Flow на PHP
Рассмотрим упрощённую реализацию, где наше PHP-приложение выступает в роли Authorization Server.
Шаг 1: Пользователь авторизуется и получает code (authorize.php)
<?php
// Проверяем, авторизован ли пользователь
session_start();
if (!isset($_SESSION['user_id'])) {
// Перенаправляем на страницу логина
header('Location: /login.php?redirect=' . urlencode($_SERVER['REQUEST_URI']));
exit;
}
// Получаем параметры запроса
$clientId = $_GET['client_id'] ?? '';
$redirectUri = $_GET['redirect_uri'] ?? '';
$state = $_GET['state'] ?? '';
// Проверяем валидность клиента (упрощённо)
$