Übersicht über JWS- und JWT-Richtlinien

Diese Seite gilt für Apigee und Apigee Hybrid.

Apigee Edge-Dokumentation aufrufen

Dieses Thema enthält allgemeine Informationen zu JWT (JSON Web Token) und JWS (JSON Web Signature) und den Apigee JWS/JWT-Richtlinien, die für Apigee-Proxy-Entwickler von Interesse sein können.

Einführung

Sowohl JWS als auch JWT werden häufig verwendet, um Ansprüche oder Assertions zwischen verbundenen Anwendungen auszutauschen. Die JWS/JWT-Richtlinien ermöglichen Apigee API-Proxys Folgendes:

In den beiden letzteren Fällen legt die Richtlinie auch Ablaufvariablen fest. So können nachfolgende Richtlinien im Apigee-Ablauf die Ansprüche im JWT oder JWS prüfen und Entscheidungen basierend auf diesen Ansprüchen treffen oder diese Informationen an die Back-End-Dienste weitergeben.

Bei Verwendung der VerifyJWS- oder VerifyJWT-Richtlinien wird eine ungültige JWS/JWT abgelehnt, die zu einer Fehlerbedingung führt. Entsprechend führt die Verwendung der DecodeJWS- oder DecodeJWT-Richtlinien zu einer fehlerhaften JWS/JWT-Datei, die zu einer Fehlerbedingung führt.

Videos

In einem kurzen Video finden Sie eine schnelle Einführung in JWT. Obwohl dieses Video speziell für die Generierung eines JWT gedacht ist, sind viele der Konzepte für JWS identisch.

In diesem kurzen Video erfahren Sie mehr über die JWT-Struktur.

Anwendungsfälle

Sie können die JWS/JWT-Richtlinien für Folgendes verwenden:

  • Generieren Sie ein neues JWS/JWT auf den Proxy- oder Zielendpunktseiten eines Apigee-Proxys. Sie können beispielsweise einen Proxy-Anfragefluss erstellen, der ein JWS/JWT generiert und an einen Client zurückgibt. Sie haben auch die Möglichkeit, einen Proxy so zu erstellen, dass er ein JWS/JWT im Zielanforderungsablauf generiert und ihn an die an das Ziel gesendete Anfrage anpasst. Das JWS/JWT und seine Ansprüche wären dann verfügbar, damit Back-End-Dienste die weitere Sicherheitsverarbeitung anwenden können.
  • Prüfen und extrahieren Sie Anforderungen aus einem JWS/JWT, die Sie von eingehenden Clientanfragen, von Zieldienstantworten, von Service-Callout-Richtlinienantworten oder aus anderen Quellen erhalten haben. Bei einem signierten JWS/JWT verwendet Apigee einen der RSA-, ECDSA- oder HMAC-Algorithmen, um die Signatur zu überprüfen, unabhängig davon, ob das JWS/JWT von Apigee oder einem Drittanbieter generiert wurde. Bei einem verschlüsselten JWT entschlüsselt Apigee das JWT mit einem der unterstützten JWA-Verschlüsselungsalgorithmen (siehe IETF RFC 7518).
  • JWS/JWT decodieren Die Dekodierung ist am nützlichsten, wenn sie zusammen mit der Richtlinie Verify JWS/JWT verwendet wird, und zwar in Fällen, in denen der Wert einer Anforderung (JWT) oder eines Headers (JWS/JWT) innerhalb des JWS/JWT bekannt sein muss, bevor ein signiertes JWS/JWT verifiziert oder ein verschlüsseltes JWT entschlüsselt wird.

Bestandteile eines JWS/JWT

Eine signierte JWS/JWT kodiert Informationen in drei durch Punkte getrennten Teilen:

Header.Payload.Signature
  • Die Richtlinie "JWS/JWT generieren" erstellt alle drei Teile.
  • Die JWS/JWT-Richtlinie prüft alle drei Teile.
  • Die DecodeJWS-Richtlinie prüft nur den Header. Die DecodeJWT-Richtlinie prüft nur den Header und die Nutzlast.

