Можно ли хранить учетные данные пользователя в JWT

Можно ли хранить учетные данные пользователя (имя пользователя / пароль) в JWT (так sign это и verify полученный токен позже)?

Я слышал что

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

но я не знаю, почему веб-сайт JWT рекомендует использовать его для целей аутентификации, тогда:

Когда следует использовать веб-токены JSON?

Вот несколько сценариев, в которых полезны веб-токены JSON:

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


person FrozenHeart    schedule 07.03.2017    source источник
comment
На веб-сайте JWT нигде не говорится, что вы можете хранить пароли в токене. Аутентификация может быть произведена другими способами, без пароля.   -  person Sergio Tulentsev    schedule 07.03.2017


Ответы (3)


JWT - это результат аутентификации. Например

  1. Пользователь отправляет свои учетные данные (например, имя пользователя / пароль) в службу аутентификации. Это может быть сторонний сервер или один внутри вашего монолита или ваши собственные микросервисы, предназначенные для аутентификации.
  2. Сервис проверяет логин-пароль. В случае успешной аутентификации он возвращает JWT, который означает, что пользователь уже аутентифицирован, другими словами, он тот, кто утверждает, что он есть. Этот JWT может содержать полезную нагрузку без конфиденциальной информации (не храните здесь пароль).
  3. Пользователь отправляет другой запрос в сервисный бизнес с JWT. Если срок действия JWT не истек и он не поврежден (знак все еще действителен), тогда служба может доверять своему JWT. Возможно, эту задачу передадут сервису авторизации.

Что находится внутри токена JWT?

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

Эту информацию можно проверить и доверять, потому что она имеет цифровую подпись.

Кроме того, JWT позволяет отправлять полезные данные.

Более формально JWT состоит из:

  • Заголовок: тип используемого токена + алгоритм хеширования
  • Полезная нагрузка: утверждения - это утверждения о сущности (обычно, о пользователе) и дополнительных метаданных.
  • Подпись: подпись используется для проверки того, что отправитель JWT является тем, кем он является, и для гарантии того, что сообщение не было изменено в процессе.

Например, если я отправлю запрос в службу проверки подлинности с моими учетными данными username: password как gabriel: giussi, он проверит эти учетные данные и, если они в порядке, может создать следующий JWT:  введите описание изображения здесь

Затем с каждым запросом я буду закодировать JWT, содержащий мое имя пользователя, и служба будет

  • Выполните авторизацию (что разрешено делать Габриэлю?), Если знак JWT действителен.
  • Попросите меня снова войти в систему, если срок действия JWT истек
  • Вернуть ошибку аутентификации, если знак сломан.
person gabrielgiussi    schedule 07.03.2017
comment
Если аутентификация прошла успешно, он возвращает JWT, который означает, что пользователь уже аутентифицирован - что это обычно? - person FrozenHeart; 07.03.2017
comment
Вы имеете в виду, что внутри JWT? Он не обязательно должен иметь полезную нагрузку, но, скорее всего, он содержит способ идентификации пользователя для выполнения задач авторизации. Сам JWT говорит, что пользователь - это тот, кем он является, имя пользователя в полезной нагрузке должно указывать, кто он. Кроме того, он может содержать все, что вы хотите (не конфиденциальное), например, контактную информацию пользователя. Но JWT должен оставаться легким, потому что он отправляется в каждом запросе. - person gabrielgiussi; 07.03.2017
comment
Правильно ли я, что результатом подписи является JWT, который совпадает с исходной полезной нагрузкой, но с подписанной? - person FrozenHeart; 07.03.2017
comment
Нет, исходной полезной нагрузкой будут учетные данные. Результатом аутентификации является JWT, который может содержать имя пользователя. - person gabrielgiussi; 07.03.2017
comment
Что обычно содержит payload часть JWT, чтобы различать пользователей? Просто username? - person FrozenHeart; 07.03.2017
comment
Что нужно хранить, чтобы идентифицировать пользователя? - Я подумал, что имени пользователя для этого должно хватить. Часть проверки будет выполнена через signature часть JWT - person FrozenHeart; 07.03.2017
comment
Если вы обратитесь к своему окончательному заключению, часть проверки будет выполнена через часть подписи JWT, вы правы. - person gabrielgiussi; 07.03.2017
comment
Таким образом, имени пользователя в payload JWT должно быть достаточно для идентификации пользователя, а части signature будет достаточно, чтобы гарантировать, что запрос действительно был отправлен этим пользователем, да? - person FrozenHeart; 07.03.2017
comment
имени пользователя в полезной нагрузке JWT должно быть достаточно для идентификации пользователя это то, о чем вы не должны спрашивать, а подтверждать, потому что это зависит от вашего варианта использования. Подпись будет достаточно, чтобы гарантировать, что JWT действителен. Создание JWT - это то, что гарантирует, что пользователь является тем, кем он говорит (иначе JWT не будет сгенерирован), не является JWT не процессом аутентификации, а его результатом. В заключение, JWT с действующей подписью и идентификатором пользователя X в своей полезной нагрузке означает, что запрос действительно был отправлен пользователем X. - person gabrielgiussi; 07.03.2017
comment
@FrozenHeart Если аутентификация прошла успешно, он возвращает JWT, который означает, что пользователь уже аутентифицирован - я увидел хорошее разъяснение того, что JWT сам по себе является учетными данными. Итак, я прочитал это следующим образом: сервер проверяет логин / пароль, в случае успеха он генерирует JWT, который сам по себе является учетными данными (хотя JWT является динамическим = изменяемым, в отличие от входа / прохода). JWT содержит все данные для проверки, кроме секретного ключа. Любой из валидаторов JWT на стороне сервера должен иметь тот же секретный ключ, который использовался для генерации JWT для проверки предоставленного JWT. - person Valentine Shi; 18.10.2020

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

