Стоит ли создавать разные таблицы для хранения JWT (веб и API для мобильного приложения)?
Создаю бэкенд, в котором есть и веб часть и API для мобильного приложения (авторизация в разных частях идет через разные таблицы ). Фронт на реакте. Авторизация с фронта по JWT.
структура таблицы токенов:
id
token string(50)
user_id int()
Схема такова:
1. Юзер логинится, я генерю токены (Id от refreshToken записываю в базу) сажаю в LocalStorage JWT (accessToken и refreshToken)
2. Аутентификация запросов по accessToken до тех пор пока не истечет время.
3. После того как accessToken протух идет запрос по refreshToken на контроллер обновление токенов.
4. При обновлении, ищу по id юзера из токена в базе, если id токена из базы совпадает с id токена из запроса обновляю токены отправляю ответом (accessToken и refreshToken), если нет, то логают и редирект на страницу автрозации.
Так же на сервере есть демон, который подчищает из базы протухшие токены.
Теперь возникла потребность сделать тоже, для API мобильного приложения. Отличия только в данных передаваемых токене.
Итак вопрос. Есть ли смысл создавать отдельную таблицу для хранения токенов с мобильного приложения или сделать все в одной таблице? Добавить помимо user_id поле system_id? Или искать по токену(тогда user_id вообще не нужен)?
Это новая фишка у jwt - рефреш токены? Можно ссылку где почитать?
Не понимаю зачем хранить в базе токены? Зачем нужны вообще рефреш токены. На заре jwt все делалось намного проще, клиент с каждым запросом шлет jwt токен любым удобным для него способом, сервер смотрит что токен скоро протухнет, генерирует новый токен и отправляет назад вместе с ответом, например в том же Authorization заголовке, клиент видит новый токен и заменяет им старый. Если токен все-таки протух - логин.
Александр Антонов, ну так злоумышленник может получить и рефреш токен и пользоваться им вечно. Кейс описанный на гитхабе когда при логине старый рефреш токен становится невалидным делает невозможным пользователю быть авторизованным на двух устройствах одновременно, что в принципе бред. Вообще то что написано на гитхабе это какой-то костыль, который добавляет иллюзию повышенной безопасности, но по факту не делает ничего полезного. Токен можно банально привязывать к определенному айпи/юзерагенту и т.д. и от этого будет больше пользы.
И не стоит путать jwt с oauth, это абсолютно разные по идеологии и принципу работы технологии. Если вам нужен oauth - используйте oauth, а не тяните jwt в oauth с какими-то костылями.
Во-первых, если злоумышленник получил refreshToken он будет им пользоваться пока не зайдет реальный пользователь с данным токеном. Я в своем вопросе не расписывал всю схему но в случае, если refreshToken провалидировался (подпись валидна) и такой записи нет(перезаписался при протухании accessTokena), то находим все токены данного пользователя и удаляем.
Во-вторых прочитайте внимательней там описан случай использования залогинивание с нескольких устройств.
В-третьих логин с только с одного устройства не бреда, а вполне актуалальный кейс. Работает в платных сервисах. Чтобы с одной учётки одновременно не пользовались продуктом много пользователей.
Зачем мне городить oauth? Проблема в том, я нем могу использовать сессии и куки в запросах от мобильного приложения и в запросах от реакта.
Raccoon, так вы и так городите oauth, у вас уже есть access token, refresh token, они хранятся в базе, осталось только танцы с получением токена добавить и oauth готов) Хотя по rfc jwt там не должно быть ничего кроме одного токена, а в oauth вот это все что вы описали)
Raccoon, я когда то писал о своем виденье JWT, как раз таки в gist-е на который вы ссылаетесь. Если вы посмотрите последнюю запись, то там нет refresh токена и как мне кажется логика выстроена достаточно безопасно. Так же у вас не должно возникнуть проблем при интеграции несколько приложений/устройств
И не стоит путать jwt с oauth, это абсолютно разные по идеологии и принципу работы технологии. Если вам нужен oauth - используйте oauth, а не тяните jwt в oauth с какими-то костылями.
Alexander Leonchik, Интересная реализация. Только не ясен один момент. Если злоумышленник украл куку и начал пользоваться токеном, то и он(злоумышленник) и реальный пользователь смогут спокойно пользоваться этим токеном (если каждый запрос только увеличивает время жизни токена). Пока пользователь не заметит, что у него какая-то дичь твориться. А может и не заметит.
Цитата из гиста:
мы записываем в Redis индефикаторы refresh токенов которые заблокировал пользователь
Raccoon, пользователь может заблокировать. Вот визуально как это выглядит
Касаемо того что "украл куку", вот аналогичный алгоритм что вы видели, только сложнее (https://ibb.co/bJ32pT), но он позволяет избежать этого притом сразу как только куку украли, только не с 100% вероятностью (но мне этого не нужно было по задаче), но если хотите, напишу как нибудь )