Ein JWS unterstützt auch eine getrennte Form, bei der die Nutzlast vom JWS weggelassen wird:

Header..Signature

Bei einem getrennten JWS wird die Nutzlast getrennt vom JWS gesendet. Verwenden Sie das Element <DetachedContent> der JWS-Richtlinie, um die nicht codierte, unverschlüsselte JWS-Nutzlast anzugeben. Die JWS-Richtlinie überprüft dann die JWS mithilfe des Headers und der Signatur in der JWS und der durch das Element <DetachedContent> angegebenen Nutzlast.

Ein verschlüsseltes JWT codiert Informationen in fünf durch Punkte getrennten Teilen:

Header.Key.InitializationVector.Payload.AuthenticationTag

Die Richtlinien GenerateJWT und VerifyJWT erstellen oder prüfen alle diese Teile. Die DecodeJWT-Richtlinie kann nur den nicht verschlüsselten Header untersuchen.

Weitere Informationen zu Tokens und dazu, wie sie codiert und signiert oder verschlüsselt werden, finden Sie in den entsprechenden Standarddokumenten:

Unterschiede zwischen JWS und JWT

Sie können entweder ein JWT oder JWS verwenden, um Anforderungen oder Assertions für verbundene Anwendungen zu teilen. Der Hauptunterschied zwischen den beiden Funktionen ist die Darstellung der Nutzlast:

  • JWT
    • Die Nutzlast ist immer ein JSON-Objekt.
    • Die Nutzlast wird immer mit dem JWT verknüpft.
    • Der Header typ des Tokens ist immer auf JWT gesetzt.
    • Die Nutzlast kann signiert oder verschlüsselt sein.
  • JWS
    • Die Nutzlast kann durch ein beliebiges Format dargestellt werden, z. B. ein JSON-Objekt, einen Byte-Stream oder einen Oktett-Stream.
    • Die Nutzlast muss nicht an das JWS angehängt werden.
    • Header und Nutzlast werden immer signiert. JWS unterstützt keine Verschlüsselung.

Da das JWT-Format immer ein JSON-Objekt zur Darstellung der Nutzlast verwendet, haben die Apigee-Richtlinien GenerateJWT und VerifyJWT eine integrierte Unterstützung für die Verarbeitung gängiger registrierter Anforderungsnamen, wie aud, iss, sub und andere. Dies bedeutet, dass Sie Elemente der Richtlinie GenerateJWT verwenden können, um diese Ansprüche in der Nutzlast festzulegen, und Elemente der Richtlinie VerifyJWT, um ihre Werte zu überprüfen. Weitere Informationen finden Sie im Abschnitt Registrierte Anforderungsnamen der JWT-Spezifikation.

Neben der Unterstützung bestimmter registrierter Anforderungsnamen unterstützt die GenerateJWT-Richtlinie direkt das Hinzufügen von Anforderungen mit beliebigen Namen zur Nutzlast oder dem Header des JWT. Jede Anforderung ist ein einfaches Name/Wert-Paar, bei dem der Wert vom Typ number, boolean, string, map oder array sein kann.

Wenn Sie GenerateJWS verwenden, geben Sie eine Kontextvariable an, die die Nutzlast darstellt. Da eine JWS eine beliebige Datendarstellung für die Nutzlast verwenden kann, gibt es in einer JWS kein Konzept für „Nutzlastanspruch“. Die GenerateJWS-Richtlinie unterstützt das Hinzufügen von Ansprüchen mit beliebigen Namen zur Nutzlast nicht. Mit der GenerateJWS-Richtlinie können Sie dem Header der JWS Ansprüche mit beliebigen Namen hinzufügen. Außerdem unterstützen die JWS-Richtlinien eine getrennte Nutzlast, wobei die JWS die Nutzlast weglässt. Mit einer getrennten Nutzlast können Sie die JWS und die Nutzlast separat senden. Die Verwendung einer getrennten Nutzlast kann insbesondere bei großen Nutzlasten speichereffizienter sein und ist für mehrere Sicherheitsstandards erforderlich.

