Аутентификация и контроль доступа
Аутентификация и контроль доступа решают три разных вопроса: кто вы (идентификация), правда ли это (аутентификация) и что вам можно (авторизация). Смешивать их нельзя — большинство ошибок доступа рождается именно из подмены одного другим. Поверх этой основы лежит практический слой: как устроен JWT, где его хранить, какие у него подводные камни и как защитить процессы входа и восстановления аккаунта.
Ловушки тут дорогие. JWT подписан, но не зашифрован — его payload читается, поэтому секреты в нём утекают; localStorage доступен любому скрипту, поэтому один XSS крадёт токен; alg=none заставляет сервер принять неподписанный токен; а разные ответы на неверный логин и неверный пароль открывают перечисление пользователей. Каждый механизм и его защита — в слоях ниже.
Карта темы
- Идентификация, аутентификация, авторизация — три разных шага, их порядок и почему их нельзя путать.
- Структура JWT — три части
header.payload.signatureи почему подпись не равна шифрованию. - Хранение JWT на клиенте —
localStorageпротивhttpOnly-cookie против памяти и риски каждого. - Уязвимости JWT —
alg=none, путаницаHS/RS, слабый секрет, отсутствиеexp, инъекцияkid. - Защита входа от атак — детект и предотвращение brute-force, stuffing, spraying, enumeration и угона сессии.
- Защита от SMS-бомбинга — почему проблема в стоимости отправки, а не в угадывании кода.
- Аудит восстановления пароля — предсказуемые ссылки, host header injection, TTL и лимиты OTP.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
| Путать аутентификацию (доказательство) с авторизацией (права) | Неверная модель доступа: проверяете не то и не там |
Считать payload JWT зашифрованным и класть туда секреты | Payload читается любым — секреты утекают |
Хранить JWT в localStorage | Один XSS крадёт токен: localStorage доступен любому скрипту |
Не отклонять alg=none на сервере | Сервер принимает неподписанный токен — обход аутентификации |
| Выдавать разные ответы на «нет пользователя» и «неверный пароль» | Перечисление пользователей (enumeration) |
Строить ссылку восстановления из заголовка Host | Host header injection — злоумышленник подменяет домен ссылки |
Оставлять эндпоинт отправки OTP доступным анонимам | SMS-бомбинг жжёт бюджет на отправке |
Значение для собеседований
Тема проверяет, отличаете ли вы слои доступа и понимаете ли, что именно защищает каждый механизм. Кандидат, который говорит «JWT подписан, а не зашифрован; localStorage крадётся XSS-ом; авторизацию проверяют на каждый запрос», сразу отделяется от того, кто заучил слова.
Что обычно проверяют:
- Разницу идентификации, аутентификации и авторизации и их порядок.
- Из чего состоит
JWT, почему payload читаем и куда его безопасно класть. - Типовые уязвимости
JWTи как их закрыть (alg,exp, ключи,kid). - Как детектировать и предотвращать credential stuffing, spraying, brute-force и угон сессии.
- Какие изъяны искать в потоке восстановления пароля и защите от
OTP-абуза.
Типичный неверный ответ: «JWT зашифрован, поэтому в payload можно хранить что угодно, а localStorage безопасен, ведь токен нельзя прочитать без ключа сервера». На деле обычный JWT только подписан, payload читается декодированием base64url, а токен в localStorage читает любой скрипт на странице.