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

Аутентификация

Аутентификация — проверка, что пользователь или система является тем, за кого себя выдаёт (ответ на вопрос «кто ты?»). Отличие от авторизации (что тебе можно). Факторы: знание (пароль), владение (телефон, ключ), присуждение (отпечаток). Способы аутентификации в API: Basic Auth (логин+пароль в Base64, только с HTTPS), API Key (простой ключ), Bearer Token / JWT (самодостаточный токен, stateless, exp), OAuth 2.0 (авторизация без пароля, разрешения через scopes), OpenID Connect (аутентификация поверх OAuth 2.0, ID Token), Mutual TLS (двухсторонние сертификаты). Хранение токенов на клиенте: localStorage (XSS), HttpOnly cookie (CSRF). Session-based vs JWT. Типичные ошибки: хранение паролей в открытом виде, JWT без exp, Basic Auth без HTTPS.

Введение: Кто вы такой?

Представьте, что вы подходите к двери секретного клуба. Швейцар задаёт вопрос: “Кто вы?” Это идентификация. Вы предъявляете паспорт. Швейцар проверяет: “Паспорт настоящий? Фотография похожа?” Это аутентификация.

Аутентификация (Authentication) — это процесс проверки, что пользователь (или система) является тем, за кого себя выдаёт. Это ответ на вопрос “Кто ты?”.

Аутентификация — это первый шаг безопасности. Без неё вы не знаете, с кем имеете дело. Может быть, это легальный пользователь. А может, злоумышленник, который украл пароль или перехватил токен.

В мире API аутентификация решает проблему: “Как серверу убедиться, что запрос пришёл от того, за кого себя выдаёт клиент?”. Способы бывают разными: от простого API ключа до сложных протоколов вроде OAuth 2.0 и JWT.

Важно не путать аутентификацию с авторизацией. Аутентификация — “кто ты”. Авторизация — “что тебе можно”. Сначала нужно узнать личность, потом уже проверять права.

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

ТерминВопросЧто проверяетПример
Идентификация“Кто ты?”Утверждение личности“Я Иван”
Аутентификация“Точно ли ты тот, за кого себя выдаёшь?”ДоказательствоПредъявил паспорт, знает пароль
Авторизация“Что тебе можно?”Права доступа“Иван может читать, но не может удалять”

Пример:

  1. Идентификация: Пользователь вводит логин “ivan”.
  2. Аутентификация: Пользователь вводит пароль. Сервер проверяет, что пароль правильный.
  3. Авторизация: Сервер проверяет, что у “ivan” есть право выполнить операцию (например, читать профиль).

Факторы аутентификации

Факторы — это “категории” доказательств. Чем больше факторов, тем безопаснее.

ФакторТипПример
1. Знание (Something you know)Пароль, PIN-код, ответ на секретный вопрос
2. Владение (Something you have)Телефон (SMS, TOTP), ключ безопасности (YubiKey), смарт-карта
3. Присуждение (Something you are)Отпечаток пальца, Face ID, голос, радужка глаза

Уровни безопасности:

ТипФакторыПримерБезопасность
Однофакторная (1FA)1 (обычно пароль)Вход по паролюНизкая
Двухфакторная (2FA)2 (пароль + код из SMS)Банк, почтаСредняя
Многофакторная (MFA)2+Пароль + отпечаток + ключВысокая

Способы аутентификации в API

СпособТипСложностьБезопасностьГде используется
Basic Auth1FA (пароль)НизкаяНизкая (без HTTPS)Устаревшие системы
API Key1FA (ключ)НизкаяСредняяПубличные API
Bearer Token (JWT)1FA (токен)СредняяВысокаяСовременные API
OAuth 2.01-2FAВысокаяВысокаяСоцсети, Google, GitHub
OpenID Connect (OIDC)1-2FAВысокаяВысокаяSingle Sign-On (SSO)
Client Certificates (mTLS)2FA (владение)ВысокаяОчень высокаяБанки, B2B, микросервисы

Basic Authentication

Как работает

Клиент отправляет логин и пароль в заголовке Authorization. Данные кодируются в Base64.

GET /users/123
Authorization: Basic aXZhbjpzZWNyZXQ=

aXZhbjpzZWNyZXQ= — это Base64 от “ivan:secret”.

Пример

// JavaScript (браузер)
fetch('https://api.example.com/users/123', {
    headers: {
        'Authorization': 'Basic ' + btoa('ivan:secret')
    }
});

