Обзор правил для JWS и JWT

Вы просматриваете документацию по Apigee Edge.
Перейдите к документации по Apigee X.
Информация

В этом разделе приведена общая информация о JWT (веб-токене JSON) и JWS (веб-подписи JSON), а также о правилах JWS/JWT Apigee, которые могут быть полезны разработчикам прокси Apigee.

Введение

И JWS, и JWT часто используются для передачи утверждений между подключенными приложениями. Правила JWS/JWT позволяют прокси-серверам Edge API:

  • Сгенерируйте подписанный JWT или JWS.
  • Проверка подписанного JWT или JWS и утверждений в JWS/JWT.
  • Декодирование подписанного JWT или JWS без проверки подписи.

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

При использовании правила Verify JWS/JWT (Проверка JWS/JWT) недействительный JWS/JWT будет отклонен и приведет к ошибке. Аналогично, при использовании правила Decode JWS/JWT (Декодировать JWS/JWT) некорректный JWS/JWT приведет к ошибке.

Видео

Посмотрите короткое видео, чтобы быстро ознакомиться с JWT. Хотя в этом видео рассказывается о создании JWT, многие принципы применимы и к JWS.

Посмотрите короткое видео о структуре JWT.

Примеры использования

Правила JWS/JWT позволяют:

  • Создание нового JWS/JWT на стороне прокси или целевой конечной точки прокси-сервера Edge. Например, вы можете создать поток запросов прокси, который генерирует JWS/JWT и возвращает его клиенту. Или вы можете создать прокси-сервер, который будет генерировать JWS/JWT в целевом потоке запросов и прикреплять его к запросу, отправляемому в целевую службу. Затем эти утверждения можно использовать для того, чтобы разрешить серверным сервисам применять дополнительные меры безопасности.
  • Проверяйте и извлекайте утверждения из JWS/JWT, полученных из входящих клиентских запросов, ответов целевого сервиса, ответов правил вызова сервиса или других источников. Edge проверяет подпись в JWS/JWT, независимо от того, был ли этот объект создан сторонним сервисом или самим Edge, с помощью алгоритмов RSA или HMAC.
  • Декодирование JWS/JWT. Декодирование наиболее полезно при использовании вместе с правилом "Проверить JWS/JWT", когда значение утверждения (JWT) или заголовка (JWS/JWT) из JWS/JWT должно быть известно до проверки JWS/JWT.

Части JWS/JWT

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

header.payload.signature
  • Правило Generate JWS/JWT создает все три части.
  • Правило Verify JWS/JWT проверяет все три части.
  • Правило "Декодировать JWS/JWT" проверяет только заголовок и полезную нагрузку.

JWS также поддерживает отделенный формат, в котором полезная нагрузка отсутствует в JWS:

header..signature

При использовании отделенной подписи JWS полезная нагрузка отправляется отдельно от JWS. Вы используете элемент <DetachedContent> правила Verify JWS, чтобы указать необработанную полезную нагрузку JWS без кодировки. Затем правило Verify JWS проверяет JWS, используя заголовок и подпись в JWS и полезную нагрузку, указанную элементом <DetachedContent>.

Чтобы узнать больше о токенах, а также о том, как они кодируются и подписываются, ознакомьтесь со следующими статьями:

Различия между JWS и JWT

Для передачи утверждений между подключенными приложениями можно использовать JWT или JWS. Основное различие между ними заключается в представлении полезной нагрузки:

  • JWT
    • Полезная нагрузка всегда представляет собой объект JSON.
    • Полезная нагрузка всегда прикрепляется к JWT.
    • Заголовок typ токена всегда имеет значение JWT.
  • JWS
    • Полезная нагрузка может быть представлена в любом формате, например в виде объекта JSON, потока байтов, потока октетов и т. д.
    • Полезная нагрузка не обязательно должна быть прикреплена к JWS.

Поскольку в формате JWT для представления полезной нагрузки всегда используется объект JSON, встроенная поддержка распространенных зарегистрированных имен утверждений, таких как aud, iss, sub и других, реализована в политиках Edge Generate JWT и Verify JWT. Это означает, что вы можете использовать элементы правила Generate JWT, чтобы задать эти утверждения в полезной нагрузке, и элементы правила Verify JWT, чтобы проверить их значения. Подробнее о зарегистрированных именах утверждений можно узнать в разделе Registered Claim Names спецификации JWT.

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

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

Как предотвратить внедрение шаблона при использовании JWS и JWT

