Pull to refresh

Comments 8

А как спасает от последствий кражи AccessToken, ввод RefreshToken? Ведь тем же XSS можно увести и RT.
Ну, как гласят ресурсы про использование RefreshToken: если не использовать RefreshToken, то чтобы блокировать сворованный AccessToken необходимо в каждом запросе проверять его (и сверять например с черным списком токенов). Но token-ы и являются self-contained (то есть включают и имя пользователя и роль и другие необходимые для авторизации поля), чтобы не делать лишних обращений к бд. В случае с RefreshToken — он отправляется редко, и при этом уже происходит обращение к базе данных и проверяется что токен валидный и пользователь не блокирован и т.д.
Ну и плюс если токены летают не по SSL, то украсть refresh token, сложнее, так как он реже отправляется.
В общем грубо говоря Refresh Token — это как замена полной пере-аутентификации пользователя, только она автоматическая и не требует светить логин и пароль лишний раз.
Обращения к БД можно делать например в 5% случаев, чего вполне достаточно.
Я использовал JWT+Session storage+ttl для документа в Mongo и каждые 30 минут обновлял сессию, причем в документе пользователя всегда сохранялась разница в айпишниках между сессиями и время последней сессии (если пользователь сообщил о проблеме — все операции по этому айпишнику будут логгироваться до повторной проблемы и простого решения).
У нас равносильно используются как Cookies, так и Tokens, для доступа к API. Cookies для браузеров, Tokens для приложений. Используем `access_token` вместе с `refresh_token`. У пользователя есть поле `SecurityStamp`, от него генерируем по `hmac` `refresh_token`. И собственно через него обновляем `access_token`. Также от `SecurityStamp` генерируем соль для `access_token`. При смене пароля или сброса сессий изменяем `SecurityStamp` и рефреш токены становятся не валидными. И в любой момент можем активировать проверку соли для `access_token`ов, что бы оградить пользователя от временного окно действительного `access_token`.
Вот несколько заметок, которые помогут улучшить секьюрность при использовании JWT:

1. При создании токена, в его тело необходимо внести IP адрес пользователя. Затем при каждом запросе сверять это поле с тем адресом откуда поступил запрос. Таким образом, даже имея токен, злоумышленник не сможет воспользоваться им. Этот способ накладывает некоторые дополнительные неудобства для пользователя, например придётся авторизовываться заново каждый раз когда меняется его IP. Однако, в большинстве случаев это происходит не очень часто и не должно вызывать особого дискомфорта.

2. Можно, конечно, при каждом запросе дёргать вашу БД и сверять данные из токена с данными в записи пользователя. Иными словами, при каждом запросе обращаться к БД, доставать юзера и убеждаться в том, что данный запрос может быть выполнен, при этом что и как сверять зависит только от вашей задумки. Можно проверять, не заблокирован ли пользователь, не менял ли он пароль с момента выдачи токена, подходящая ли у него роль и т.д. Этот способ довольно грубый, но максимально эффективный. Тем не менее, есть более практичный и интересный способ проверки, не насилующий вашу основную БД — смотрите пункт 3.

3. Хранение списка актуальных токенов (т.н. «белый список») в отдельной высокопроизводительной БД, например Redis или Memcahed. При каждом запросе, после обычной проверки токена на валидность, мы также проверяем его наличие в этой БД. Если по какой-то причине его там не оказалось — значит запрос не может быть выполнен и нужно получить новый токен. Таким образом, после каких-то критических действий с аккаунтом (смена пароля, смена роли, бан и т.д.) мы просто удаляем из белого списка все токены, относящиеся к этому аккаунту.
Держать список валидных это тяжеловато. Да, это удобно в плане хранения в мемкеше, где если и потеряется, то ничего страшного, но неудобно в плане масштабирования. Тут или балансировщик должен по пользователю раскидывать, или все эти ключи должны быть на каждом сервере. В этом плане проще таки держать список невалидных. Да, от копирования на все сервера мы не убежим, но он банально меньше, причем при правильно выбранных задержках — меньше на порядки.
1) IP меняется часто в условиях мобильного интернета. Как быть в этом случае? Для авторизации мобильных приложений этот способв совсем как-то не подходит.

2 и 3) Можно хранить в базе не токен (я не вижу в этом смысла, если чувак смог подделать подпись то значит у нас очень большая беда), а идентификатор сессии. В этом случае мы можем и сессию дропнуть и все такое. В случае redis нагрузка и объемы данных хранимые будут минимальны. Опять же там же можно хранить IP адреса с которых токен использовался и если того требует логика высылать нотификашку если внезапно пользователь начал использовать сессию из другой страны.
Sign up to leave a comment.

Articles