JWT: обновить токен и получить доступ к хранилищу токенов

Есть много сообщений о JWT, но ни одно из них, похоже, не решило мое замешательство.

В моем текущем проекте (Next.js 14 и Postgres) я пытаюсь создать собственную аутентификацию, чтобы узнать больше о важных концепциях.

В настоящее время, когда пользователь входит в систему, токен доступа сохраняется в файлах cookie (только HTTP). У меня есть промежуточное программное обеспечение, которое проверяет достоверность этого токена, но когда этот токен недействителен или срок его действия истек, я хочу, чтобы мое промежуточное программное обеспечение вызывало API для получения нового токена доступа с токеном обновления.

Сохраняю ли я этот токен обновления в файлах cookie или его можно сохранить в моей базе данных Postgres?

Потому что, если я хочу, чтобы мое промежуточное программное обеспечение вызывало API для получения нового токена доступа, я беру токен обновления и проверяю его достоверность, а затем получаю новый токен доступа.

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

Итак, на самом деле мой вопрос: можно ли просто хранить токен обновления вместе с токеном доступа? Если нет, то как я могу реализовать логику базы данных, потому что я слышал, что токен обновления хорошо хранить на сервере.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
245
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что ваш вопрос немного неясен, что выполняется на стороне клиента, а что — на стороне сервера. Я сделаю некоторые предположения.

Прежде всего, клиент должен хранить как ваш токен доступа, так и ваш токен обновления, и оба они должны быть надежно защищены на стороне клиента. См. https://stackoverflow.com/a/76889949/2889165

У вас есть несколько различных вариантов хранения клиентской части токена обновления. Я видел следующее:

  • Сохраните его как поле токена доступа JWT. Это имеет тот недостаток, что по истечении срока действия JWT большинство библиотек будут рассматривать JWT как «плохой» и не отличать его от JWT с неправильной подписью (манипулируемой или вредоносной). Кроме того, если JWT будет украден, то же самое произойдет и с токеном обновления.
  • Сохраните токен обновления в другом файле cookie для того же домена. Недостатком этого метода является то, что он отправляется в каждом запросе, но его легко реализовать. Кроме того, если JWT украден, вполне вероятно, что токен обновления также будет украден.
  • Сохраните токен обновления в файле cookie для определенного поддомена аутентификации. Это имеет тот недостаток, что усложняет настройку.
  • Сохраните токен обновления в безопасном хранилище сеансов на клиенте. Вероятно, это лучший способ, который я видел. Я думаю, это то, что Auth0 делает за кулисами.

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

  • В первом случае токена обновления (JWT) достаточно, чтобы серверная часть приняла решение, может ли пользователь обновить токен доступа (другой JWT) или нет. Однако это не сильно отличается от обычного JWT с более длительным сроком службы, но без особого повышения безопасности.
  • Во втором случае серверная часть сравнивает токен обновления с токеном, хранящимся на внутренней стороне (в вашем случае, возможно, в базе данных Postgres. Если есть совпадение, JWT можно обновить. Преимущество этого метода заключается в том, что вы можете:
    • Удалите токен обновления на стороне сервера, если пользователь выходит из системы, меняет пароль, серверная часть обнаруживает какое-либо вредоносное поведение и т. д.
    • Убедитесь, что JWT можно обновить только один раз, чтобы, если злоумышленник украл копию JWT, сеанс пользователя не продолжился, не заметив, что JWT был украден. Только конечный пользователь или хакер сможет продлить JWT. Если есть второй запрос на продление того же JWT (с использованием старого токена обновления), вы можете полностью удалить токен обновления, не позволяя никому повторно продлевать свой JWT. Вы не обнаружили подозрительную активность и заставите пользователя снова войти в систему.

Извините, что мой вопрос был немного неясен, но да, вы ответили на мой вопрос! Я пошел по пути хранения токена обновления в файле cookie только для http, но зашифровал его перед сохранением. А для аннулирования токенов обновления я использую Redis. Я посмотрю на хранилище сеансов.

manny_paz 22.05.2024 16:12

@manny_paz не стесняйтесь проголосовать и принять ответ. Существует стандарт шифрования JWT, но мы чаще всего только его подписываем. Шифрование токена просто дает вам еще один токен...

Andreas Lundgren 23.05.2024 20:30

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

manny_paz 23.05.2024 20:44

Если вы не храните в JWT что-либо секретное (и я не знаю ни одного случая, когда вам следует это делать), добавление такого типа «запутывания» считается плохой практикой, потому что либо у вас есть что-то водонепроницаемое внизу и оно вам не нужно, или он не водонепроницаем и тогда это не поможет. Кроме того, это не позволяет вам управлять графическим интерфейсом клиента на основе состояния пользователя.

Andreas Lundgren 24.05.2024 22:55

В этом есть смысл. Я думаю, не существует «идеального» способа хранения токена JWT? Я слышал, что это можно сделать несколькими способами: в памяти, локальном хранилище или файлах cookie. Но для каждого есть компромисс. Я хотел, чтобы мой сервер аутентификации оставался без сохранения состояния и не имел никаких сведений о сервере ресурсов. Поэтому сохранение обновления в базе данных было невозможным. Кроме того, аннулирование всех токенов обновления в случае взлома обойдется дорого. Единственная причина, по которой я подумал, что шифрование токена обновления было бы хорошей идеей, заключалась в том, что все запросы будут отправляться с доступом и обновлением с использованием метода cookie. Но конфиденциальной информации нет.

manny_paz 28.05.2024 16:43

Если произойдет нарушение, вы поменяете закрытый ключ подписи JWT, что немедленно сделает недействительными все JWT, не дожидаясь следующего обновления. А токен обновления — это просто случайная строка, и его шифрование просто создаст новую случайную строку, верно?

Andreas Lundgren 29.05.2024 17:22

Ого... Я никогда об этом не думал. Но означает ли это, что я не могу просто хранить свой закрытый ключ подписи в файле env, но мне он понадобится в переменных env, например, в менеджере секретов aws? Для этого созданы эти системы? Поскольку этот проект является локальным, я просто храню ключ подписи в файле .env.local сервера аутентификации и в файле .env.local сервера ресурсов. И да, токен обновления становится новой случайной строкой.

manny_paz 29.05.2024 18:01

Нет, мы приступаем к операции. :-) Вы определенно можете хранить ключ в файле на вашем сервере (хотя если у вас есть перерыв, его будет легче найти, чем просто хранить его в памяти). Секретные менеджеры действительно пригодятся, когда у вас нет статического сервера, но вы можете запускать лямбда-функции, контейнеры в Kubernetes и т. д. Также, если у вас 200 разработчиков, тогда только немногие должны иметь доступ к ключу в виде обычного текста.

Andreas Lundgren 01.06.2024 16:41

Проведите анализ рисков. Что произойдет, если клиент будет взломан и JWT украден? (обнаружение, если токен обновления используется дважды или JWT используется с другого IP-адреса и т. д.) Что произойдет, если мой сервер будет скомпрометирован? Сегментирована ли моя сеть или игра со вторжением окончена на всех уровнях? Если вы считаете, что ваш ключ подписи был украден, вам необходимо сдать его на переработку после того, как вы исправите точку входа и избавитесь от всех бэкдоров.

Andreas Lundgren 01.06.2024 16:41

Попался, имеет смысл. Я в основном думал поверхностно, а не об анализе рисков, но это помогает.

manny_paz 04.06.2024 21:44

Другие вопросы по теме