Перейти к основному содержимому

7.07. Авторизация и аутентификация

Разработчику Инженеру

Авторизация и аутентификация

В современных информационных системах управление доступом — неотъемлемый элемент архитектуры. Независимо от того, разрабатывается ли веб-приложение, мобильное приложение, корпоративная ERP-система или облачный микросервис, важно строго определять, кто пытается получить доступ к системе (аутентификация) и что ему разрешено делать (авторизация). Эти два процесса, хотя и тесно связаны, решают принципиально разные задачи и реализуются различными подходами, механизмами и протоколами.

Конфузия между аутентификацией и авторизацией — одна из самых распространённых ошибок даже среди опытных разработчиков. Такая путаница ведёт к уязвимостям в системах безопасности, некорректному управлению правами и, как следствие, к серьёзным инцидентам: утечкам данных, несанкционированному доступу, повреждению инфраструктуры.

Данная глава призвана систематизировать знания об этих двух ключевых механизмах, детализировать их внутреннее устройство, рассмотреть архитектурные паттерны, распространённые протоколы и готовые решения, а также дать практические рекомендации по их корректной реализации в различных типах приложений.


1. Аутентификация: «Кто ты?»

Аутентификация — это процесс подтверждения личности пользователя или субъекта, пытающегося получить доступ к системе. Этот этап всегда предшествует авторизации и отвечает на вопрос: «Кто ты?».

В основе аутентификации лежит проверка одного или нескольких факторов подлинности:

  • Что-то, что вы знаете (например, пароль, PIN-код);
  • Что-то, что у вас есть (например, аппаратный токен, смартфон с приложением Google Authenticator);
  • Что-то, что вы являетесь (биометрические данные: отпечаток пальца, лицо, голос).

Сочетание двух и более факторов называется многофакторной аутентификацией (MFA). Она значительно повышает уровень безопасности, поскольку компрометация одного фактора (например, утечка пароля) не приводит к полному доступу злоумышленника.

Виды аутентификации

  1. Парольная аутентификация
    Наиболее распространённый, но наименее защищённый метод. Основан на проверке пары логин/пароль. Без дополнительных мер (хэширование с солью, ограничение попыток, MFA) уязвима к брутфорсу, фишингу и утечкам баз данных.

  2. Базовая аутентификация (Basic Authentication)
    Реализуется передачей логина и пароля в заголовке HTTP-запроса в закодированном виде (Base64). Не рекомендуется в чистом виде без шифрования TLS, так как данные легко декодируются. Используется в тестовых средах или внутренних API с ограничениями трафика.

  3. Биометрическая аутентификация
    Основана на уникальных физиологических или поведенческих характеристиках. Требует надёжного хранения шаблонов и защиты от подмены (например, фото вместо лица). Применяется в мобильных устройствах, системах физического доступа.

  4. Сертификатная аутентификация
    Использует X.509-сертификаты для подтверждения подлинности клиента. Применяется в корпоративных и высоконадёжных системах, где требуется строгая идентификация без участия пользователя.

  5. Токен-ориентированная аутентификация
    Использует криптографически подписанные токены (например, JWT) для передачи идентификатора пользователя и его атрибутов. Подробно рассматривается в разделе о JWT.

  6. Протокольная аутентификация
    Включает такие стандарты, как:

    • OAuth 2.0: в первую очередь предназначен для делегирования доступа, но часто используется и для аутентификации (через OpenID Connect).
    • OpenID Connect (OIDC): надстройка над OAuth 2.0, специально созданная для аутентификации. Позволяет использовать внешние провайдеры (Google, Microsoft и др.).
    • SAML (Security Assertion Markup Language): XML-стандарт для единого входа (SSO), широко применяемый в корпоративных средах.
    • Kerberos / NTLM: протоколы, используемые в Windows-доменах для аутентификации в закрытых сетях.

Готовые решения

Для сокращения времени разработки и повышения уровня безопасности рекомендуется использовать проверенные платформы:

  • Auth0 — облачный Identity-as-a-Service (IDaaS) с поддержкой множества протоколов.
  • Firebase Authentication — простая интеграция для веб- и мобильных приложений с поддержкой социальных провайдеров.
  • Keycloak — open-source решение с поддержкой OAuth 2.0, OIDC, SAML, ролевой модели и расширенной настройки.
  • Azure Active Directory (Entra ID) — корпоративное решение Microsoft, интегрируемое с Office 365, Windows и Azure-сервисами.
  • Okta — коммерческая платформа с мощным UI, жизненным циклом пользователей и MFA.

2. Авторизация: «Что тебе разрешено?»