Безопасность

ПроблемаРискРешение
Base64 не шифрованиеЛюбой может декодироватьВсегда использовать HTTPS
Пароль в каждом запросеПерехват, логированиеНе использовать Basic Auth в продакшене
Нет сессииНельзя “выйти” (кроме смены пароля)Использовать токены

Когда использовать

  • Простые внутренние API
  • Тестирование и отладка
  • Интеграции, где пароль меняется редко

Никогда не используйте Basic Auth без HTTPS!

API Key

Как работает

Сервер генерирует уникальный ключ для каждого клиента. Клиент отправляет ключ в каждом запросе (в заголовке, параметре или cookie).

GET /users/123
X-API-Key: abc123xyz456
GET /users/123?api_key=abc123xyz456

Пример

fetch('https://api.example.com/users/123', {
    headers: {
        'X-API-Key': 'abc123xyz456'
    }
});

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

ПреимуществоОбъяснение
ПростотаЛегко реализовать и использовать
Отзыв ключейМожно заблокировать ключ без смены пароля
Разные ключи для разных клиентовМожно ограничивать по IP, эндпоинтам
АналитикаМожно отслеживать, какой ключ сколько запросов делает

Недостатки

НедостатокОбъяснение
Один ключ — всёКлюч даёт доступ ко всем данным (нет гранулярности)
Утечка ключаНужно менять ключ, нельзя быстро отозвать (если нет механизма)
Нет сессииКлюч всегда действителен (нет истечения)

Когда использовать

  • Публичные API для разработчиков (например, погода, курсы валют)
  • Сервис-ту-сервис (S2S) интеграции
  • Внутренние системы с низкими требованиями к безопасности

Bearer Token (JWT)

Что такое JWT

JWT (JSON Web Token) — это компактный, самодостаточный токен в формате JSON. Он содержит информацию о пользователе и его правах.

Структура JWT: header.payload.signature

// Header (тип токена, алгоритм подписи)
{
    "alg": "HS256",
    "typ": "JWT"
}

// Payload (claims — утверждения о пользователе)
{
    "sub": "1234567890",
    "name": "Иван Петров",
    "iat": 1516239022,
    "exp": 1516242622
}

// Signature (подпись, чтобы токен нельзя было подделать)
HMACSHA256(
    base64UrlEncode(header) + "." + base64UrlEncode(payload),
    secret
)

Пример JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IuCQmNCy0LDQvSDRg9C00LXRgCIsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE2MjQyNjIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Как работает

  1. Аутентификация: Клиент отправляет логин и пароль на /auth/login.
  2. Выдача токена: Сервер проверяет, генерирует JWT и возвращает его клиенту.
  3. Использование токена: Клиент отправляет JWT в заголовке Authorization: Bearer <token>.
  4. Проверка токена: Сервер проверяет подпись и срок действия.
POST /auth/login
{"username": "ivan", "password": "secret"}
HTTP/1.1 200 OK
{"token": "eyJhbGciOiJIUzI1NiIs..."}
GET /users/123
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

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

ПреимуществоОбъяснение
StatelessСерверу не нужно хранить сессии. Токен самодостаточен
МасштабируемостьЛюбой сервер может проверить токен (нет единой точки хранения сессий)
Содержит информациюИмя, роль, права — в самом токене (не нужно лезть в БД)
Срок действия (exp)Токен автоматически истекает
МеждоменныйРаботает с CORS

Недостатки JWT

НедостатокОбъяснение
Нельзя отозватьТокен действителен до истечения (нужен blacklist)
РазмерБольше, чем session ID (может быть несколько КБ)
Хранение на клиентеlocalStorage (XSS), cookies (CSRF) — нужно продумать

Когда использовать

  • Микросервисные архитектуры (stateless, масштабирование)
  • SPA (Single Page Applications)
  • Мобильные приложения
  • API, где важна масштабируемость

OAuth 2.0

Что это

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

Ключевая идея: Вы не даёте свой пароль приложению. Вы даёте разрешение, а сервер выдаёт приложению временный токен.

Участники OAuth 2.0

УчастникРольПример
Resource OwnerВладелец данныхВы (пользователь)
ClientПриложение, которое хочет доступМобильное приложение
Authorization ServerСервер, выдающий токеныGoogle Auth
Resource ServerСервер, хранящий данныеGoogle Drive