Signieren und Verschlüsseln

Apigee kann signierte oder verschlüsselte JWTs generieren. Wählen Sie ein signiertes JWT aus, wenn die Nutzlast nicht geheim sein muss, es aber wichtig ist, den Lesern Integrität und Verbindlichkeit zu garantieren. Ein signiertes JWT gibt Lesern die Sicherheit, dass die Nutzlast seit der Signierung des JWT nicht geändert wurde und dass das JWT vom Inhaber des privaten Schlüssels signiert wurde. Wählen Sie ein verschlüsseltes JWT aus, wenn die Nutzlast vertraulich sein soll. Ein verschlüsseltes JWT bietet Vertraulichkeit für die Nutzlast, da nur der entsprechende Schlüsselinhaber sie entschlüsseln kann.

Es ist möglich, sowohl verschlüsselte als auch signierte JWTs zusammen zu verwenden, insbesondere wenn das verschlüsselte JWT einen asymmetrischen Kryptografiealgorithmus (RSA, ECDSA) verwendet. In diesem Fall kann die Identität des Erstellers dieses JWT nicht ermittelt werden, da der Verschlüsselungsschlüssel öffentlich ist. Um dieses Problem zu beheben, kombinieren Sie die Signierung mit der Verschlüsselung. Ein typisches Muster sieht so aus:

  • Signieren Sie eine Nutzlast, um ein JWS oder signiertes JWT zu erstellen.
  • Verschlüsseln Sie das signierte Ergebnis, um ein verschlüsseltes JWT zu erstellen.

Wenn Sie mit diesem Ansatz eine signierte Nutzlast in ein verschlüsseltes JWT einbetten, erhalten Sie sowohl die Garantie für die Verbindlichkeit als auch für die Vertraulichkeit. Apigee-Richtlinien können solche Kombinationen erstellen, decodieren und prüfen.

Signaturalgorithmen

Die Richtlinien für die JWS/JWT-Überprüfung und die JWS/JWT-Generierung unterstützen RSA-, RSASSA-PSS-, ECDSA- und HMAC-Algorithmen und verwenden SHA2-Prüfsummen der Bitstärke 256, 384 oder 512. Die Richtlinien „DecodeJWS“ und „DecodeJWT“ funktionieren unabhängig vom Algorithmus, der zum Signieren des JWS/JWT verwendet wurde.

HMAC-Algorithmen

Der HMAC-Algorithmus beruht auf einem gemeinsamen Secret, dem sogenannten geheimen Schlüssel, zum Erstellen der Signatur (auch als Signatur des JWS/JWT bezeichnet) und der Überprüfung der Signatur.

Die Mindestlänge des geheimen Schlüssels hängt von der Bitstärke des Algorithmus ab:

  • HS256: 32 Byte Mindestlänge
  • HS386: Mindestlänge von 48 Byte
  • HS512: Mindestlänge von 64 Byte

RSA-Algorithmen

Die RSA-Algorithmen verwenden ein öffentliches/privates Schlüsselpaar für die kryptografische Signatur. In der JWA-Spezifikation werden die Moniker RS256, RS384 und RS512 verwendet, um diese Optionen darzustellen. Bei RSA-Signaturen verwendet die signierende Partei einen privaten RSA-Schlüssel, um das JWS/JWT zu signieren, und die überprüfende Partei verwendet den entsprechenden öffentlichen RSA-Schlüssel, um die Signatur auf dem JWS/JWT zu prüfen. Es gibt keine Größenanforderungen für die Schlüssel.

RSASSA-PSS-Algorithmen

Die RSASSA-PSS-Algorithmen sind ein Update der RSA-Algorithmen und verwenden die Moniker PS256, PS384 und PS512. Wie die RS*-Varianten verwendet RSASSA-PSS ein öffentliches/privates RSA-Schlüsselpaar für die kryptografische Signatur. Das Format, der Mechanismus und die Größenbeschränkungen des Schlüssels sind dieselben wie für die RS*-Algorithmen.

