Экспресс-курс · No. 08
За одним словом «auth» прячутся два разных вопроса. Аутентификация подтверждает, кто ты; авторизация решает, что тебе можно. Спутай их, пропусти любой или поверь клиенту — и дверь открыта.
22 понятия · схема у каждого · шпаргалка в конце
За словом «auth» прячутся два разных вопроса. Большинство багов безопасности рождается из их путаницы — или из того, что отвечают на один и забывают про другой.
Authentication (authN) — аутентификация: кто ты?
Показать паспорт в аэропорту — доказать, что ты и правда тот человек, за кого себя выдаёшь.
Это понятие Authentication (authN), и оно означает подтверждение личности: вход, passkey, токен, который говорит «это и правда Алиса». Обычно случается один раз за сессию. Ошибёшься — и самозванец входит как кто-то другой. Но подтверждение того, кто ты, не говорит ничего о том, что тебе можно, — это совсем другой вопрос.
- Что это
- Проверка, что пользователь — тот, за кого себя выдаёт.
- Как работает
Пользователь предъявляет креденшл (пароль, passkey, токен), система его проверяет и устанавливает личность.
- Пример
- Логин по email и паролю, «это Алиса».
- Подвох
- Знать, кто человек, — ещё не значит знать, что ему можно.
- Связи
Вход для Authorization; способы — Password Hashing, MFA, Passkeys, OIDC.
Authorization (authZ) — авторизация: что тебе можно?
Карта-ключ от отеля — она ничего не доказывает о твоём имени, но открывает твой номер, а не чужие, и не кабинет управляющего.
Это понятие Authorization (authZ): решение, что личности разрешено делать — читать это, править то, никогда не трогать админку. В отличие от authN, её надо проверять на каждый запрос, потому что один залогиненный пользователь может трогать сотню разных вещей. Знать, кто человек, — это не разрешение делать что-то конкретное.
- Что это
- Решение, что этой личности можно делать с этим ресурсом.
- Как работает
На каждый запрос: кто + действие + ресурс → правило → разрешить или отказать.
- Пример
Алиса-редактор может править документ #42, но не может открыть админку.
- Подвох
Проверить один раз и забыть. Проверять надо каждый запрос, на сервере.
- Связи
Модели — Least Privilege, RBAC, ABAC, Ownership Check; провал — Broken Access Control.
Два слоя — никогда не схлопывай их
Клуб: вышибала проверяет ID на входе один раз, а бармен всё равно проверяет твой возраст каждый раз, когда ты заказываешь. Две проверки, два момента.
Классическая ошибка — слить эти двое: подтвердить личность один раз и доверять этому навсегда или запихнуть все права в токен входа и больше не перепроверять. AuthN происходит на входной двери; authZ — на каждой двери внутри. Держи их раздельно и проверяй вторую постоянно.
Don't Roll Your Own Auth — никогда не делай свою
Ты не варишь себе банковский сейф из листового железа в гараже — ты покупаешь тот, что построили и испытали люди, которые больше ничем не занимаются.
Это практика Don't Roll Your Own Auth. Личность — это фундамент, на котором стоит всё остальное, и ошибиться в ней тонко до жути легко. Используй проверенные стандарты и библиотеки — устоявшиеся протоколы, обкатанную auth-библиотеку или провайдера, — а не хитрую схему, которую ты придумал. История безопасности вымощена самодельным auth, который выглядел нормально, пока вдруг не переставал.
- Проблема
- Самодельный auth выглядит нормально, пока его не сломают.
- Идея
- Брать проверенные протоколы, библиотеки и провайдеров.
- Пример
- Вместо своей схемы токенов — OIDC и auth из фреймворка.
- Цена
- Надо разобраться в чужом инструменте и правильно его подключить.
- Когда брать
- Почти всегда.
- Связи
- Ведёт к Auth Provider; стандарты — OAuth 2.0, OIDC.
Карта: 22 понятия в шести группах
Связка ключей: сначала видишь всю связку, потом узнаёшь, какой ключ от какой двери.
Понятия курса делятся на шесть групп. Каждая отвечает на свой вопрос: что такое два «auth», как доказать личность, как остаться залогиненным, как дать доступ без пароля, как решать про права и как всё это обычно ломается.
У каждого понятия дальше одно и то же: английское название (это термин, по нему ищут в документации), образ из жизни, схема и карточка с полями. В конце — шпаргалка со всеми понятиями.
Аутентификация — это дверь. Авторизация — каждая дверь внутри. Пропусти вторую — и первая ничего не значит.
Аутентификация сводится к доказательству, что ты — это ты. Факторы тянутся от слабого, но универсального пароля до современного, устойчивого к фишингу passkey.
Password Hashing — пароли: слабый дефолт
Секретное слово, известное тебе и швейцару, — нормально, пока его не подслушали, не угадали или ты не используешь одно и то же везде.
Пароли универсальны и при этом — слабейший общий фактор: их переиспользуют, угадывают, выуживают фишингом. Если без них никак, незыблемое правило — никогда не хранить их текстом. Храни медленный, солёный хеш (Argon2, bcrypt) — это и есть Password Hashing, — чтобы украденная база не выдала всем чужие пароли. (Подробнее в главе про ошибки.)
- Проблема
- Пароли в базе текстом: одна утечка — и все пароли у атакующего.
- Идея
Хранить не пароль, а медленный хеш с солью (salt) — своей для каждого пользователя.
- Пример
- При входе считаешь Argon2/bcrypt от введённого пароля и сравниваешь.
- Цена
- Вход чуть медленнее — и это нарочно.
- Когда брать
- Всегда, если хранишь пароли.
- Связи
- Анти-пример — Plaintext / Fast Hash; сверху добавь MFA.
MFA — многофакторка: что-то знаешь, имеешь, есть
Банковской ячейке нужен твой ключ и ключ банка. Один сам по себе не открывает ничего.
MFA (Multi-Factor Authentication), или двухфакторка, требует второе доказательство сверх пароля — что-то, что у тебя есть (код из приложения, аппаратный ключ) или что-то, чем ты являешься (отпечаток). Тогда даже украденный пароль сам по себе бесполезен. Код из приложения-аутентификатора (TOTP) надёжен; SMS-коды слабы (перехватываемы), но лучше, чем ничего. MFA — это самый большой и дешёвый выигрыш в безопасности, который можно добавить.
- Проблема
- Один украденный пароль = полный вход в аккаунт.
- Идея
- Требовать второй фактор другого типа: «имеешь» или «являешься».
- Пример
- Пароль + шестизначный TOTP-код из приложения-аутентификатора.
- Цена
- Лишний шаг при входе; SMS-коды можно перехватить.
- Когда брать
- Везде, где это важно; на админских аккаунтах — обязательно.
- Связи
- Укрепляет Password Hashing; Passkeys — следующий шаг.
Passkeys — будущее без паролей
Ключ, который работает только у той одной двери, под которую был выточен, — подделай сайт, сфоткай замок, и ключ просто не повернётся.
Passkeys (на основе стандарта WebAuthn) заменяют пароли криптографической парой ключей, привязанной к твоему устройству и настоящему сайту, так что нечего фишить, переиспользовать или сливать — и Apple, Google и Microsoft уже делают их дефолтом. Приватный ключ никогда не покидает устройство; сайт видит лишь подпись. Вот куда движется аутентификация: красть нечего.
- Проблема
- Пароли фишат, переиспользуют и сливают.
- Идея
Пара ключей: приватный остаётся на устройстве, у сайта — публичный. Вход — это подпись.
- Пример
- Вход по отпечатку или Face ID вместо ввода пароля.
- Цена
- Нужна поддержка устройств и запасной путь восстановления.
- Когда брать
Как основной вход там, где пользователи на современных устройствах.
- Связи
- Заменяет Password Hashing; сам по себе сильнее MFA по SMS.
Пароль — это секрет, который можно потерять. Passkey — это доказательство, которое нельзя. Добавь второй фактор в любом случае.
HTTP забывает тебя между запросами, так что после входа системе нужен способ продолжать тебя узнавать. Два подхода с реальным разменом.
Stateless HTTP — у HTTP нет памяти
Магазин, где продавец забывает тебя, едва ты отвернулся, — поэтому нужен чек, чтобы на следующем шаге доказать, что ты уже заплатил.
HTTP — stateless (без состояния): каждый запрос независим, сервер не помнит, что ты вошёл секунду назад. Поэтому после аутентификации тебе вручают нечто — куку или токен, — что ты шлёшь с каждым запросом, говоря «это всё ещё я». Всё ниже — два способа это сделать. (Это та самая безсостоятельность из курса про протоколы.)
- Что это
- Сервер не помнит предыдущие запросы клиента.
- Следствие
- После входа нужен «пропуск», который едет с каждым запросом.
- Пример
- Браузер сам прикладывает куку к каждому запросу на этот сайт.
- Связи
- Два ответа — Session и JWT.
Session — сессии: сервер помнит
Гардероб — у тебя на руках маленький номерок, а вся реальная информация лежит за стойкой под этим номером.
При сессиях (sessions) сервер хранит, кто ты, и вручает тебе куку, в которой лежит лишь случайный session id. На каждый запрос он этот id ищет. Сервер — источник правды, так что выйти или забанить кого-то — мгновенно: просто удали сессию. Цена в том, что серверу надо хранить это состояние и искать в нём. Правильный дефолт для большинства веб-приложений.
- Проблема
- HTTP не помнит, кто ты, между запросами.
- Идея
- Сервер хранит данные входа, клиент держит только случайный session id.
- Пример
- Кука
sid=8f3a…→ в хранилище8f3a → Алиса. - Цена
- Серверу нужно хранилище и поиск на каждый запрос.
- Когда брать
- Обычное веб-приложение. Это дефолт.
- Связи
Альтернатива — JWT; id хранится в httpOnly Cookie; отзыв — мгновенный.
JWT — токен несёт правду
Фестивальный браслет, на котором уже напечатан и запаян от подделки твой уровень доступа, — охранник проверяет пломбу, а не список гостей.
JWT (JSON Web Token) — это подписанный токен на руках у клиента, который содержит личность и права (claims); сервер просто проверяет подпись, без поиска. Это делает его безсостоятельным и лёгким для масштабирования по сервисам — но тяжёлым для отзыва: утёкший токен валиден, пока не истечёт. Поэтому держи срок жизни коротким и сочетай с refresh token. Отлично для API и микросервисов; избыточно для простого веб-приложения.
- Проблема
- Много сервисов, и каждому лезть в общее хранилище сессий — дорого.
- Идея
- Положить личность и права в сам токен и подписать его.
- Пример
Payload
sub: alice, role: editor, exp: …; каждый сервис проверяет подпись сам.- Цена
- Трудно отозвать: утёкший токен валиден до истечения.
- Когда брать
- API и микросервисы — короткоживущий JWT + refresh token.
- Связи
- Альтернатива Session; угроза — Token Leakage.
httpOnly Cookie — где ты его хранишь, важно
Ключ в запертом ящике против ключа, приклеенного к входной двери, — ключ тот же, безопасность совсем разная.
Токену в браузере место в httpOnly cookie (JavaScript не может её прочитать), а не в localStorage, откуда любой внедрённый скрипт его украдёт. Хранилище — часть безопасности: ошибёшься — и один XSS-баг отдаёт атакующему все сессии. Как ты переносишь и хранишь креденшл, не менее важно, чем сам креденшл.
- Проблема
- Токен в
localStorageкрадёт любой внедрённый скрипт. - Идея
- Хранить токен в куке с флагом
httpOnly— JS её не видит. - Пример
Set-Cookie: sid=…; HttpOnly.- Цена
- Почти никакой — это правильный дефолт для браузера.
- Связи
- Хранит Session id или JWT; защищает от Token Leakage.
Сессии: сервер помнит и может забыть тебя мгновенно. JWT: помнит токен, и забрать его назад непросто.
Часто ты вообще не хочешь иметь дело с паролем — ты хочешь, чтобы пользователи входили под уже имеющимся аккаунтом или чтобы один сервис действовал за другой. Для этого и есть OAuth2 и OIDC.
OAuth 2.0 — дать доступ, не делясь паролем
Парковочный ключ, который заводит машину и открывает дверь, но не багажник и не бардачок, — ты отдаёшь ограниченный доступ, а не всю связку.
Это протокол OAuth 2.0. Он позволяет пользователю выдать твоему приложению ограниченный доступ к его аккаунту в другом сервисе — твоё приложение читает его Google Calendar — ни разу не дав тебе его пароль от Google. Другой сервис вручает твоему приложению ограниченный по области (scope) access token («читать календарь, больше ничего»). Это про делегированную авторизацию, а не про личность.
- Проблема
- Приложению нужен доступ к чужому аккаунту, но пароль давать нельзя.
- Идея
- Сервис-владелец выдаёт приложению access token с узким scope.
- Пример
- Твоё приложение читает Google Calendar пользователя — и только его.
- Цена
- Протокол сложный; самому танцевать с токенами опасно.
- Когда брать
- Действовать от имени пользователя в другом сервисе.
- Связи
- Не говорит, кто пользователь, — для этого OIDC сверху.
OIDC — OAuth2, который ещё и говорит, кто ты
Тот же парковочный ключ, но теперь с пристёгнутым удостоверением с фото — не только «что этот ключ открывает», но и «и вот чей он».
Один OAuth2 говорит, к чему приложению можно дотянуться, а не кто пользователь. OpenID Connect (OIDC) добавляет сверху тонкий слой личности — ID token с проверенными claims (это Алиса, вот её email). Именно это питает «Войти через Google» и single sign-on (SSO). Когда нужен соц-логин или SSO, OIDC — это стандарт.
- Проблема
- OAuth2 даёт доступ, но не говорит, кто пользователь.
- Идея
- Добавить ID token с проверенными данными о личности.
- Пример
- Кнопка «Войти через Google»; вход в рабочие сервисы через SSO.
- Цена
- Зависишь от внешнего провайдера личности.
- Когда брать
- Соц-логин и single sign-on.
- Связи
- Построен на OAuth 2.0; это способ Authentication.
API Key — простой машинный креденшл
Запасной ключ, который ты даёшь доверенному подрядчику, — без имени, просто «у кого он есть, тот может войти».
API key — это длинная секретная строка, которая идентифицирует программу, а не человека, — для доступа «сервис — сервис» и программного доступа. Просто и эффективно, но он и есть креденшл: кто его найдёт, тот внутри. Поэтому ограничивай его область, ротируй и никогда не коммить в git и не клади в URL. Хорош для машин; не замена настоящей личности пользователя.
- Проблема
- Программе нужно входить в API без человека и без логина.
- Идея
- Длинный секрет, который опознаёт программу.
- Пример
- Бэкенд вызывает платёжный API с ключом в заголовке.
- Цена
- Ключ и есть доступ: нашёл — вошёл.
- Когда брать
- «Машина — машина». Не для входа людей.
- Связи
- Ограничивай по Least Privilege; главная угроза — Token Leakage.
OAuth2 одалживает доступ без пароля. OIDC добавляет «и вот кто это». Используй стандарт — не изобретай свой танец с токенами.
Когда ты знаешь, кто человек, ты решаешь, что ему можно трогать. Модели тянутся от грубых ролей до тонкой политики — и правило под всеми ними одно: deny by default.
Deny by Default / Least Privilege — запрещено всё, что не разрешено
Бейдж нового сотрудника, который не открывает ничего, пока каждую дверь явно не разрешат, — а не открывает всё, пока кто-то не вспомнит запереть пару.
Фундамент авторизации — два правила. Deny by default: всё запрещено, пока явно не разрешено. Least privilege (минимум привилегий): каждая личность получает минимум доступа, который ей нужен, не больше. Системы «по умолчанию открыто» текут — кто-то всегда забывает ограничить новый эндпоинт. Системы «по умолчанию закрыто» падают безопасно. Начинай с «нет» и выдавай осознанно.
- Проблема
- Новый эндпоинт забыли закрыть — и он открыт всем.
- Идея
- По умолчанию «нет»; выдавать только нужный минимум.
- Пример
- Новый сотрудник получает доступ только к своему проекту.
- Цена
- Чаще приходится явно выдавать права.
- Когда брать
- Всегда — это основа любой модели прав.
- Связи
- Фундамент для RBAC, ABAC, Ownership Check.
RBAC — права по роли
Театр, где тип билета — партер, бельэтаж, бэкстейдж — решает, куда тебе можно, не называя тебя лично.
RBAC (Role-Based Access Control) группирует права в роли — admin, editor, viewer — и назначает пользователям роли. Просто, читаемо и достаточно для большинства приложений: «редакторы могут публиковать, зрители нет». Становится грубо, когда правила зависят от контекста или от конкретной записи, — тут на сцену выходят следующие модели.
- Проблема
- Выдавать права каждому человеку по отдельности — хаос.
- Идея
- Права — ролям, роли — пользователям.
- Пример
- «Редакторы могут публиковать, зрители — только читать».
- Цена
- Грубо, когда правило зависит от контекста или конкретной записи.
- Когда брать
- Большинство приложений.
- Связи
- Тоньше — ABAC; всегда дополняй Ownership Check.
ABAC — права по политике
Правило вместо списка — «менеджеры могут одобрять расходы до 10k, в рабочие часы, с корпоративного устройства» — вычисляемое заново каждый раз.
ABAC (Attribute-Based Access Control) решает по атрибутам пользователя, ресурса и контекста — роль и сумма и время и устройство. Куда гибче фиксированных ролей и куда сложнее. Сигнал, что пора: ты навешиваешь больше пары кастомных условий if на свои проверки ролей.
- Проблема
- Права зависят не только от роли, но и от суммы, времени, устройства.
- Идея
- Правило-политика над атрибутами пользователя, ресурса и контекста.
- Пример
- Менеджер одобряет расход до 10k, в рабочие часы, с рабочего ноутбука.
- Цена
- Гораздо сложнее писать, читать и тестировать.
- Когда брать
- Когда к ролям прилипает больше пары кастомных
if. - Связи
- Развитие RBAC; стоит на Least Privilege.
Ownership Check — можешь ли ты трогать эту запись?
У тебя есть действующий читательский билет (роль), но это не даёт тебе читать заметки, нацарапанные в чужой взятой на руки книге.
Ownership check (проверка владения, или авторизация на уровне объекта) — самая пропускаемая проверка: даже валидный «редактор» должен править только свои документы, а не все подряд. Роль говорит «редакторы могут править»; тебе всё равно надо проверить, что этот редактор владеет этой строкой. Забыть это — самый частый баг контроля доступа: поменял id в URL — и ты в чужих данных. Всегда проверяй объект, а не только роль.
- Проблема
- Роль разрешает «править документы» — и человек правит чужие.
- Идея
- Кроме роли проверять, что этот объект принадлежит этому пользователю.
- Пример
Перед
PUT /docs/42проверить: владелец документа 42 — текущий пользователь.- Цена
- Лишняя проверка на каждый доступ к объекту.
- Когда брать
- Всегда, когда у данных есть владелец.
- Связи
- Дополняет RBAC/ABAC; без неё — IDOR.
Deny by default. Выдавай минимум. И всегда спрашивай не только «какая роль», но и «чья запись».
Auth ломается горсткой хорошо известных способов — одних и тех же, снова и снова, в приложении за приложением. Знать их — это половина защиты.
Broken Access Control / IDOR — забыл проверить
Здание, где входная дверь под охраной, но каждая внутренняя — нараспашку: раз уж ты внутри, можешь ходить где угодно.
Broken Access Control — уязвимость номер один в вебе: эндпоинт аутентифицирует пользователя, но забывает проверить, что ему авторизовано то, что он попросил. Её частейшая форма — IDOR (Insecure Direct Object Reference): меняешь /orders/123 на /orders/124 и видишь чужой заказ, потому что сервер ни разу не проверил владение. Утечки миллионов записей восходят ровно к этому. Проверяй authZ на каждый запрос, на сервере, против реального объекта.
- Что это
- Пользователь аутентифицирован, но права на объект не проверены.
- Как выглядит
/orders/123→/orders/124— и виден чужой заказ.- Чем грозит
- Утечки миллионов записей.
- Как чинить
authZ на каждый запрос, на сервере:
WHERE id = 124 AND owner = current_user.- Связи
- Лечится Ownership Check и Least Privilege.
Plaintext / Fast Hash — неправильное хранение паролей
Держать запасные ключи от каждого дома на улице в стеклянной банке на крыльце.
Хранение паролей текстом (plaintext) — или с быстрым хешем вроде MD5 — означает, что одна утечка базы обнажает всех, а переиспользованные пароли компрометируют ещё и другие их аккаунты. Пароли надо медленно и индивидуально хешировать (Argon2, bcrypt), чтобы их было дорого взломать даже украденными. То, что хеш медленный, — это смысл, а не недостаток.
- Что это
- Пароли в базе как есть или под быстрым хешем.
- Чем грозит
Одна утечка — все пароли; переиспользованные пароли открывают и чужие аккаунты.
- Как чинить
- Медленный хеш с солью: Argon2 или bcrypt.
- Связи
- Правильная версия — Password Hashing.
Token Leakage — утечка и доверие токенам
Написать код от сигнализации на стикере, приклеенном к двери, — замок в порядке; ты просто раздал секрет.
Token leakage — утечка токенов и ключей. Они утекают через URL (которые логируются), браузерный localStorage (который может прочитать скрипт) и секреты, закоммиченные в git. И токен надо проверять, а не доверять ему лишь потому, что он появился, — подделанный или истёкший надо отклонить. Относись к любому креденшлу как к тому, что однажды утечёт: короткий срок жизни, ротация и никогда — там, где это логируется или скрейпится.
- Что это
- Креденшл попадает туда, где его можно прочитать или найти.
- Как выглядит
?token=в URL, токен вlocalStorage, ключ в git-коммите.- Чем грозит
- Кто нашёл токен — тот вошёл.
- Как чинить
Проверять подпись и срок; короткая жизнь, ротация; httpOnly Cookie в браузере.
- Связи
- Больнее всего для JWT и API Key.
Trusting the Client — доверие клиенту
Магазин, который позволяет покупателям самим писать ценники и никогда не сверяет их на кассе.
Анти-паттерн trusting the client. Всё, что шлёт клиент — скрытое поле формы, роль в куке, флаг isAdmin=false, — можно подделать. Браузер, приложение, запрос — всё под контролем пользователя. Каждая настоящая проверка должна происходить на сервере, который пользователь править не может. Клиент — это предложение; сервер — это власть.
- Что это
- Решение о правах принимают по данным, которые прислал клиент.
- Как выглядит
- Роль в куке, скрытое поле, флаг
isAdminв запросе. - Чем грозит
- Пользователь сам себе выдаёт права.
- Как чинить
- Все проверки — на сервере; клиент только предлагает.
- Связи
- Частая причина Broken Access Control.
Почти любая утечка auth — это одно из трёх: пропущенная проверка, плохо хранимый секрет или поверили клиенту.
Хороший auth — это в основном про то, чтобы правильно использовать проверенные инструменты и неустанно проверять права, а не про изобретательность. Вот как выбирать.
Auth Provider — используй библиотеку или провайдера
Ты не производишь себе ремни безопасности — ты ставишь сертифицированные, спроектированные специалистами и испытанные в краш-тестах годами.
Почти для всех правильный ход — не строить auth самому: используй auth своего фреймворка или auth provider (Auth0, Clerk, Supabase, Cognito и подобные), который берёт на себя хеширование, сессии, MFA, OAuth и краевые случаи, о которых ты бы и не подумал. Твоя работа — корректно его подключить и владеть авторизацией — той частью, которую знаешь только ты.
- Проблема
- Своими руками auth почти всегда получается с дырами.
- Идея
- Отдать authN проверенному инструменту, себе оставить authZ.
- Пример
- Auth0, Clerk, Supabase, Cognito или встроенный auth фреймворка.
- Цена
- Зависимость от поставщика; его надо правильно подключить.
- Когда брать
- Почти всегда.
- Связи
- Реализует Don't Roll Your Own Auth.
Подбери механизм под приложение
Ключ от дома, ключ от машины и карта-ключ от отеля — всё это «ключи»; выбираешь ты по двери, а не по моде.
Сессии для обычного веб-приложения (просто, мгновенно отзываемо); короткоживущие JWT плюс refresh, когда нужен безсостоятельный масштаб по сервисам; OIDC для соц-логина и SSO; API-ключи для «машина — машина». Добавляй MFA везде, где это важно, особенно на админских аккаунтах. Выбирай по форме своего приложения, а не по тому, что звучит продвинуто.
- Пароли медленно хешируются (Argon2/bcrypt) и никогда не хранятся текстом?
- Доступна ли MFA и обязательна ли для админов?
- Каждый ли эндпоинт проверяет authZ — роль и владение объектом?
- Токены в httpOnly-куках, короткоживущие и никогда не в URL или git?
- Настоящая проверка на сервере, без доверия ролям от клиента?
- Использую ли я проверенную библиотеку/провайдера вместо самопальной схемы?
- Смена id в URL показывает чужие данные.
- Право живёт в куке или скрытом поле, которое клиент может править.
- Пароли хранятся текстом или в MD5.
- Нет способа отозвать залогиненного пользователя, кроме ожидания истечения.
- Нет MFA на аккаунтах, способных нанести больше всего урона.
- Ты написал свою схему токенов или крипту.
- AuthN и authZ раздельны, и authZ проверяется на каждый запрос.
- Каждый доступ к объекту проверяет, что этот пользователь владеет этой вещью.
- Креденшлы хешированы, ограничены по области, короткоживущи и ротируемы.
- Сервер — это власть; ничто не доверяет клиенту.
- Ты можешь отозвать доступ и увидеть кто что сделал в логе.
- Тяжёлая работа лежит в проверенной библиотеке или провайдере, а не в твоём коде.
Как всё связано
Путь гостя в отеле: паспорт на ресепшене, карта-ключ на руках, и каждая дверь сама решает, открыться ли.
Факторы входа (пароль, MFA, passkey, OIDC, API-ключ) ведут к authN. Её результат едет с каждым запросом в сессии или JWT, лучше всего в httpOnly-куке. На каждом запросе authZ решает по ролям или политике — и всегда проверяет владение объектом.
Шпаргалка: все 22 понятия
Два вопроса
- Authentication (authN)аутентификация
Подтвердить, кто ты. Обычно один раз за вход.
- Authorization (authZ)авторизация
Решить, что тебе можно. На каждый запрос.
- Don't Roll Your Own Authне делай свой auth
Бери проверенные стандарты и библиотеки, а не свою схему.
Подтвердить, кто ты
- Password Hashingхеширование паролей
Храни медленный солёный хеш (Argon2, bcrypt), а не пароль.
- MFAмногофакторка, 2FA
Второй фактор: что-то имеешь или чем являешься. Самый дешёвый выигрыш.
- PasskeysWebAuthn
Пара ключей на устройстве, вход по подписи. Фишить нечего.
Оставаться залогиненным
- Stateless HTTPHTTP без состояния
Сервер не помнит запросы — нужен пропуск в каждом.
- Sessionсерверная сессия
В куке только id, правда — на сервере. Мгновенный отзыв. Дефолт.
- JWTJSON Web Token
Подписанный токен с правами внутри. Без поиска, но трудно отозвать.
- httpOnly Cookieкука без доступа из JS
Место для токена в браузере. XSS её не прочитает.
Делегированный доступ
- OAuth 2.0делегированная авторизация
Доступ к чужому аккаунту по токену с узким scope, без пароля.
- OIDCOpenID Connect
OAuth2 + ID token: «и вот кто это». Соц-логин и SSO.
- API KeyAPI-ключ
Секрет для программ. Узкий scope, ротация, не в git и не в URL.
Права
- Least Privilegedeny by default
По умолчанию «нет»; выдавай только нужный минимум.
- RBACRole-Based Access Control
Права по ролям: admin, editor, viewer.
- ABACAttribute-Based Access Control
Права по политике над атрибутами пользователя, ресурса, контекста.
- Ownership Checkпроверка владения
Не только «какая роль», но и «чья запись».
Как ломается
- Broken Access Control / IDORсломанный контроль доступа
Забыли проверить права: поменял id в URL — видишь чужое.
- Plaintext / Fast Hashпароли текстом или в MD5
Одна утечка базы — все пароли наружу.
- Token Leakageутечка токенов
Токены в URL, localStorage, git. Кто нашёл — тот вошёл.
- Trusting the Clientдоверие клиенту
Клиент — предложение, сервер — власть.
Сделать правильно
- Auth Providerauth-библиотека или сервис
Отдай authN проверенному инструменту, authZ оставь себе.
Auth — это не место, где умничают. Это место, где правильно используют стандарты, отказывают по умолчанию и никогда, ни за что не доверяют клиенту.