Если аутентификация отвечает на вопрос «Кто ты?», то авторизация отвечает на «Что тебе разрешено?». Это процесс проверки прав доступа субъекта (пользователя, сервиса, устройства) к объекту (файлу, API-эндпоинту, функции).

Авторизация выполняется после успешной аутентификации. Без подтверждённой личности проверка прав не имеет смысла.

Модели управления доступом

Существует несколько ключевых моделей авторизации, каждая из которых подходит для определённого класса систем:

  1. RBAC (Role-Based Access Control)
    Доступ определяется через роли. Пользователь назначается одной или несколькими ролями, а каждой роли присваивается набор разрешений (permissions).
    Пример: Роль admin может удалять пользователей, роль user — только просматривать профиль.

  2. ABAC (Attribute-Based Access Control)
    Доступ определяется на основе атрибутов: пользователя (отдел, должность), ресурса (категория, владелец), среды (время суток, геолокация, IP-адрес).
    Пример: Пользователь из отдела «Финансы» имеет доступ к документу «Бюджет», если время запроса — в рабочие часы и IP принадлежит корпоративной сети.

  3. PBAC (Policy-Based Access Control)
    Более обобщённый подход, где доступ управляется политиками — логическими правилами, которые могут включать условия из ABAC, временные ограничения, контекст устройства и т.п.
    Пример: «Доступ к административной панели разрешён только с доверенного устройства и только при включённой 2FA».

  4. ACL (Access Control List)
    Классический подход: у каждого ресурса есть список, где указано, какие субъекты имеют к нему доступ и с какими правами. Гибок, но трудно масштабируем при большом числе пользователей и ресурсов.

Механизмы авторизации

  • Списки разрешений (Permissions)
    Минимальная единица контроля доступа. Например: read:documents, write:users, delete:posts. Комбинируются в роли или политики.

  • Делегирование доступа
    Пользователь может временно передавать свои права другому субъекту (например, через OAuth). Это особенно важно в SaaS-системах и интеграциях.

  • Сессии и токены
    После аутентификации система должна каким-то образом помнить, что пользователь уже прошёл проверку. Это реализуется через:

    • Сессии (сервер хранит состояние в памяти или БД, клиент получает session ID в cookie);
    • Токены (клиент хранит состояние, сервер проверяет подпись и содержимое токена — stateless подход).

3. JSON Web Tokens (JWT): архитектура и применение

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

Структура JWT

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

  1. Header — метаданные токена. Содержит тип токена ("typ": "JWT") и алгоритм подписи ("alg"). Пример:

    {
    "alg": "HS256",
    "typ": "JWT"
    }
  2. Payload — тело токена. Содержит утверждения (claims). Существуют три типа claims:

    • Зарезервированные (iss, exp, sub, aud и др.) — стандартизированы, но не обязательны.
    • Публичные — согласованные между сторонами (например, role, department).
    • Приватные — специфичные для приложения (например, user_id, is_premium).

    Пример payload:

    {
    "sub": "1234567890",
    "name": "Тимур Тагиров",
    "role": "admin",
    "exp": 1730000000
    }
  3. Signature — криптографическая подпись, гарантирующая целостность токена. Формируется путём:

    • Кодирования header и payload в Base64Url;
    • Конкатенации их через точку;
    • Подписи полученной строки с использованием секретного ключа (HMAC) или закрытого ключа (RSA/ECDSA).

    Пример подписи (для HMAC):

    HMACSHA256(
    base64UrlEncode(header) + "." + base64UrlEncode(payload),
    secret
    )

Результирующий токен выглядит так:
xxxxx.yyyyy.zzzzz

Применение JWT

  1. Аутентификация
    После успешного входа пользователь получает JWT. При последующих запросах он передаёт токен (обычно в заголовке Authorization: Bearer <token>). Сервер проверяет подпись и срок действия, после чего считает запрос аутентифицированным.

  2. Авторизация
    Роли и разрешения кодируются в payload. Например, наличие "role": "admin" позволяет контроллеру разрешить доступ к защищённому эндпоинту.

  3. Единый вход (SSO)
    JWT может использоваться как токен обмена между сервисами в рамках единой экосистемы. Например, сервис аутентификации генерирует токен, который принимают все микросервисы.

Ограничения и риски

  • JWT не отменяется
    Поскольку JWT stateless, его нельзя инвалидировать до истечения срока действия (exp). Решения:

    • Использовать короткий срок жизни (например, 15 минут) и пару access/refresh tokens;
    • Вести чёрный список недействительных токенов (например, в Redis).
  • Хранение на клиенте
    Хранение JWT в localStorage подвержено атакам XSS; в HttpOnly cookie — атакам CSRF. Оптимальный выбор зависит от архитектуры и уровня угроз.

  • Подделка токена
    Если сервер использует слабый или утечку секретного ключа, злоумышленник может сгенерировать валидный JWT. Требуется тщательное управление ключами.