ECDSA-Algorithmen

Die Algorithmen des Elliptic Curve Digital Signature Algorithm (ECDSA) sind Elliptische-Kurven-Kryptographie-Algorithmen mit einer P-256-, P-384- oder P-521-Kurve. Wenn Sie ECDSA-Algorithmen verwenden, bestimmt der Algorithmus den Typ des öffentlichen und privaten Schlüssels, den Sie angeben müssen:

Algorithmus Kurve Schlüsselanforderung
ES256 P-256 Ein Schlüssel, der aus der P-256-Kurve generiert wurde (auch bekannt als secp256r1 oder Prime256v1)
ES384 P-384 Ein Schlüssel, der aus der P-384-Kurve generiert wird (auch secp384r1)
ES512 P-521 Ein Schlüssel, der aus der P-521-Kurve erzeugt wurde (auch als "secp521r1" bezeichnet)

Verschlüsselungsalgorithmen

Wenn Sie GenerateJWT und VerifyJWT verwenden, um verschlüsselte JWTs zu verarbeiten, unterstützen die Richtlinien die folgenden Algorithmen:

  • dir
  • RSA-OAEP-256
  • A128KW, A192KW, A256KW
  • A128GCMKW, A192GCMKW, A256GCMKW
  • PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW
  • ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW

Schlüssel und Schlüsselrepräsentationen

Die JOSE-Standards, die JWS, signierte und verschlüsselte JWTs und mehr abdecken, beschreiben, wie kryptografische Schlüssel zum Signieren oder Verschlüsseln von Informationen verwendet werden. Die grundlegenden Elemente für jeden kryptografischen Vorgang sind der Algorithmus und der Schlüssel. Für verschiedene Algorithmen sind unterschiedliche Schlüsseltypen und in einigen Fällen unterschiedliche Schlüsselgrößen erforderlich.

Symmetrische Algorithmen, wie die HS*-Familie zum Signieren oder der A128KW-Algorithmus zum Verschlüsseln, erfordern symmetrische oder gemeinsam genutzte Schlüssel: Es wird derselbe Schlüssel zum Signieren und Verifizieren oder derselbe Schlüssel zum Ver- und Entschlüsseln verwendet. Asymmetrische Algorithmen wie die RS*-, PS*- und ES*-Algorithmen zum Signieren oder die ECDH*-Algorithmen zur Verschlüsselung verwenden Schlüsselpaare. Es gibt einen öffentlichen Schlüssel und einen privaten Schlüssel, die übereinstimmen. Beim Signieren verwendet der Unterzeichner den privaten Schlüssel zum Signieren und jede Partei kann den öffentlichen Schlüssel zum Überprüfen der Signatur verwenden. Bei der Verschlüsselung verwendet der Verschlüsseler den öffentlichen Schlüssel zum Verschlüsseln und der Entschlüsseler den privaten Schlüssel zum Entschlüsseln. Öffentliche Schlüssel können, wie der Name schon sagt, öffentlich weitergegeben werden und müssen nicht geheim gehalten werden.

Es gibt verschiedene Möglichkeiten, kryptografische Schlüssel in das Textformat zu serialisieren. Apigee-Richtlinien akzeptieren Schlüssel, die in verschiedenen Formen serialisiert sind: PEM-codiert, JWKS-Form oder für gemeinsam genutzte Schlüssel UTF-8-codiert oder Base64-codiert.

PEM-Format

Für öffentliche oder private Schlüssel wird häufig die PEM-Codierung verwendet, die in IETF RFC 7468 definiert ist. Hier ein Beispiel für einen privaten Schlüssel im PEM-Format:

-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgVcB/UNPxalR9zDYAjQIf
jojUDiQuGnSJrFEEzZPT/92hRANCAASc7UJtgnF/abqWM60T3XNJEzBv5ez9TdwK
H0M6xpM2q+53wmsN/eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ
-----END PRIVATE KEY-----

Es gibt ähnliche PEM-Formate für öffentliche Schlüssel oder verschlüsselte private Schlüssel.

JWKS-Format