Схема работы

    sequenceDiagram
    participant User as Пользователь
    participant Client as Клиент
    participant Auth as Auth Server
    participant Resource as Resource Server
    
    User->>Client: 1. Нажми "Войти через Google"
    Client->>Auth: 2. Перенаправление на Google
    Auth->>User: 3. Запрос разрешения
    User->>Auth: 4. Разрешить доступ
    Auth->>Client: 5. Authorization Code
    Client->>Auth: 6. Code + Client Secret → Access Token
    Auth-->>Client: 7. Access Token
    Client->>Resource: 8. Access Token → Запрос данных
    Resource-->>Client: 9. Данные пользователя
  

Типы грантов (flows)

Grant TypeОписаниеКогда использовать
Authorization CodeКод + секретВеб-приложения с сервером
ImplicitТокен напрямую (устарел)SPA (раньше)
Resource Owner PasswordЛогин + парольДоверенные приложения
Client CredentialsТолько клиент (без пользователя)Сервис-ту-сервис
Device CodeУстройства без браузераТелевизоры, принтеры

OAuth 2.0 Scopes

Scopes — это разрешения, которые запрашивает приложение.

ScopeЧто даёт
profileИмя, фото, пол
emailАдрес электронной почты
openidИдентификация (для OIDC)
https://www.googleapis.com/auth/drive.readonlyЧтение Google Drive

Преимущества OAuth 2.0

ПреимуществоОбъяснение
Нет пароляПриложение не получает пароль пользователя
Ограниченный доступТолько те scope, которые разрешил пользователь
ОтзывМожно отозвать доступ в любой момент
Временные токеныТокены имеют срок действия

Недостатки OAuth 2.0

НедостатокОбъяснение
СложностьМного типов грантов, много участников
Стандарт не полныйНет встроенной аутентификации (только авторизация)
БезопасностьЛегко ошибиться (например, использовать Implicit flow)

Когда использовать

  • Вход через Google, Facebook, GitHub, Yandex
  • Доступ к API от имени пользователя (Google Drive, Dropbox)
  • B2B интеграции

OpenID Connect (OIDC)

Что это

OpenID Connect (OIDC) — это слой поверх OAuth 2.0, добавляющий аутентификацию. OAuth 2.0 даёт авторизацию (доступ к API). OIDC даёт аутентификацию (подтверждение личности).

Ключевое отличие:

  • OAuth 2.0: “Приложение может читать ваш профиль”
  • OIDC: “Вы точно Иван”

ID Token

В OIDC добавляется ID Token (JWT), который содержит информацию о пользователе.

{
    "iss": "https://accounts.google.com",
    "sub": "1234567890",
    "aud": "myapp123",
    "exp": 1516242622,
    "iat": 1516239022,
    "name": "Иван Петров",
    "email": "ivan@gmail.com",
    "email_verified": true
}

Когда использовать

  • Single Sign-On (SSO) — один вход во все сервисы
  • Вход через соцсети
  • Корпоративные системы (Active Directory, Keycloak, Auth0)

Mutual TLS (mTLS)

Что это

mTLS (Mutual TLS) — это двухсторонняя аутентификация через сертификаты. В обычном TLS клиент проверяет сервер. В mTLS сервер тоже проверяет клиента.

    sequenceDiagram
    participant Client
    participant Server
    
    Client->>Server: Привет, я клиент
    Server-->>Client: Привет, я сервер (мой сертификат)
    Client->>Server: Доверяю. Вот мой сертификат
    Server-->>Client: Доверяю. Соединение установлено.
  

Как работает

  1. Клиент предъявляет сертификат, подписанный доверенным центром (CA)
  2. Сервер проверяет подпись, срок действия, отзыв сертификата
  3. Если всё хорошо — соединение устанавливается

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

ПреимуществоОбъяснение
Очень высокая безопасностьСертификат сложнее украсть, чем пароль
Машинная аутентификацияНе требует участия человека
Встроено в TLSНе нужно дополнительных токенов

Недостатки

НедостатокОбъяснение
Сложность управленияНужно выпускать, обновлять, отзывать сертификаты
Инфраструктура (PKI)Нужен свой центр сертификации
ПроизводительностьTLS handshake тяжелее

Когда использовать

  • Банковские API
  • B2B интеграции (высокая безопасность)
  • Микросервисы внутри кластера (например, Istio, Linkerd)
  • IoT (устройства с сертификатами)

