ХРАНЕНИЕ REFRESH ТОКЕНА
Несколько лет назад я делала краткий обзор аутентификации и авторизации. Про JWT и процесс создания/обновления токенов довольно понятно написано в стандарте. Также можно почитать подробные статьи на эту тему: 1, 2.
Сейчас хочется поговорить о работе с refresh-токенами: где их хранить на клиенте и нужно ли их хранить на сервере?
Давайте по порядку:
❓Где клиент хранит токены?
Наиболее важная задача для клиента — безопасно хранить и передавать refresh-token. Потому что именно этот токен может предоставить злоумышленникам долговременный доступ к ресурсам системы. Срок его жизни — это обычно дни или недели, к тому же, с его помощью можно получить новый refresh-token и так далее.
Обычно клиенты используют один из этих вариантов хранения:
• HttpOnly cookie — защищает от XSS, но уязвим к CSRF. Можно дополнительно создавать CSRF-токен, который хранится в переменной JS и передаётся в заголовке запроса. Так мы обеспечим защиту и от XSS, и от CSRF.
• LocalStorage / SessionStorage — удобно, но доступно любому JS-коду на странице.
• In-memory (переменная в JS) — безопасно, но теряется при обновлении страницы, поэтому там обычно хранят access-токен и CSRF-токен.
❓Где сервер хранит токены?
Access-токен живет в идеале до 15 минут и служит только для доступа к ресурсам, поэтому хранить на сервере его не нужно. А вот с refresh-токеном возможны разные варианты:
• Stateless (без хранения) — сервер ничего не хранит, только проверяет подпись. Вся нужная информация содержится в токене. Однако при таком подходе невозможно отозвать токен до истечения срока. Если токен украли — сделать ничего нельзя.
• Хранилище данных (Redis, СУБД) — позволяет отзывать токены, отслеживать сессии, реализовать ротацию. Очень важно хранить токены в захешированном виде.
• Гибридный вариант — stateless-токены плюс blacklist отозванных токенов в Redis/БД. Хранятся не все токены, а только те, что нужно инвалидировать.
❓Как безопасно хранить токены на сервере?
• Хеширование — refresh-токен это по сути пароль для получения access-токена. Поэтому его обязательно надо хешировать перед сохранением в хранилище.
• Ротация — при каждом обновлении токена клиент получает не только новый access, но и новый refresh-токен. Таким образом refresh чаще обновляется, а клиенту надо реже отправлять логин и пароль на сервер.
• Инвалидация старых токенов — старый refresh-токен помечается как отозванный сразу после выдачи нового. И если им кто-то еще раз попробует воспользоваться — это сигнал о возможной компрометации. После этого можно отозвать всё семейство токенов, вынудив пользователя войти заново.
• Хранение мета-информации — идентификатор устройства, срок действия, дата инвалидации, семейство токенов и пр.
Запоминая устройства, мы можем инвалидировать все устаревшие токены при перелогине на определенном устройстве.
При помощи даты инвалидации легче отслеживать попытки взлома аккаунта.
А семейтво токенов поможет определить, какие именно токены могли быть скомпроментированы.
✅ Как обычно, выбор способов хранения и обеспечения безопасности зависит от конкретики системы и требований:
Находится система в контуре компании или доступ открыт всему интернету?
Hасколько чувствительны данные?
Какие будут последствия компроментации?
Сколько стоит реализация и поддержка каждого этапа обработки refresh-токенов? И т.д.
А с какими вызовами вы сталкивались при реализации аутентификации?
Post #93
2.06K