Ein JSON Web Key (JWK) ist eine JSON-Datenstruktur, die einen einzelnen kryptografischen Schlüssel darstellt. Ein JSON-Webschlüsselsatz (JWKS) ist eine JSON-Struktur, die einen Satz von JWKs darstellt. JWK und JWKS werden in RFC7517 beschrieben. Beispiele für JWKS finden Sie unter Anhang A. Beispiele für JSON-Webschlüsselsets.

JWKS soll es jeder Partei ermöglichen, eine Reihe von Schlüsseln in einem Standardformat darzustellen. Ein wichtiger Anwendungsfall ist die standardmäßige Freigabe öffentlicher Schlüssel über einen HTTP-Endpunkt, der Daten im JWKS-Format bereitstellt. Wenn ein Unternehmen oder System, das signierte JWS oder JWT generiert, z. B. ein Identitätsanbieter, seine öffentlichen Schlüssel veröffentlicht, kann jedes System oder jede Anwendung, die die öffentlichen Schlüssel lesen kann, von der signierenden Partei generierte Signaturen überprüfen. Umgekehrt kann jedes System oder jede App, das bzw. die Daten verschlüsseln möchte, die nur von einer bestimmten Partei oder einem bestimmten Unternehmen gelesen werden sollen, die öffentlichen Schlüssel dieser Partei oder dieses Unternehmens abrufen und zu diesem Zweck ein verschlüsseltes JWT generieren.

In RFC7517 werden die JWKS-Schlüsselelemente für jeden Schlüsseltyp wie RSA oder EC beschrieben. Diese Elemente sollten immer vorhanden sein:

  • kty – der Schlüsseltyp, z. B. RSA oder EC.
  • kid: die Schlüssel-ID. Dies kann ein beliebiger eindeutiger Stringwert sein. Es darf keine Duplikate innerhalb eines einzelnen Schlüsselsatzes geben. Wenn das eingehende JWT eine Schlüssel-ID besitzt, die im Satz von JWKS vorhanden ist, verwendet die Richtlinie den richtigen öffentlichen Schlüssel, um die JWS/JWT-Signatur zu überprüfen.

Im Folgenden finden Sie Beispiele für optionale Elemente und ihre Werte:

  • alg – der Schlüsselalgorithmus Er muss mit dem Signaturalgorithmus in JWS/JWT übereinstimmen.
  • use: Der vorgesehene Verwendungszweck des Schlüssels. Typische Werte sind „sig“ für Signieren und Verifizieren oder „enc“ für Verschlüsseln und Entschlüsseln.

Die folgende JWKS, die ursprünglich von https://www.googleapis.com/oauth2/v3/certs abgerufen wurde, aber jetzt veraltet ist, enthält die erforderlichen Elemente und Werte und wäre von Apigee verwendbar:

{
     "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",
        }
     ]
  }
  

Schlüssel für die JWS- und JWT-Richtlinien angeben

Unabhängig davon, ob Sie JWS oder JWT generieren oder bestätigen, müssen Sie einen Schlüssel für die kryptografischen Vorgänge angeben.

Wenn Sie ein signiertes JWT generieren, müssen Sie einen Schlüssel angeben, mit dem die Signatur erstellt werden kann.

  • Im Falle eines RS*-, PS*- oder ES*-Signaturalgorithmus, die alle asymmetrische Schlüssel verwenden, müssen Sie den privaten Schlüssel zur Erzeugung der Signatur angeben.
  • Im Falle eines HS*-Algorithmus müssen Sie den symmetrischen Schlüssel angeben, der beim Generieren der Signatur verwendet wird.

Wenn Sie ein signiertes JWS/JWT bestätigen, müssen Sie einen Schlüssel angeben, mit dem die Signatur bestätigt werden kann.

  • Im Falle eines RS*-, PS*- oder ES*-Signaturalgorithmus müssen Sie den öffentlichen Schlüssel angeben, der dem privaten Schlüssel zugeordnet ist, der ursprünglich zum Signieren des Tokens verwendet wurde.
  • Im Falle eines HS*-Algorithmus müssen Sie denselben symmetrischen Schlüssel angeben, der zum Signieren der JWS oder des JWT verwendet wurde.