Чтобы предотвратить несанкционированное раскрытие данных, следуйте приведенным ниже рекомендациям при использовании правил GenerateJWT или GenerateJWS:

  • Избегайте прямых ссылок на ввод данных пользователем. Никогда не используйте ненадежные входные данные (например, request.queryparam.* или request.header.*) напрямую в атрибуте ref, поддерживающем шаблоны.
  • Очистка входных данных. Если вам нужно использовать внешние данные в утверждении JWT/JWS, сначала примените правило AssignMessage, чтобы удалить из входных данных все фигурные скобки ({ }) и другие символы шаблонов, прежде чем ссылаться на них.
  • Используйте явные утверждения для строк. Для простых строковых утверждений избегайте type="map". Использование значения по умолчанию type="string" предотвращает неявное создание шаблона для указанного значения.
  • Обратите внимание на поведенческое несоответствие между правилами проверки и создания. Правила создания JWS и JWT ведут себя иначе, чем правила проверки, в отношении шаблонов.

Алгоритмы подписи

Правила проверки и создания JWS/JWT поддерживают алгоритмы RSA, RSASSA-PSS, ECDSA и HMAC с использованием контрольных сумм SHA2 длиной 256, 384 или 512 бит. Правило декодирования JWS/JWT работает независимо от алгоритма, который использовался для подписи JWS/JWT.

Алгоритм HMAC

Алгоритм HMAC основан на общем секрете, известном как секретный ключ, который используется для создания подписи (также известной как подпись JWS/JWT) и ее проверки.

Минимальная длина секретного ключа зависит от стойкости алгоритма:

  • HS256: минимальная длина ключа – 32 байта.
  • HS386: минимальная длина ключа – 48 байт
  • HS512: минимальная длина ключа – 64 байта.

алгоритм RSA

В алгоритме RSA для криптографической подписи используется пара открытого и закрытого ключей. При использовании подписей RSA сторона, подписывающая JWS/JWT, использует закрытый ключ RSA, а сторона, проверяющая подпись, – соответствующий открытый ключ RSA. Требования к размеру ключей отсутствуют.

Алгоритм RSASSA-PSS

Алгоритм RSASSA-PSS – это обновленная версия алгоритма RSA. Как и RSS, RSASSA-PSS использует для криптографической подписи пару открытого и закрытого ключей RSA. Формат ключа такой же, как и для RSS. Сторона, подписывающая JWS/JWT, использует закрытый ключ, а сторона, проверяющая подпись, – соответствующий открытый ключ. Требований к размеру ключей нет.

Алгоритм ECDSA

Алгоритм цифровой подписи на основе эллиптических кривых (ECDSA) – это алгоритм криптографии на эллиптических кривых с кривой P-256, P-384 и P-521. При использовании алгоритмов ECDSA тип открытого и закрытого ключей определяется алгоритмом:

Алгоритм Кривая Ключевое требование
ES256 P-256 Ключ, сгенерированный на основе кривой P-256 (также известной как secp256r1 или prime256v1).
ES384 P-384 Ключ, сгенерированный на основе кривой P-384 (также известной как secp384r1)
ES512 P-521 Ключ, сгенерированный на основе кривой P-521 (также известной как secp521r1).

Алгоритмы шифрования ключей

Правила JWS/JWT поддерживают все алгоритмы шифрования ключей, которые поддерживает OpenSSL.

Как использовать набор веб-ключей JSON (JWKS) для проверки JWS/JWT

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

  • использовать фактическое значение открытого ключа (обычно предоставляется в переменной потока);
  • использовать открытый ключ, обернутый в JWKS.

О JWKS

JWKS – это структура JSON, представляющая набор веб-ключей JSON (JWK). JWK – это структура данных JSON, которая представляет криптографический ключ. Форматы JWK и JWKS описаны в документе RFC7517. Примеры использования JKWS приведены в Приложении А. Примеры наборов ключей JSON

Структура JWKS

В RFC7517 описаны ключевые элементы JWKS для каждого типа ключа, например "RSA" или "EC". Например, в зависимости от типа ключа эти параметры могут включать:

  • kty – тип ключа, например "RSA" или "EC".
  • kid (идентификатор ключа) – может быть любым произвольным значением (без дубликатов в наборе ключей). Если входящий токен JWT содержит идентификатор ключа, который есть в наборе JWKS, то правило будет использовать правильный открытый ключ для проверки подписи JWS/JWT.