person Тодор Иванов    schedule 07.03.2017
comment
Весь процесс в моем веб-приложении выглядит следующим образом: отправить имя пользователя / пароль на сервер - ›подписать их с помощью некоторого секрета -› отправить полученный токен клиенту - ›использовать этот токен для следующих запросов. Это нормально? - person FrozenHeart; 07.03.2017
comment
Да, так почему вы хотите отправлять пароль в каждом запросе? - person gabrielgiussi; 07.03.2017
comment
@gabrielgiussi не пароль, а JWT. Но JWT содержит подписанные учетные данные (имя пользователя / пароль) - person FrozenHeart; 07.03.2017
comment
Нет, JWT не содержит учетных данных. Или, лучше сказать, не должно, потому что это не нужно и представляет угрозу безопасности. - person gabrielgiussi; 07.03.2017
comment
Я имею в виду, что результатом signing является JWT, который совпадает с исходной полезной нагрузкой, но с подписью, верно? - person FrozenHeart; 07.03.2017
comment
Результатом будет новый токен jwt, который должен быть автоматически сгенерирован и не содержит никаких конфиденциальных данных. Затем вы должны использовать этот токен в своих запросах, а не имя пользователя / пароль. - person Тодор Иванов; 07.03.2017

Вкратце: да, можно передавать / получать конфиденциальные данные в JWT, если вы зашифруете данные перед помещением в полезную нагрузку JWT и расшифруете их после проверки JWT, чтобы использовать их.

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

    1.1 Однако вы можете передать что-то не такое конфиденциальное, как чистый логин / пароль, но все же содержащее ценную информацию, которая вам нужна во время проверки JWT. Это может быть идентификатор пользователя (в заявлении sub, hashed, если необходимо), или код уровня доступа и т.п.

  2. Тем не менее, если вы хотите, вы можете передать конфиденциальную информацию с помощью JWT. И все это довольно просто, как показано ниже.

    2.1 Для конфиденциальных данных вы можете использовать свои конкретные частные заявки в полезной нагрузке JWT, например:

    {
      // These are registered claims: (see https://tools.ietf.org/html/rfc7519#section-4.1)
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    
      // There can be some public claims you are not afraid to expose to the world
      // these are omitted here for brevity (see https://tools.ietf.org/html/rfc7519#section-4.2).
      "omitted": "for brevity",
    
      // And here can go some private claims you wish to include in the payload, e.g.:
      "sensitiveInfo": {
        "username": "admin",
        "password": "12345",
        "account_balance": 10000,
        "etc": "something else"
      }
    }
    

    2.2 Ключ полезной нагрузки sensitiveInfo по умолчанию закодирован только в формате base64 (поэтому он легко читается любым, кто получает JWT). Чтобы сделать его безопасным, вы можете зашифровать его с помощью какого-либо внешнего модуля (например, crypto или _ 4_ на NodeJS или методы PHP по вашему выбору).

    2.3 В этом случае:

    • At the JWT generation step you have to encrypt the key's data before you provide the entire payload to JWT generator.
    • На этапе проверки JWT после того, как JWT успешно пройдет стандартную проверку (например, jsonwebtocken jwt.verify() в Node) вы получаете декодированную полезную нагрузку с зашифрованными данными в sensitiveInfo ключе. Теперь вам просто нужно расшифровать данные и использовать их, как вы планировали.

Это оно.

person Valentine Shi    schedule 18.10.2020