Sie haben zwei Möglichkeiten, die Schlüssel für die JWS- und JWT-Richtlinien bereitzustellen:

  • Geben Sie den Schlüsselwert direkt an (normalerweise über eine Kontextvariable) oder
  • Geben Sie den Schlüssel indirekt über ein kid und ein JWKS an. Sie können das JWKS direkt oder indirekt über eine HTTP-URL angeben, über die Apigee das JWKS abrufen kann.

Die Option „JWKS-URL“ wird in der Regel nur als Quelle öffentlicher Schlüssel verwendet, die mit asymmetrischen Algorithmen verwendet werden können, da JWKS-URLs in der Regel öffentlich sind.

Die folgenden Beispiele veranschaulichen, wie Sie Schlüssel in verschiedenen Szenarien direkt angeben können.

  • Ein mit dem HS256-Algorithmus signiertes JWT generieren. Der erforderliche Schlüssel ist in diesem Fall ein symmetrischer Schlüssel. Diese Richtlinie stellt eine Kontextvariable mit dem base64url-codierten geheimen Schlüssel bereit.

    <GenerateJWT name='gen-138'>
      <Algorithm>HS256</Algorithm>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <SecretKey encoding='base64url'>
        <Value ref='private.secretkey'/>
        <Id ref='variable-containing-desired-keyid'/>
      </SecretKey>
      . . .
      <OutputVariable>output_variable_name</OutputVariable>
    </GenerateJWT>
  • Ein mit dem HS256-Algorithmus signiertes JWT verifizieren. Der erforderliche Schlüssel ist in diesem Fall ein symmetrischer Schlüssel. Wie im obigen Beispiel stellt diese Richtlinie eine Kontextvariable mit dem base64url-codierten geheimen Schlüssel bereit.

    <VerifyJWT name='verify-138'>
      <Algorithm>HS256</Algorithm>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <SecretKey encoding='base64url'>
        <Value ref='private.secretkey'/>
      </SecretKey>
      . . .
      <OutputVariable>output_variable_name</OutputVariable>
    </VerifyJWT>
  • Ein mit dem PS256-Algorithmus signiertes JWT verifizieren. Der erforderliche Schlüssel ist in diesem Fall ein öffentlicher RSA-Schlüssel. Diese Richtlinie stellt eine Kontextvariable mit dem PEM-codierten öffentlichen Schlüssel bereit.

    <VerifyJWT name='JWT-001'>
      <Algorithm>PS256</Algorithm>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PublicKey>
        <Value ref='variable-containing-pem-encoded-public-key'/>
      </PublicKey>
      . . .
    </VerifyJWT>
  • Ein mit dem HS256-Algorithmus signiertes JWT generieren. In diesem Fall ist ein privater RSA-Schlüssel erforderlich. Diese Richtlinie stellt eine Kontextvariable bereit, die den PEM-codierten privaten Schlüssel enthält.

    <GenerateJWT name='JWT-002'>
      <Algorithm>PS256</Algorithm>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PrivateKey>
        <Value ref='private.variable-containing-pem-encoded-private-key'/>
      </PrivateKey>
       . . .
    </GenerateJWT>

JWKS als Schlüsselquelle beim Überprüfen eines JWS oder signierten JWT

Wenn ein System oder eine App ein JWS/JWT generiert, fügt das System oder die App in der Regel eine Schlüsselkennung (die kid-Anforderung) in den JWS/JWT-Header ein. Der Schlüssel teilt jedem Leser des JWS/JWT mit, welcher Schlüssel erforderlich ist, um die Signatur auf dem signierten JWS/JWT zu überprüfen oder das verschlüsselte JWT zu entschlüsseln.