Session-based Authentication (сравнение)

В отличие от токенов, сессии хранятся на сервере.

    sequenceDiagram
    participant Client
    participant Server
    participant SessionStore as Session Store (Redis)
    
    Client->>Server: POST /login (пароль)
    Server->>SessionStore: Создать сессию (session_id)
    SessionStore-->>Server: session_id
    Server-->>Client: Set-Cookie: session_id=abc123
    
    Client->>Server: GET /profile (Cookie: session_id)
    Server->>SessionStore: Проверить session_id
    SessionStore-->>Server: user_id=123
    Server-->>Client: Данные профиля
  
ХарактеристикаSessionJWT
Хранение на сервереДаНет (stateless)
МасштабированиеНужен общий Session Store (Redis)Легко (stateless)
ОтзывЛегко (удалить сессию)Сложно (blacklist)
РазмерМаленький (session_id)Большой (JWT)
CSRFНужна защитаНет (если не cookie)
XSSHttpOnly cookie защищаетЗависит от хранения

Где хранить токены на клиенте

СпособЗащита от XSSЗащита от CSRFПодходит для
localStorageНет (JavaScript читает)НетSPA (осторожно)
sessionStorageНетНетВременные данные
Cookie (HttpOnly)ДаНет (нужен CSRF токен)Классические веб-приложения
Cookie (HttpOnly + SameSite=Strict)ДаДаЛучший вариант для веба
В памяти (JS переменная)Да (не хранится)НетМобильные приложения

Рекомендация для веб-приложений: HttpOnly + SameSite=Strict + Secure + CSRF токен.

Распространённые ошибки

Ошибка 1: Хранение паролей в открытом виде

# Плохо
users = [{"username": "ivan", "password": "secret"}]

# Хорошо (хеширование)
import bcrypt
hashed = bcrypt.hashpw(b"secret", bcrypt.gensalt())

Ошибка 2: JWT без срока действия (exp)

// Плохо
{
    "sub": "123",
    "name": "Иван"
}

// Хорошо
{
    "sub": "123",
    "name": "Иван",
    "exp": 1516242622,
    "iat": 1516239022
}

Ошибка 3: Basic Auth без HTTPS

GET /users/123
Authorization: Basic aXZhbjpzZWNyZXQ=

Пароль передаётся открыто (Base64 — не шифрование).

Исправление: Всегда HTTPS.

Ошибка 4: JWT с секретным ключом “secret”

# Плохо
jwt.encode(payload, "secret", algorithm="HS256")

# Хорошо
import os
secret = os.environ.get("JWT_SECRET")

Ошибка 5: Хранение токена в localStorage без защиты

// Плохо (XSS уязвимо)
localStorage.setItem('token', token);

// Лучше (HttpOnly cookie)
document.cookie = `token=${token}; HttpOnly; Secure; SameSite=Strict`;

Резюме для системного аналитика

  1. Аутентификация — проверка, что пользователь тот, за кого себя выдаёт. Отвечает на вопрос “Кто ты?”.

  2. Факторы аутентификации: знание (пароль), владение (телефон), присуждение (отпечаток). Чем больше факторов, тем безопаснее.

  3. Способы аутентификации в API:

    • Basic Auth: пароль в каждом запросе. Только с HTTPS, лучше не использовать.
    • API Key: простой ключ. Для публичных API, S2S.
    • Bearer Token (JWT): самодостаточный токен. Для микросервисов, SPA, мобильных приложений.
    • OAuth 2.0: авторизация без пароля. Для входа через соцсети, доступа к API от имени пользователя.
    • OpenID Connect (OIDC): аутентификация поверх OAuth 2.0. Для SSO, корпоративных систем.
    • mTLS: двухсторонняя аутентификация через сертификаты. Для B2B, банков, микросервисов.
  4. JWT: stateless, масштабируемый, но нельзя отозвать до истечения. Хранить секрет надёжно, использовать короткое время жизни (exp), не хранить чувствительные данные в payload.

  5. OAuth 2.0: сложный, но мощный. Не используйте Implicit flow. Authorization code + PKCS для SPA.

Проверка знаний

Вопрос 1 из 4
На какой вопрос отвечает аутентификация?
Почему Basic Auth без HTTPS считается небезопасным?
Что лучше всего описывает JWT?
Где mTLS особенно уместен?

Вопросы, где были ошибки