4. Валидация входных данных и управление доверием

Аутентификация и авторизация не защищены, если входные данные не проходят строгую валидацию. Уязвимости типа insecure direct object reference (IDOR) или injection часто возникают из-за отсутствия проверки входных параметров.

Белый и чёрный списки

  • Белый список (allowlist) — явное разрешение только известных, ожидаемых значений.
    Пример: разрешить выбор роли только из ["user", "moderator", "admin"].

  • Чёрный список (blocklist) — попытка запретить опасные значения. Не рекомендуется, так как невозможно перечислить все возможные векторы атаки.

Белый список — единственный надёжный подход в критичных местах (ролях, путях файлов, идентификаторах).

Библиотеки валидации

Для обеспечения типобезопасности и валидации структуры данных используются специализированные библиотеки:

  • Python: Marshmallow — декларативная валидация и сериализация объектов.
  • Node.js: Joi (ныне @hapi/joi) или Zod — строгая схема валидации с поддержкой кастомных правил.
  • C#: встроенные механизмы Data Annotations ([Required], [StringLength]) и библиотеки вроде FluentValidation.
  • Java: Bean Validation (@NotNull, @Pattern) + Hibernate Validator.

Пример на Python (Marshmallow):

from marshmallow import Schema, fields

class LoginSchema(Schema):
username = fields.Str(required=True, validate=validate.Length(min=3, max=32))
password = fields.Str(required=True, validate=validate.Length(min=8))

Такой подход предотвращает передачу неожиданных или вредоносных данных на уровень аутентификации.


5. Управление сессиями и stateful-подход

Хотя JWT популярен, сессионная аутентификация остаётся актуальной, особенно в монолитных веб-приложениях.

Как работает сессия

  1. Пользователь отправляет логин и пароль.
  2. Сервер проверяет учётные данные.
  3. При успехе создаётся объект сессии на сервере (в памяти, Redis, БД).
  4. Клиенту возвращается session ID (обычно в Set-Cookie).
  5. При последующих запросах браузер автоматически отправляет cookie с session ID.
  6. Сервер находит сессию по ID и проверяет её валидность.

Преимущества сессий

  • Возможность мгновенной отмены (удаление из хранилища).
  • Отсутствие передачи чувствительных данных клиенту.
  • Встроенная защита от XSS при использовании HttpOnly cookie.

Недостатки

  • Требует stateful-архитектуры (сложнее масштабировать).
  • Неудобно в мобильных и SPA-приложениях без дополнительной обвязки.

6. Готовые фреймворки: Identity, Keycloak, Auth0

ASP.NET Core Identity

Встроенная система управления пользователями в .NET. Включает:

  • CRUD-операции над пользователями и ролями.
  • Хранение в таблицах: AspNetUsers, AspNetRoles, AspNetUserRoles.
  • Поддержку внешних провайдеров (Google, Facebook).
  • Встроенную двухфакторную аутентификацию (2FA) через TOTP или SMS.

Пример включения 2FA:

// Включение 2FA
await _userManager.SetTwoFactorEnabledAsync(user, true);

// Генерация секретного ключа для Google Authenticator
var key = await _userManager.GetAuthenticatorKeyAsync(user);
if (string.IsNullOrEmpty(key))
{
await _userManager.ResetAuthenticatorKeyAsync(user);
key = await _userManager.GetAuthenticatorKeyAsync(user);
}

Проверка TOTP-кода:

var isValid = await _userManager.VerifyTwoFactorTokenAsync(
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, code);

Keycloak

Open-source Identity и Access Management (IAM) сервер. Поддерживает:

  • OAuth 2.0, OpenID Connect, SAML.
  • RBAC, fine-grained permissions.
  • Адаптеры для Java, JavaScript, .NET, Python.
  • UI для управления пользователями и ролями.

Auth0 и Okta

Облачные решения с минимальной настройкой. Подходят для стартапов и SaaS-продуктов. Предоставляют:

  • Готовые экраны входа/регистрации.
  • Аналитику аутентификации.
  • Поддержку социальных провайдеров.
  • Управление MFA, блокировку брутфорса, anomaly detection.

7. Единый вход (Single Sign-On, SSO)

Single Sign-On (SSO) — архитектурный паттерн, позволяющий пользователю аутентифицироваться один раз и получить доступ к множеству взаимодействующих систем без повторного ввода учётных данных.