Angenommen, ein Aussteller signiert ein JWT mit einem privaten Schlüssel. Die „Schlüssel-ID“ identifiziert den passenden öffentlichen Schlüssel, der zur Überprüfung des JWT verwendet werden muss. Die Liste der öffentlichen Schlüssel ist in der Regel an einem bekannten Endpunkt verfügbar, z. B. am Google Identity-Endpunkt oder am Firebase Authentication-Endpunkt. Andere Anbieter haben eigene öffentliche Endpunkte, über die Schlüssel im JWKS-Format veröffentlicht werden.

Wenn Sie Apigee verwenden, um ein JWS oder signiertes JWT mit öffentlichen Schlüsseln zu überprüfen, die über einen JWKS-Endpunkt geteilt werden, haben Sie folgende Möglichkeiten:

  • Option 1: Geben Sie in der Richtlinienkonfiguration die JWKS-Endpunkt-URI im Element <PublicKey/JWKS> an. Zum Beispiel für die Richtlinie VerifyJWT:

    <VerifyJWT name="JWT-Verify-RS256">
      <Algorithm>RS256</Algorithm>
      <Source>json.jwt</Source>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PublicKey>
          <JWKS uri="https://www.googleapis.com/oauth2/v3/certs"/>
      </PublicKey>
      . . .
    </VerifyJWT>

    In diesem Fall gilt Folgendes:

    1. Untersuchen Sie den JWS/JWT-Header, um den Signaturalgorithmus (alg) zu finden, z. B. RS256, und lehnen Sie das eingehende JWT ab, wenn dieser Algorithmus nicht mit dem in der Richtlinie konfigurierten Algorithmus übereinstimmt.
    2. Rufen Sie die Liste der Schlüssel mit ihren IDs von dem angegebenen JWKS-Endpunkt ab oder aus einem internen Cache, wenn dieser JWKS-Endpunkt bereits verwendet wurde.
    3. Suchen Sie im JWS/JWT-Header nach der Schlüssel-ID (kid). Wenn das eingehende JWT keine Schlüssel-ID (kid) im Header enthält, ist die Zuordnung von kid zu verification-key nicht möglich und Apigee gibt einen Fehler aus.
    4. Extrahieren Sie aus dem JWKS den JWK mit der Schlüssel-ID, die im JWS/JWT-Header angegeben ist. Einen Fehler ausgeben, wenn kein Schlüssel mit dieser Schlüssel-ID vorhanden ist.
    5. Prüfen Sie, ob der Algorithmus für den JWK mit dem in der Richtlinienkonfiguration angegebenen Algorithmus übereinstimmt. Lehnen Sie die Prüfung ab und geben Sie einen Fehler aus, wenn die Algorithmen nicht übereinstimmen.
    6. Verwenden Sie diesen öffentlichen Schlüssel, um die Signatur auf dem JWS/JWT zu prüfen. Lehnen Sie die Prüfung ab und geben Sie einen Fehler aus, wenn die Signatur nicht verifiziert werden kann.
  • Option 2: Geben Sie in der Richtlinienkonfiguration eine Variable an, die die JWKS-Endpunkt-URI im Element <PublicKey/JWKS> enthält.

    Zum Beispiel für die Richtlinie VerifyJWT:

    <VerifyJWT name="JWT-Verify-RS256">
      <Algorithm>RS256</Algorithm>
      <Source>json.jwt</Source>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PublicKey>
        <JWKS uriRef="variable-containing-a-uri"/>
      </PublicKey>
      . . .
    </VerifyJWT>

    In diesem Fall führt Apigee dieselben Schritte wie oben aus, mit dem Unterschied, dass Apigee das JWKS nicht von einem hartcodierten URI, sondern von dem URI abruft, der in der Variable angegeben ist, auf die durch das Attribut uriRef verwiesen wird. Caching ist weiterhin möglich.

  • Option 3: Geben Sie in der Richtlinienkonfiguration eine Variable an, die die hartcodierten JWKS-Daten im Element <PublicKey/JWKS> enthält.

    Zum Beispiel für die Richtlinie VerifyJWT:

    <VerifyJWT name="JWT-Verify-RS256">
      <Algorithm>RS256</Algorithm>
      <Source>json.jwt</Source>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PublicKey>
        <JWKS ref="variable-that-holds-a-jwks"/>
      </PublicKey>
      . . .
    </VerifyJWT>

    In diesem Fall führt Apigee dieselben Schritte wie oben aus, mit dem Unterschied, dass Apigee das JWKS nicht von einem URI, sondern von der Kontextvariablen abruft, die Sie im Attribut ref angeben. Normalerweise haben Sie diese Kontextvariable aus einem ServiceCallout, einem KVM oder einer dem Proxy zugeordneten Eigenschaftendatei geladen.

