Как мне обращаться с аутентификацией RESTful при использовании токенов JWT? - PullRequest
1 голос
/ 09 апреля 2019

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

Это поток, который, я думаю, до сих пор нормален:

  1. Пользователь заполняет форму, используя электронную почту и пароль, и отправляет ее.
  2. Сервер проверяет пароль, если он совпадает, и отвечает с помощью файла cookie httponly с подписанным токеном jwt, срок действия которого истекает примерно через 10 минут.(Я знаю, что должен защитить его от атак csrf)
  3. Пользователь входит в систему, и при каждом новом запросе к серверу он автоматически отправляет файл cookie в заголовке, а сервер проверяет токен.

Все хорошо, но я столкнулся с некоторыми проблемами и у меня возникли некоторые вопросы:

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

Что должно произойти, если срок действия токена истек?

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

На новый запрос, когда маркер доступа истек, пользователь отправит куки-обновление на сервер, еслион соответствует токену обновления базы данных пользователя, сервер ответит отдельным файлом cookie, который обновит токен доступа?

Если есть токен обновления, где его хранить и в каком формате?(cookie, база данных или где?)

Должен ли я держать пользователя вошедшим в систему на основе этого файла cookie обновления маркера? Если это httponly, я не могу его прочитать и установить состояние, в которое вошел пользователь. Как следуетЯ делаю это?

Я слышал о том, что отзыв токена jwt проблематичен.Как бы вы это исправить?

Как бы вы все это сделали? Пожалуйста, объясните рабочий процесс, я стараюсь избегать локального хранения, так как я читаю везде, что небезопасно для конфиденциальных данных.

1 Ответ

0 голосов
/ 10 апреля 2019

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

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

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

Я бы не стал беспокоиться об отзыве JWT, а вместо этого просто позволил бы им истечь, если они это сделают, и инициировал новый поток входа в систему, если обнаружится, что JWT истек. Кроме того, вместо использования локального хранилища я бы предложил использовать хранилище сеансов для хранения вашего JWT, чтобы оно оставалось на время сеанса вашего пользователя на веб-сайте, и оно будет удалено, как только браузер будет закрыт. Это предотвратит сохранение JWT после сеанса и уменьшит ваши опасения по поводу сохранения конфиденциальных данных в хранилище сеанса. Кроме того, при создании вашего JWT вы также должны избегать хранения в нем конфиденциальных данных, поскольку JWT легко реверсивно проектируется. Это также может предотвратить раскрытие любых конфиденциальных данных на клиенте.

EDIT:

Главное, что нужно помнить при разработке серверного API, - это то, что у вас должно быть два разных класса конечных точек. Один набор должен быть не аутентифицирован, а один набор должен быть аутентифицирован.

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

Набор конечных точек без проверки подлинности потребовал бы, чтобы токен доступа был включен в запрос, и если токен доступа илиобнаружен неверный токен доступа, конечная точка ответит с помощью 401 HTTP-кода ответа (указывающего на несанкционированный запрос).Примером этого класса конечной точки может быть конечная точка, которая позволяет пользователю обновлять свою личную информацию.Очевидно, что пользователь не может обновить свою собственную информацию, если он не может предоставить учетные данные, чтобы доказать, что он является пользователем, чью информацию он пытается обновить.Если клиент получает ответ с кодом ответа 401, это будет сигнал, который понадобится клиенту, чтобы сообщить пользователю о необходимости повторного входа в систему, чтобы можно было получить новый действительный токен доступа.Этой возможности можно избежать на клиенте, если клиент запрограммирован на периодическую проверку истечения срока действия JWT, который в данный момент удерживается на клиенте, и инициирование обновления маркера доступа, но, очевидно, у вас все еще должна быть логика для обнаружения и ответа на него.код ответа 401, чтобы клиентский пользовательский поток управлялся должным образом.

...