OAuth 2.0 и JWT авторизация на C++: пошаговое руководство для начинающих

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

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

Начать курс

Введение в OAuth 2.0 и JWT на C++

Современные веб-приложения и API редко обходятся без систем авторизации. Два самых популярных стандарта — OAuth 2.0 и JWT (JSON Web Token) — стали основой безопасности для миллионов сервисов. В этой статье мы разберём, как реализовать базовую OAuth 2.0 авторизацию с JWT токенами на языке C++. Вы узнаете, как работают эти протоколы, и увидите готовые примеры кода, которые можно адаптировать под свой проект.

Статья ориентирована на начинающих разработчиков, которые уже знакомы с основами C++ (классы, функции, работа с сетью) и хотят добавить в свои приложения безопасную авторизацию. Мы не будем использовать сторонние библиотеки для HTTP-сервера — все примеры будут на чистом C++ с минимальными зависимостями.

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

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

Основные роли в OAuth 2.0:

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

На C++ мы реализуем упрощённую версию Authorization Server и Resource Server, используя JWT в качестве токена доступа.

JWT: структура и принцип работы

JWT (JSON Web Token) — это компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Токен состоит из трёх частей, разделённых точками:

header.payload.signature

Header содержит тип токена и алгоритм подписи (обычно HMAC SHA256 или RSA). Payload — это полезная нагрузка: идентификатор пользователя, время жизни токена, роли и т.д. Signature — подпись, которая проверяет целостность данных.

Пример создания JWT на C++ без библиотек (упрощённо):

#include <iostream>
#include <sstream>
#include <vector>
#include <openssl/sha.h>
#include <openssl/hmac.h>

std::string base64_encode(const std::string &input) {
    // Упрощённая реализация Base64 (для примера)
    static const char* lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    std::string result;
    // ... код кодирования ...
    return result;
}

std::string create_jwt(const std::string &payload, const std::string &secret) {
    std::string header = R"({"alg":"HS256","typ":"JWT"})";
    std::string header_b64 = base64_encode(header);
    std::string payload_b64 = base64_encode(payload);
    std::string data = header_b64 + "." + payload_b64;
    
    unsigned char* sig = HMAC(EVP_sha256(), secret.c_str(), secret.length(), 
                              (unsigned char*)data.c_str(), data.length(), NULL, NULL);
    std::string sig_b64 = base64_encode(std::string((char*)sig, 32));
    
    return data + "." + sig_b64;
}

int main() {
    std::string payload = R"({"user_id":123,"role":"admin","exp":1700000000})";
    std::string token = create_jwt(payload, "my_secret_key");
    std::cout << "JWT: " << token << std::endl;
    return 0;
}

Этот код создаёт JWT с заголовком HS256 и полезной нагрузкой. В реальных проектах используйте проверенные библиотеки, такие как jwt-cpp или libjwt, но для понимания сути подойдёт и такой пример.

Реализация OAuth 2.0 сервера на C++

Теперь объединим OAuth 2.0 и JWT. Наш сервер будет:

  • Принимать запросы на авторизацию (логин/пароль).
  • Выдавать JWT токен доступа.
  • Проверять токен при обращении к защищённым ресурсам.

Шаг 1: Базовая структура HTTP-сервера

Для простоты используем сокеты POSIX. Создадим класс OAuthServer:

#include <string>
#include <map>
#include <functional>
#include <netinet/in.h>

class OAuthServer {
public:
    OAuthServer(int port) : port_(port) {}
    
    void start() {
        // Создание сокета, привязка, прослушивание
        int server_fd = socket(AF_INET, SOCK_STREAM, 0);
        sockaddr_in address;
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(port_);
        bind(server_fd, (struct sockaddr*)&address, sizeof(address));
        listen(server_fd, 3);
        
        while (true) {
            int client_fd = accept(server_fd, nullptr, nullptr);
            handle_request(client_fd);
            close(client_fd);
        }
    }
    
private:
    int port_;
    std::map<std::string, std::string> users_; // user_id -> password hash
    
    void handle_request(int client_fd) {
        // Парсинг HTTP запроса, маршрутизация
        // Если путь /oauth/token -> process_login()
        // Если путь /api/resource -> verify_token()
    }
};

Шаг 2: Обработка логина и выдача JWT

Когда пользователь отправляет POST-запрос с логином и паролем, сервер проверяет учётные данные и возвращает JWT:

std::string process_login(const std::string &username, const std::string &password) {
    // Проверка пароля (в реальности — хеширование)
    if (users_.find(username) == users_.end() || users_[username] != password) {
        return "HTTP/1.1 401                

Блоги

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