JWKS als Schlüsselquelle beim Generieren eines verschlüsselten JWT

Wenn Sie ein verschlüsseltes JWT über einen asymmetrischen Algorithmus (RSA-OAEP-256 oder eine der ECDH-*-Varianten) generieren, verwenden Sie den öffentlichen Schlüssel zum Verschlüsseln. Sie haben mehrere Möglichkeiten, den Schlüssel für die GenerateJWT-Richtlinie bereitzustellen.

Ein typischer Ansatz besteht darin, in der Richtlinienkonfiguration die JWKS-Endpunkt-URI im Element <PublicKey/JWKS> anzugeben. Beispiele:

<GenerateJWT name="GJWT-1">
  <Algorithms>
    <Key>RSA-OAEP-256</Key>
    <Content>A128GCM</Content>
  </Algorithms>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PublicKey>
    <JWKS uri='https://www.example.com/.well-known/jwks.json'/>
    <Id ref='variable-containing-desired-keyid'/>
  </PublicKey>
    . . .
</GenerateJWT>

In diesem Fall gilt Folgendes:

  1. Die nicht codierte Nutzlast und den Header für das JWT basierend auf der Richtlinienkonfiguration zusammenstellen.
  2. Rufen Sie die Liste der Schlüssel mit ihren IDs vom angegebenen JWKS-Endpunkt oder aus einem internen Cache ab, wenn dieser JWKS-Endpunkt bereits verwendet wurde. Die aktuelle Cache-TTL beträgt 5 Minuten.
  3. Extrahieren Sie den JWK mit der im Element PublicKey/Id angegebenen Schlüssel-ID aus dem JWKS. Einen Fehler ausgeben, wenn kein Schlüssel mit dieser Schlüssel-ID vorhanden ist.
  4. Prüfen Sie, ob der Algorithmus für den JWK mit dem in der Richtlinienkonfiguration angegebenen Algorithmus übereinstimmt. Geben Sie einen Fehler aus, wenn die Algorithmen nicht übereinstimmen.
  5. Generieren Sie eine zufällige Sequenz, die als Inhaltsverschlüsselungsschlüssel verwendet werden soll.
  6. Verschlüsseln Sie den Inhaltsverschlüsselungsschlüssel mit dem ausgewählten öffentlichen Schlüssel.
  7. Verwenden Sie den Inhaltsverschlüsselungsschlüssel, um die Nutzlast zu verschlüsseln.
  8. Fügen Sie schließlich alle Teile zu einem serialisierten verschlüsselten JWT zusammen.

Alternativ können Sie das Attribut uriRef verwenden, um eine Variable anzugeben, die den URI eines JWKS-Endpunkts enthält. Beispiele:

<GenerateJWT name="GJWT-1">
  <Algorithms>
    <Key>RSA-OAEP-256</Key>
    <Content>A128GCM</Content>
  </Algorithms>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PublicKey>
    <JWKS uriRef='variable-containing-jwks-uri'/>
    <Id ref='variable-containing-desired-keyid'/>
  </PublicKey>
  . . .
</GenerateJWT>

In diesem Fall führt Apigee dieselben Schritte wie oben aus, mit dem Unterschied, dass Apigee das JWKS nicht von einem hartcodierten URI, sondern von dem URI abruft, der in der Variable angegeben ist, auf die durch das Attribut uriRef verwiesen wird. Apigee liest das JWKS aus einem internen Cache, wenn dieser JWKS-Endpunkt bereits verwendet wurde.