Pull to refresh

Comments 26

>> Чтобы злоумышленник смог пользоваться дольше — ему потребуется украсть еще и рефреш, но тогда настоящий пользователь узнает, что его взломали, поскольку его выкинет из системы.

Немного не понятен механизм проверки на компрометацию рефреш токена. Не могли бы, подсказать где прочитать или может в двух словах?
Нет никакой проверки. Невозможно узнать, был он скомпрометирован, или же нет.
На самом деле смысл такой.
У вас есть Access Token (в нашем случае JWT) и Refresh Token (любой).
Access Token — короткоживущий (например, час; можно реализовать через exp), его можно не записывать в базу, проверяется только по подписи.
Refresh Token — живет дольше (например, 30 дней), записан в базу и проверяется по наличию в ней.
Когда нужно сгенерировать новый Access Token:
— берём Refresh Token из запроса
— ищем его в базе и получаем код связанного с ним пользователя
— удаляем текущий Refresh Token из базы
— генерируем новую пару токенов
— новый Refresh Token записываем в базу.
Если кто-то украдет из клиентского приложения только Access Token, он проживет тот же час и протухнет.
Если кто-то украдет оба токена, то через час одна копия приложения успешно получит новую пару токенов, а вторую выкинет, так как такого Refresh Token уже нет в базе.
все верно. И тогда пользователь увидит, что его выкинуло и что-то заподозрит.
Также довольно сложно обсуждать рефреш токен без обсуждения токена со sliding expiration, потому-что вроде как это два подхода к решению проблемы короткой жизни access token.
Если коротко, то для решения этой проблемы можно использовать либо долгоживущие access токены, либо токены со sliding expiration. Это значит, что при каждом обращении к серверу время жизни токена обновляется. То есть он протухает, например, за 10 минут, но именно за 10 минут бездействия.
Проблема такого подхода в том, что если пользователя удалять или урежут его права, то он будет продолжать ходить с существующим access токеном все-еще со старыми правами неограниченное время. Для этого и ввели refresh токены, т.к. чтобы дропануть пользователя, достаточно просто удалить его из бд

Ещё проблема — нужна постоянная активность пользователя, либо какие-то keepalive-запросы.

нет, в том и дело, что рефреш токен выдается на очень длительный срок (или бессрочно), т.к. вы его жизнь можете контролировать на сервере
Если кто-то украдет оба токена, то через час одна копия приложения успешно получит новую пару токенов, а вторую выкинет, так как такого Refresh Token уже нет в базе.

Так а если обновится утекший токен? У злоумышленника будет рабочий токен, хоть и не надолго.

Да. Это зависит от времени жизни токена, да и вообще меньшее зло. Либо запрашивать сервер авторизации на каждый чих, либо допустить кратковременный доступ для злоумышленника.
В конце концов, идеальной защиты не существует. Если кого-то захотят взломать — взломают.

смысл в RT если можно точно так же послать на какой-нибудь ендпоинт JWT и вам вернут новый JWT? :) таким образом старый украденый JWT перестанет быть валидным.
старый не перестанет быть валидным, т.к. он все-еще расшифровывается подписью, а это ровно то, что и проверяется
ничего не понял, а как вы тогда инвалидируете по своей схеме JWT? он же и через тысячу милионов лет будет расшифровываться в таком случаи :)
Есть короткий Access токен, который никак не развалидировать, так-что в хучшем случае там 10 минут еще с ним походят, есть refresh токен, по которому обычно можно получить Access токен. Но рефрешь токен также хранится в базе данных для этого пользователя, например. И когда по рефрешь токену просят обновить access токен проверяется, что пришедший токен и токен в базе совпадают, выдается новый access и новый refresh, в базе обновляется. Соответственно если кто-то зашел под твоим логино-паролем или с твоим рефрешь токеном, то тот, который остался у тебя падает, т.к. в базе лежит уже другой. Ну или если нужно удалить/порезать пользователя в правах, то его токен дропается с базы и ему нужно перезайти (соответственно его текущий токен с его старыми правами становится не валидным)
Не знаю, в статье просто как-то этот процесс не очень подробно описан (а в комментарии передать тяжело)
Каким образом инвалидируется еще действующий access token? Т.е. пользователя урезали, но пока жив его старый access token он может пользоваться старыми правами. Как это решается?
Только коротким временем действия Access-токена, больше никак не ограничено.

