Аутентификация и потоки OAuth2
Что это такое
Аутентификация отвечает на вопрос, кто вызывает систему, и в современном API вызывающий предъявляет обычно не пароль, а токен, выданный провайдером идентификации. OAuth2 описывает, как такой токен получают: кто просит доступ, кто аутентифицирует пользователя, чем клиент доказывает собственную личность и что позволяет выданное разрешение. От вида клиента и от того, присутствует ли при этом пользователь, зависит выбор потока.
Почему это важно
Неверно выбранный поток оборачивается тем, что секрет уезжает внутрь мобильного приложения, а пользователя просят ввести пароль в чужом сервисе. Каждый поток существует потому, что клиент определённого вида не умеет хранить секрет или перенаправлять браузер, и когда понятно, зачем они нужны, правильный выбор становится очевидным. Небезопасное сокращение тогда видно именно как сокращение, а не как настройка.
Ключевые идеи
Стороны различны, и их секреты тоже
Владельцем ресурса выступает пользователь, клиентом — приложение, которое просит доступ, сервер авторизации выдаёт токены, а сервер ресурсов их принимает, и для любого потока ключевой вопрос один: кто из этих сторон способен хранить секрет. Серверное приложение способно; страница в браузере и мобильное приложение — нет, и именно это закодировано в выборе потока.
пользователь -> клиент -> сервер авторизации -> токен -> сервер ресурсов
Authorization code с перенаправлением — вариант по умолчанию для клиентов с пользователем
Пользователя отправляют на сервер авторизации. Там он аутентифицируется и возвращается к клиенту с короткоживущим кодом, который клиент обменивает на токены. Пароля пользователя клиент не видит никогда, а без собственных учётных данных клиента сам код бесполезен. Такая форма годится для серверных приложений; однако клиентам, которые не в состоянии хранить секрет, требуется дополнительный шаг доказательства.
Поток client credentials — для сервисов без пользователя
Когда один бэкенд вызывает другой и пользователя в этом нет, вызывающий сервис аутентифицируется как он сам и получает токен для своей личности, потому что ни шага согласия, ни пользователя здесь нет. Поток от этого намного проще — и уместен он только там, где тот, кто вызывает, действительно действует от своего имени, а не от чьего-то другого.
Секрет нельзя хранить в браузере или в мобильном бинарнике
Всё, что попало на устройство пользователя, можно прочитать, поэтому такой клиент приходится считать публичным. Любой поток, который требует от него хранить секрет, сломан по построению. Отсюда и дополнительный шаг доказательства, и вытеснение потока в стиле implicit grant, возвращавшего токен прямо в браузер.
Токены должны быть краткоживущими, а обновление — отдельным разрешением
Access token предъявляется при каждом запросе и чаще всего становится добычей копирования, поэтому срок его жизни должен быть коротким. Refresh token хранят тщательнее и используют только против сервера авторизации; им и получают новый access token, не тревожа пользователя лишний раз. Долгоживущие access token убирают запас прочности, благодаря которому утечку ещё можно пережить.
Области доступа выражают разрешение, а не роль пользователя
Область доступа говорит, что клиент попросил разрешения делать — читать заказы, писать платежи, — и на что пользователь дал согласие, но о полномочиях пользователя внутри приложения она ничего не утверждает. Именно разделение этих двух вещей позволяет сделать разрешение узким, не ограничивая того, что пользователь может делать в другом контексте.
Практика
Выберите поток для трёх клиентов
Укажите, какой поток использует каждый из трёх клиентов — серверное веб-приложение, одностраничное приложение и ночная пакетная задача, — и где этот клиент хранит свой секрет.
Готово, когда: в каждом выборе названа сторона, хранящая секрет, и ни одному клиенту, не способному его хранить, секрет не вменяется.
Проследите жизненный цикл токена
Опишите последовательность от первого запроса пользователя до того момента, когда истёкший access token обновляют, и назовите, у какой стороны на каждом шаге находится каждая учётная единица.
Готово, когда: вы можете сказать, сколько access token остаётся действительным и что происходит с запросом в полёте, когда он истекает.
Частые ошибки
- Хранение секрета клиента в браузере или мобильном приложении — его прочтёт кто угодно; исправить: считайте клиент публичным и выбирайте поток, не требующий секрета.
- Использование долгоживущего access token — утечку нельзя ограничить сроком действия; исправить: держите access token коротким и обновляйте его.
- Использование потока client credentials от имени пользователя — личность сервиса подменяет личность пользователя; исправить: берите поток, в котором участвует пользователь.
- Трактовка области доступа как роли — узкое разрешение принимают за ограниченные полномочия; исправить: держите решения об авторизации отдельно от разрешения.
- Работа с паролем пользователя внутри клиента — пароль оказывается под ударом собственных багов клиента; исправить: отправляйте пользователя на сервер авторизации.
Что читать дальше
- Проверка JWT и авторизация (05-backend-data/10-authentication-authorization-oauth2-jwt/02-jwt-verification-and-authorization) — что происходит с токеном после того, как его выдали.
- Аутентификация и авторизация (OAuth2 / JWT) (05-backend-data/10-authentication-authorization-oauth2-jwt) — пара задач, первой половиной которой служит этот дочерний урок.
- Веб-безопасность (OWASP Top 10) (07-security/01-web-security-owasp-top-10) — атаки, нацеленные на перенаправление и работу с сессией вокруг этих потоков.