Принцип работы

  1. Пользователь пытается получить доступ к приложению A.
  2. Приложение A перенаправляет его на Identity Provider (IdP).
  3. Если пользователь не аутентифицирован в IdP — ему предлагается войти.
  4. После успешной аутентификации IdP генерирует утверждение (assertion) и перенаправляет пользователя обратно в приложение A с этим утверждением.
  5. Приложение A проверяет подлинность утверждения и создаёт локальную сессию.

Стандарты SSO

  • SAML (Security Assertion Markup Language)
    XML-ориентированный стандарт, доминирующий в корпоративном секторе (особенно в интеграциях с Microsoft, SAP, Salesforce). Обеспечивает надёжную передачу атрибутов и поддержку федеративной идентификации.

  • OpenID Connect (OIDC)
    Современный, JSON/REST-ориентированный стандарт на базе OAuth 2.0. Широко используется в облачных и веб-приложениях. Проще в реализации, чем SAML, и лучше подходит для SPA и мобильных клиентов.

  • OAuth 2.0 как основа
    Хотя OAuth 2.0 изначально не предназначен для аутентификации, в связке с OIDC он становится полноценным SSO-решением. Провайдеры (Google, Microsoft, GitHub) предоставляют OIDC-эндпоинты (/.well-known/openid-configuration).

Преимущества SSO

  • Улучшение UX: пользователь входит один раз.
  • Централизованный контроль: администратор управляет доступом в одном месте.
  • Снижение рисков: меньше паролей → меньше утечек.
  • Упрощённый аудит и логирование.

Риски

  • Единая точка отказа: компрометация IdP даёт доступ ко всем системам.
  • Сложность отмены доступа: требуется своевременная синхронизация статуса учётной записи.

8. Интеграция аутентификации и авторизации в разные типы приложений

8.1. Веб-приложения

  • Традиционные (server-rendered)
    Используют сессионную аутентификацию с HttpOnly cookie. CSRF-токены обязательны. Авторизация реализуется через middleware (например, [Authorize] в ASP.NET, @login_required в Django).

  • SPA (React, Angular, Vue)
    Чаще используют токен-ориентированный подход (JWT). Токен хранится в памяти (не в localStorage) для защиты от XSS. Авторизация на фронтенде — декоративна; окончательная проверка всегда на бэкенде.

  • API-first архитектура
    Все эндпоинты защищаются через заголовок Authorization: Bearer <token>. Используются кастомные middleware или библиотеки (express-jwt, Flask-JWT-Extended, Microsoft.AspNetCore.Authentication.JwtBearer).

8.2. Десктопные приложения

  • Native-приложения (WPF, WinForms, Electron)
    Аутентификация часто реализуется через браузерную перенаправляющую модель (OAuth 2.0 Authorization Code + PKCE). Это безопаснее хранения логина/пароля в приложении.
    После получения токена он сохраняется в защищённом хранилище ОС: Windows Credential Vault, Keychain (macOS), libsecret (Linux).

  • Автономные системы
    В отсутствие сети может применяться локальная аутентификация (например, хэши паролей в зашифрованном файле), но с ограничениями: нет централизованного управления, нет SSO.

8.3. Мобильные приложения

  • OAuth 2.0 + PKCE — рекомендуемый стандарт (RFC 7636). Предотвращает перехват authorization code.
  • Biometric Unlock — после первоначального входа пользователь может разблокировать приложение отпечатком, но JWT/refresh token остаются в защищённом хранилище (Android Keystore, iOS Secure Enclave).
  • Refresh Tokens — критически важны из-за долгой сессии. Должны быть привязаны к устройству и иметь механизм отмены.

9. Практические рекомендации по проектированию системы доступа

  1. Разделяйте аутентификацию и авторизацию
    Не смешивайте проверку личности и проверку прав. Используйте отдельные компоненты (IdP и Policy Engine).

  2. Минимизируйте привилегии (Principle of Least Privilege)
    Пользователь должен получать только те права, которые необходимы для выполнения задачи.

  3. Никогда не храните пароли в открытом виде
    Используйте адаптивные хэш-функции: Argon2, scrypt, bcrypt. Не используйте MD5 или SHA1.

  4. Используйте HTTPS повсеместно
    Без TLS любой механизм аутентификации уязвим к перехвату.

  5. Внедряйте многофакторную аутентификацию (MFA)
    Особенно для администраторов и привилегированных учётных записей.

  6. Ведите аудит действий
    Логируйте входы, выходы, изменения прав, неудачные попытки входа. Это необходимо для расследования инцидентов.

  7. Избегайте самописных криптографических решений
    Используйте проверенные библиотеки и протоколы. «Security through obscurity» не работает.

  8. Тестируйте на уязвимости
    Регулярно проводите аудиты: проверяйте на IDOR, broken access control (OWASP Top 10), утечки токенов.