Является ли токен обновления действительно необходимым при использовании аутентификации маркера JWT?

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

Автоматическое продление срока действия JWT (JSON Web Token)

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

введите описание изображения здесь

Я понимаю аутентификацию маркера JWT, но я немного смущен тем, как использовать токены обновления.

Я хочу, чтобы моя JWT-аутентификация имела следующие свойства:

  • Значок JWT имеет срок действия 2 часа.

  • Токен обновляется каждые один час клиентом.

  • Если токен пользователя не обновляется (пользователь неактивен и приложение не открыто) и истекает, им необходимо будет войти в систему, когда захотят возобновить работу.

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

Мои вопросы таковы:

  • Если бы я использовал токен обновления, не было бы еще полезно иметь долгосрочное окончание срока для хорошей практики на этом токене?
  • Если мне нужно использовать токен обновления, будет ли этот токен сохранен с помощью токена userId и/или JWT?
  • Когда я обновляю свой токен каждые 1 час, как это работает? Я хочу создать конечную точку, которая принимает мой токен JWT или токен обновления? Будет ли это обновлять дату истечения срока действия моего оригинального токена JWT или создать новый токен?
  • Есть ли необходимость в токере обновления, учитывая эти данные? Кажется, что если пользователь просто использует токен JWT для захвата нового токена (по ссылке выше), токен обновления устарел.

Ответ 1

Позвольте мне подойти к вашим вопросам чуть позже по линии и начать с обсуждения на самом деле цели токена обновления.

Итак, ситуация такова:

Пользователь открывает приложение и предоставляет свои учетные данные. Теперь, скорее всего, приложение взаимодействует с бэкэнд-сервером REST. REST, являющийся апатридом, на самом деле не существует способа авторизации доступа к API. Следовательно, пока в обсуждении нет способа проверить, действительно ли авторизованный пользователь фактически обращается к API, или это просто некоторые случайные запросы.

Теперь, чтобы решить эту проблему, нам нужен способ узнать, что запросы поступают от авторизованного пользователя. Итак, что мы сделали, это ввести что-то, называемое токеном доступа. Итак, теперь, как только пользователь успешно аутентифицирован, ему выдают токен доступа. Этот токен должен быть длинным и очень случайным токеном (чтобы не догадаться). Здесь JWT входит в картину. Теперь вы можете/не захотите хранить какие-либо детали, специфичные для пользователя, в токере JWT. В идеале вы хотели бы просто хранить очень простые, крайне нечувствительные детали в JWT. Обработка JWT-хэша для получения других деталей пользователя (IDOR и т.д.) Выполняется JWT (самой используемой библиотекой).

Итак, на данный момент решена наша проблема авторизованного доступа.

Теперь мы говорим о сценарии атаки. Скажем, используя все вышеперечисленного пользователя, Алиса, используя приложение, имеет авторизованный токен доступа, и теперь ее приложение может отправлять запросы ко всем API-интерфейсам и получать данные в соответствии с ее авторизацией.

Предположим, что SOMEHOW Алиса теряет токен доступа или использует другой способ, противник, Боб, получает доступ к токену доступа Алисы. Теперь Боб, несмотря на то, что он несанкционирован, действительно может делать запросы ко всем API, которым была разрешена Алиса.

ЧТО-ТО МЫ ИДЕАЛЬНО НЕ ХОТЯТ.

Теперь решение этой проблемы:

  • Определите, что происходит что-то подобное.
  • Уменьшить само окно атаки.

Используя только токен доступа, трудно достичь условия 1 выше, потому что, будь то Алиса или Боб, он использует тот же самый разрешенный токен, и поэтому запросы от двух пользователей не различимы.

Итак, мы пытаемся достичь 2 выше и, следовательно, добавляем истечение срока действия токена доступа, скажем, токен доступа действителен для времени "t" (короткое время).

