Аутентификация
Аутентификация — проверка, что пользователь или система является тем, за кого себя выдаёт (ответ на вопрос «кто ты?»). Отличие от авторизации (что тебе можно). Факторы: знание (пароль), владение (телефон, ключ), присуждение (отпечаток). Способы аутентификации в 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 Авторизация
| Термин | Вопрос | Что проверяет | Пример |
|---|---|---|---|
| Идентификация | “Кто ты?” | Утверждение личности | “Я Иван” |
| Аутентификация | “Точно ли ты тот, за кого себя выдаёшь?” | Доказательство | Предъявил паспорт, знает пароль |
| Авторизация | “Что тебе можно?” | Права доступа | “Иван может читать, но не может удалять” |
Пример:
- Идентификация: Пользователь вводит логин “ivan”.
- Аутентификация: Пользователь вводит пароль. Сервер проверяет, что пароль правильный.
- Авторизация: Сервер проверяет, что у “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 Auth | 1FA (пароль) | Низкая | Низкая (без HTTPS) | Устаревшие системы |
| API Key | 1FA (ключ) | Низкая | Средняя | Публичные API |
| Bearer Token (JWT) | 1FA (токен) | Средняя | Высокая | Современные API |
| OAuth 2.0 | 1-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: abc123xyz456GET /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
Как работает
- Аутентификация: Клиент отправляет логин и пароль на
/auth/login. - Выдача токена: Сервер проверяет, генерирует JWT и возвращает его клиенту.
- Использование токена: Клиент отправляет JWT в заголовке
Authorization: Bearer <token>. - Проверка токена: Сервер проверяет подпись и срок действия.
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: Доверяю. Соединение установлено.
Как работает
- Клиент предъявляет сертификат, подписанный доверенным центром (CA)
- Сервер проверяет подпись, срок действия, отзыв сертификата
- Если всё хорошо — соединение устанавливается
Преимущества
| Преимущество | Объяснение |
|---|---|
| Очень высокая безопасность | Сертификат сложнее украсть, чем пароль |
| Машинная аутентификация | Не требует участия человека |
| Встроено в 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: Данные профиля
| Характеристика | Session | JWT |
|---|---|---|
| Хранение на сервере | Да | Нет (stateless) |
| Масштабирование | Нужен общий Session Store (Redis) | Легко (stateless) |
| Отзыв | Легко (удалить сессию) | Сложно (blacklist) |
| Размер | Маленький (session_id) | Большой (JWT) |
| CSRF | Нужна защита | Нет (если не cookie) |
| XSS | HttpOnly 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`;Резюме для системного аналитика
Аутентификация — проверка, что пользователь тот, за кого себя выдаёт. Отвечает на вопрос “Кто ты?”.
Факторы аутентификации: знание (пароль), владение (телефон), присуждение (отпечаток). Чем больше факторов, тем безопаснее.
Способы аутентификации в 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, банков, микросервисов.
JWT: stateless, масштабируемый, но нельзя отозвать до истечения. Хранить секрет надёжно, использовать короткое время жизни (exp), не хранить чувствительные данные в payload.
OAuth 2.0: сложный, но мощный. Не используйте Implicit flow. Authorization code + PKCS для SPA.