Не совсем по теме вопрос.


HS256 vs RS256
Если на стороне клиента не требуется проверять подпись,
то что дает (в плане безопасности, скорости и т.д.) rs256?
Имеет ли смысл ограничиться HS512?


Спасибо.

RS256 — асимметричный, имеет смысл если у вас отдельно вынесенный сервер авторизации. У сервера авторизации есть секретный ключ для подписи токена, а на прикладном сервере только парный открытый ключ для проверки подписи.
Если прикладной сервер взломают, то всё равно не смогут генерировать корректно подписанные токены. Сервер авторизации при этом может быть один на группу прикладных и, соответственно, более защищённым, поскольку к нему обращаются только прикладные серверы.

Условия:
Авторизации как таковой у меня нет.
Я использую JWT, разумеется, чтобы не хранить у себя состояние, которое я не могу восстановить, если я его не храню или мне его не вернут.
Отдельного сервиса с ключом у меня тоже нет, можно считать, что каждый сервис хранит ключ у себя и вопрос взлома не стоит.


Использование:
Один раз я отдаю токен с данными клиенту, второй раз, если они его устраивают,
он мне возвращает токен, я проверяю время и подпись, затем применяю эти данные.


Вывод:
Не имея в наличие отдельного сервиса, который создавал бы токены, выгоды в RS256 я не вижу.(В моем случае)

Так если вы не используете авторизацию, то и токены вам особо не нужны.
Без авторизации всем пользователям доступнs все данные и функции и нет смысла в подписи токена. Полезная же нагрузка без кодирования в base64 займёт в полтора раза меньше места.

У меня Stateless сервис, для этого мне и нужны JWT токены.
Насчет base64 — пока оставил в таком виде, чтобы не городить велосипеды.

на стороне клиента обычно не проверяется подпись, там есть открытая часть, которую просто можно прочитать, а есть закрытая, которая является зашифрованной открытой с некоторым ключем. Если вы имеете в виду другие сервисы — потребители токенов, то там в любом случае требуется проверять подпись (а если не требуется, то можно и не подписывать)
UFO just landed and posted this here
Пока токены на скомпрометированы, каждое устройство будет иметь свою пару токенов (Access + Refresh). Как только будет обнаружен неверный Refresh-токен, все Refresh-токены этого пользователя будут аннулированы и на всех устройствах придётся перелогиниться по истечению срока действия их Access-токенов.

Смотря как настроено.
Самый лучший вариант — показывать текущие сессии пользователя, с IP и GeoIP-данными, и иметь возможность закрыть любую из них (удалив Refresh Token).

Насколько я понял в предлагаемой схеме клиентское приложение самостоятельно отслеживает истек JWT или нет и, в случае необходимости, запрашивает RT. А что если у пользователя некорректно установлено время в системе и JWT при каждом запросе будет считаться истекшим? Не правильнее ли будет на клиенте запрашивать RT при получении от сервера ошибки «Токен истек»?
Т.е. основной сценарий использования такой: клиент запрашивает ресурс с JWT и если сервер возвращает ошибку «Токен истек», тогда клиент отправляет RT и нам приходит новая пара JWT+RT. С новым JWT мы снова можем обращаться к приватным ресурсам.
Или я неправильно понял и имелась ввиду именно такая схема?
Такой вариант тоже возможен и он должен использоваться не вместо, а наравне с основным. Случай, когда токен уже протух — обязательно должен обрабатываться. И не стоит бояться неправильно установленного времени, потому что Date.now() всегда отработает корректно.
А разве Date.now() информацию берет не с установленного у пользователя времени? Если я выставлю на своем компе некорректную дату и время, разве результат будет правильным?
Sign up to leave a comment.

Articles