Как это помогает? Ну, даже если у Боба есть токен доступа, он может использовать его только до тех пор, пока он не будет действителен. Как только он истечет, ему придется снова получить его. Теперь, конечно, вы могли бы сказать, что он может получить его так же, как и в первый раз. Но опять же нет ничего подобного 100% безопасности!

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

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

Теперь вы можете спросить, у Боба также есть доступ к токену обновления, аналогично тому, как он скомпрометировал токен доступа. ДА. Он может. Однако теперь становится легко идентифицировать такую ​​частоту, что было невозможно в случае одного токена доступа, и принять необходимые меры для уменьшения нанесенного ущерба.

Как?

Для каждого пользователя, прошедшего проверку подлинности (в случае мобильного приложения, как правило), один экземпляр обновленного токена обновления и пара токен доступа предоставляется приложению. Поэтому в любой момент времени для одного аутентифицированного пользователя будет только один токен доступа, соответствующий токере обновления. Теперь предположим, что если Боб скомпрометировал токен обновления, он будет использовать его для создания токена доступа (поскольку токен доступа - это единственное, что разрешено для доступа к ресурсам через API). Как только Bob (атакующий) делает запрос с вновь созданным токеном доступа, поскольку токен доступа Alice (подлинный пользователь) все еще действителен, сервер увидит это как аномалию, потому что для одного токена обновления может быть только один разрешенный токен доступа одновременно. Выявив аномалию, сервер уничтожит токен обновления, о котором идет речь, и вместе с ним все связанные с ним токены доступа также будут признаны недействительными. Таким образом, предотвращая любой доступ, подлинный или злонамеренный, к любому разрешению, требующему ресурсов. Пользователь, Алиса, должен будет снова аутентифицировать свои учетные данные и получить действительную пару токенов обновления и доступа.

Конечно, вы все же можете утверждать, что Боб мог снова получить доступ к токенам обновления и доступа и повторить всю историю выше, что потенциально может привести к DoS on Alice, фактическому подлинному клиенту, но опять же нет ничего, как 100 % безопасность.

Также как хорошая практика, токен обновления должен также иметь истечение, хотя и довольно длинный.

Ответ 2

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

Вот как это работает:

  • Когда ваш пользователь регистрируется с учетными данными (имя пользователя/пароль), вы возвращаете недолговечный JWT. Вы также создаете запись db, в которой вы храните:

    • JWT id
    • идентификатор пользователя
    • IP-адрес
    • Пользовательский агент
    • a valid флаг (по умолчанию TRUE)
    • createdAt
    • updatedAt
  • Ваш клиент отправляет JWT по каждому запросу. Пока JWT не истек, он имеет доступ к ресурсам. Если JWT истек, вы обновите его за кулисами и возвращает как ресурс, так и дополнительный заголовок X-JWT с новым JWT.

  • Когда клиент получает ответ с заголовком X-JWT, он отбрасывает старый JWT и использует новый для будущих запросов.

Как обновление JWT работает на сервере

  • Посмотрите на соответствующую запись db с помощью JWT-идентификатора.
  • Убедитесь, что флаг valid по-прежнему верен, в противном случае отклоняется.
  • При желании вы можете сравнить IP-адрес запроса и пользовательский агент с сохраненный IP-адрес и пользовательский агент, и принять решение отклонить, если что-то выглядит тусклый.
  • Необязательно, вы можете проверить записи db records createdAt или updatedAt и решите не обновляться, если прошло слишком много времени.
  • Обновите поле updatedAt в записи db.
  • Возвращает новый JWT (который в основном является копией JWT с истекшим сроком действия, но с расширенным сроком действия).

Эта конструкция также даст вам возможность отозвать все токены для пользователя (для например, если пользователь теряет свой телефон или обновляет свой пароль).

Преимущества:

  • Ваш клиент никогда не должен проверять время истечения срока действия или сделать токен обновления запросов, все, что он делает, это проверка заголовка X-JWT на ответы.
  • Вы можете добавить пользовательскую логику обновления на основе IP-адреса, пользовательского агента, max-token возраста или их комбинации.
  • Вы можете отменить некоторые или все токены для пользователя.