Как стать автором
Обновить

Комментарии 7

По поводу недостатков при логауте. Я использую такую схему


  • если при логине не поставить галочку "запомнить меня", время жизни токена 1 час
  • если поставить — 2 недели
  • при логауте записываю токен в блеклист, блеклист храню в Redis
  • при смене пароля инкрементится поле, которое также участвует в формировании токена, следовательно все предыдущие токены становятся невалидными

Да, чтобы проверить валидность токена, приходится лезть в базу пользователей. Но текущего пользователя все равно придется доставать, так что не считаю это проблемой


Блеклист в Redis получается относительно невелик, так как те, кто выбирают "запомнить меня" редко вылогиниваются вообще


Нерешенным является вопрос отображения всех залогиненных мест и выборочная инвалидация, но это невозможно сделать без хранения токенов, что собственно лишает использование jwt смысла

Ребят, а чем вам refresh_token не угодил-то? Вместо этого городить Redis и постоянно на каждый чих делать туда запросы на блеклист токена это моветон.

Текущего пользователя нужно доставать далеко не всегда, наоборот JWT создан для того чтобы в нем хранить скажем, его роли,, а не лазить за пользователем постоянно в базу.

В итоге ваш велосипед приводит к минимуму 2 обращениям к двум разным базам на каждый запрос… Оптимизация в действии.
Как уже описал товарищ x512, вы не совсем корректно используете данный механизм.
1. Чистый JWT токен самостоятельно практически не выдается. Для этого есть OAuth2 или, что более предпочтительней — OpenId Connect.
2. Ваша проблема решается связкой access_token + id_token + refresh_token. Лайфтайм первого — минимально допустимый(пара минут). Второго — хоть на две недели. Дополнительно можно докинуть SSO куку вместо или иногда даже вместе с refresh_token.
3. Логаут делается при помощи редиректа на Identity Provider(Idp) — например EndSession endpoint в OpenId Connect.
Вы передаете свой id_token на этот эндпоинт и опционально получаете редирект на нужный Url. При этом на Idp чистятся сессии, SSO и тд.
4. Валидность токена можно проверить при помощи валидации подписи и времени выдачи + жизни. Так же можно делать онлайн проверку на Idp.
5. Все выданные токены хранятся на Idp Для возможности отзыва — типичный пример: удаляем refresh_token и приложение не может обновить access_token через минуту.
6. Ну есть еще вариант с SPA приложениями — SSO + access_token. Тут просто убиваем сессию SSO и никаких токенов данному господину.
7. Доступ к атрибутам пользователя из приложения происходит только из данных токена + опционально UserInfo Endpoint(для OpenId Connect). Это дает возможность размазать все это по микросервисам и получить тру стэйтлес.

Если вы спросите где достать OpenId Connect Idp — то один из самых удачных на .Net IdentityServer 3. Ставится как OWIN MIddleware или просто Middleware в 4 версии для Core.

var key = Encoding.UTF8
                              .GetBytes("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1");


Если это ключ в HEX представлении, то так делать не надо.
Может я не понял чего, но чем не устраивают классические FormsAuthentication.SetAuthCookie или FormsAuthenticationTicket, туда же тоже можно записать, что угодно, хоть JSON строку, все равно же куки передаются в AJAX заросах? Или тут фишка в другом?
1. Forms — deprecated. Вместо него есть CookieAuthenticationMiddleware.
2. REST эндпоинт для мобильного приложения по куке ходить? Ну или ваш клиент другой сервис?
3. Как пробросить Identity во внутренний сервис? Кукой? А как проверить валидность? Ключи шарить?

Хотя кука для фронта ИМХО самый безопасный механизм(Secure+NoScript+SameSite).
refresh_token весьма удобное решение в распределенной системе где необходимо делегировать доступ к пользовательским данным. И у него есть даже альтернатива, которую я описал в комменте выше(Implicit Flow). За блэклист токенов и вывод — кол.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий