Введение в OAuth 2.0 и JWT авторизацию на C++
В современном мире веб-разработки безопасность и удобство аутентификации играют ключевую роль. OAuth 2.0 и JWT (JSON Web Tokens) стали стандартами де-факто для реализации авторизации в распределенных системах. В этой статье мы рассмотрим, как реализовать OAuth 2.0 и JWT авторизацию на языке C++ — мощном и производительном языке, который часто используется для создания высоконагруженных серверных приложений.
Несмотря на то, что C++ не является типичным выбором для веб-разработки, его производительность и контроль над памятью делают его идеальным для создания API-шлюзов, микросервисов и систем реального времени. Мы покажем, как использовать современные библиотеки C++ для работы с HTTP, JSON и криптографией, чтобы построить надежную систему авторизации.
Основы OAuth 2.0
OAuth 2.0 — это протокол авторизации, который позволяет приложениям получать ограниченный доступ к ресурсам пользователя без передачи его учетных данных. Основные роли в OAuth 2.0:
- Resource Owner — пользователь, владеющий ресурсами
- Client — приложение, запрашивающее доступ
- Authorization Server — сервер, выдающий токены
- Resource Server — сервер, предоставляющий защищенные ресурсы
Основные потоки (grant types) OAuth 2.0:
- Authorization Code — для серверных приложений
- Client Credentials — для сервис-сервисной аутентификации
- Implicit — устаревший, для SPA
- Resource Owner Password Credentials — для доверенных клиентов
Реализация клиента OAuth 2.0 на C++
Для работы с HTTP в C++ мы будем использовать библиотеку cpp-httplib. Рассмотрим пример получения access token через поток Client Credentials:
#include <httplib.h>
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;
std::string get_access_token(const std::string& client_id,
const std::string& client_secret,
const std::string& token_url) {
httplib::Client cli(token_url);
// Формируем тело запроса
std::string body = "grant_type=client_credentials&"
"client_id=" + client_id + "&"
"client_secret=" + client_secret;
auto res = cli.Post("/token", body, "application/x-www-form-urlencoded");
if (res && res->status == 200) {
json response = json::parse(res->body);
return response["access_token"];
}
throw std::runtime_error("Failed to get access token");
}
JWT (JSON Web Tokens)
JWT — это компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Токен состоит из трех частей:
- Header — содержит тип токена и алгоритм подписи
- Payload — содержит claims (утверждения) о пользователе
- Signature — подпись для верификации
Генерация JWT на C++
Для работы с JWT и криптографией в C++ используем библиотеки jwt-cpp и OpenSSL. Пример генерации JWT с алгоритмом HS256:
#include <jwt-cpp/jwt.h>
#include <chrono>
std::string create_jwt(const std::string& user_id,
const std::string& secret_key) {
auto now = std::chrono::system_clock::now();
auto exp = now + std::chrono::hours(1);
auto token = jwt::create()
.set_type("JWT")
.set_issuer("auth.example.com")
.set_subject(user_id)
.set_issued_at(now)
.set_expires_at(exp)
.set_payload_claim("role", jwt::claim(std::string("admin")))
.sign(jwt::algorithm::hs256{secret_key});
return token;
}
Верификация JWT на C++
При получении JWT от клиента необходимо проверить его подпись и срок действия:
#include <jwt-cpp/jwt.h>
bool verify_jwt(const std::string& token,
const std::string& secret_key) {
try {
auto decoded = jwt::decode(token);
// Проверяем подпись
auto verifier = jwt::verify()
.allow_algorithm(jwt::algorithm::hs256{secret_key})
.with_issuer("auth.example.com");
verifier.verify(decoded);
// Проверяем срок действия
auto exp = decoded.get_expires_at();
auto now = std::chrono::system_clock::now();
if (now >= exp) {
return false; // Токен истек
}
return true;
} catch (const std::exception& e) {
std::cerr << "JWT verification failed: " << e.what() << std::endl;
return false;
}
}
Интеграция OAuth 2.0 и JWT
Типичный сценарий использования OAuth 2.0 с JWT выглядит следующим образом:
- Клиент запрашивает access token через OAuth 2.0 flow
- Authorization Server возвращает JWT в качестве access token
- Клиент использует JWT для доступа к защищенным ресурсам
- Resource Server верифицирует JWT без обращения к Authorization Server
Создание middleware для проверки JWT на C++
Рассмотрим пример middleware для HTTP-сервера на C++ с использованием библиотеки cpp-httplib:
#include <httplib.h>
#include <jwt-cpp/jwt.h>
class AuthMiddleware {
private:
std::string secret_key_;
public:
AuthMiddleware(const std::string& secret_key)
: secret_key_(secret_key) {}
bool authenticate(const httplib::Request& req,
httplib::Response& res) {
// Извлекаем токен из заголовка Authorization
auto auth_header = req.get_header_value("Authorization");
if (auth_header.empty() ||
auth_header.substr(0, 7) != "Bearer ") {
res.status = 401;
res.set_content("Unauthorized", "text/plain");
return false;
}
std::string token = auth_header.substr(7);
// Верифицируем ток