Ниже приведены примеры необязательных элементов и их значений:

  • alg – алгоритм ключа. Он должен совпадать с алгоритмом подписи в JWS/JWT.
  • use – если присутствует, должно иметь значение sig.

Ниже приведен пример JWKS с необходимыми элементами и значениями, который будет действителен в Edge (из https://www.googleapis.com/oauth2/v3/certs):

{
   "keys":[
      {
         "kty":"RSA",
         "alg":"RS256",
         "use":"sig",
         "kid":"ca04df587b5a7cead80abee9ea8dcf7586a78e01",
         "n":"iXn-WmrwLLBa-QDiToBozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt7-V7KDjCq0_Nkd-X9rMRV5LKgCa0_F8YgI30QS3bUm9orFryrdOc65PUIVFVxIwMZuGDY1hj6HEJVWIr0CZdcgNIll06BasclckkUK4O-Eh7MaQrqb646ghFlG3zlgk9b2duHbDOq3s39ICPinRQWC6NqTYfqg7E8GN_NLY9srUCc_MswuUfMJ2cKT6edrhLuIwIj_74YGkpOwilr2VswKsvJ7dcoiJxheKYvKDKtZFkbKrWETTJSGX2Xeh0DFB0lqbKLVvqkM2lFU2Qx1OgtTnrw",
         "e":"AQAB"
      },
      {
          "kty":"EC",
          "alg":"ES256",
          "use":"enc",
          "kid":"k05TUSt7-V7KDjCq0_N"
          "crv":"P-256",
          "x":"Xej56MungXuFZwmk_xccvsMpCtXmqhvEEMCmHyAmKF0",
          "y":"Bozpu4Y4ThKdwORWFXQa9I75pKOvPUjUjE2Bk05TUSt",
      }
   ]
}

Как настроить прокси-сервер для использования JWKS

Когда издатель получает JWS/JWT, он часто вставляет в заголовок JWS/JWT идентификатор ключа (kid). Ключ указывает получателю JWS/JWT, как найти открытый или секретный ключ, необходимый для проверки подписи в подписанном JWS/JWT.

Предположим, что эмитент подписывает JWT с помощью закрытого ключа. "Идентификатор ключа" определяет соответствующий открытый ключ, который используется для проверки JWT. Список открытых ключей обычно доступен в известной конечной точке, например https://www.googleapis.com/oauth2/v3/certs.

Ниже описана основная последовательность действий, которые Edge (или любая платформа, работающая с JWKS) должна выполнить, чтобы работать с JWS/JWT, у которого есть JWKS:

  1. Проверьте заголовок JWS/JWT, чтобы найти идентификатор ключа (kid).
  2. Проверьте заголовок JWS/JWT, чтобы найти алгоритм подписи (alg), например RS256.
  3. Получите список ключей и идентификаторов из JWKS известной конечной точки для определенного издателя.
  4. Извлеките открытый ключ из списка ключей с идентификатором, указанным в заголовке JWS/JWT, и с соответствующим алгоритмом, если он указан в ключе JWKS.
  5. Используйте этот открытый ключ, чтобы проверить подпись в JWS/JWT.

Чтобы выполнить проверку JWS/JWT, разработчику прокси-сервера API Edge необходимо сделать следующее:

  1. Получите список ключей и идентификаторов из известной конечной точки для определенного издателя. На этом этапе можно использовать правило вызова сервиса.
  2. В правиле Verify JWS/JWT укажите местоположение JWS/JWT в элементе <Source> и полезную нагрузку JWKS в элементе <PublicKey/JWKS>. Например, для правила VerifyJWT:
    <VerifyJWT name="JWT-Verify-RS256">
        <Algorithm>RS256</Algorithm>
        <Source>json.jwt</Source>
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
        <PublicKey>
            <JWKS ref="public.jwks"/>
        </PublicKey>
        <Subject>apigee-seattle-hatrack-montage</Subject>
        <Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
        <Audience>urn://c60511c0-12a2-473c-80fd-42528eb65a6a</Audience>
        <AdditionalClaims>
            <Claim name="show">And now for something completely different.</Claim>
        </AdditionalClaims>
    </VerifyJWT>

Правило Verify JWT выполняет все остальные действия:

  • Если ключ с идентификатором, совпадающим с идентификатором ключа (kid), указанным в JWT, не найден в JWKS, правило Verify JWT выдает ошибку и не проверяет JWT.
  • Если входящий токен JWT не содержит идентификатор ключа (kid) в заголовке, то сопоставление keyid-to-verification-key невозможно.

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