Ü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-Richtlinie wird eine ungültige JWS/JWT abgelehnt, die zu einer Fehlerbedingung führt. Entsprechend führt die Verwendung der DecodeJWS- oder DecodeJWT-Richtlinie 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. Die JWS/JWT und ihre 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 unverschlüsselten Header prüfen.

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

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 entweder 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.
    • Der Header und die Nutzlast sind 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 „Nutzlastansprüche“. Die GenerateJWS-Richtlinie unterstützt nicht das Hinzufügen von Ansprüchen mit beliebigen Namen zur Nutzlast. Mit der GenerateJWS-Richtlinie können Sie dem Header des JWT 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 platzsparender sein und ist gemäß mehreren Sicherheitsstandards erforderlich.

Signatur und Verschlüsselung

Apigee kann signierte oder verschlüsselte JWTs generieren. Wählen Sie signierte JWTs aus, wenn die Nutzlast nicht geheim sein muss, aber für Leser Integrität und Verbindlichkeit gewährleistet werden müssen. Ein signiertes JWT versichert Lesern, dass sich die Nutzlast seit der Signatur des JWT nicht geändert hat und dass das JWT vom Inhaber des privaten Schlüssels signiert wurde. Wählen Sie „Verschlüsseltes JWT“ aus, wenn die Nutzlast geheim 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 Signatur mit der Verschlüsselung. Ein typisches Muster sieht so aus:

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

Wenn Sie eine signierte Nutzlast mit diesem Ansatz in ein verschlüsseltes JWT einbetten, sind sowohl die Verbindlichkeit als auch die Vertraulichkeit gewährleistet. Apigee-Richtlinien können solche Kombinationen generieren, decodieren und überprü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 diese Optionen mit den Aliasnamen RS256, RS384 und RS512 dargestellt. 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 werden als PS256, PS384 und PS512 bezeichnet. Wie die RS*-Varianten verwendet RSASSA-PSS ein öffentliches/privates RSA-Schlüsselpaar für die kryptografische Signatur. Format, Mechanismus und Größenbeschränkungen des Schlüssels sind dieselben wie bei den 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 zum Verarbeiten verschlüsselter JWTs verwenden, 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üsseldarstellungen

Die JOSE-Standards, die unter anderem JWS, signierte und verschlüsselte JWTs umfassen, beschreiben, wie Informationen mit kryptografischen Schlüsseln signiert oder verschlüsselt 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 auch 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. Bei der Signatur verwendet der Unterzeichner den privaten Schlüssel und jede Partei kann den öffentlichen Schlüssel verwenden, um die Signatur zu überprüfen. Bei der Verschlüsselung verwendet der Verschlüsseler den öffentlichen Schlüssel und der Entschlüsseler den privaten Schlüssel. Öffentliche Schlüssel können, wie der Name schon sagt, öffentlich geteilt werden und müssen nicht geheim gehalten werden.

Es gibt verschiedene Möglichkeiten, kryptografische Schlüssel in Textformat zu serialisieren. Gemäß den Apigee-Richtlinien werden Schlüssel in verschiedenen Formen serialisiert akzeptiert: PEM-codiertes Format, JWKS-Format oder für freigegebene Schlüssel UTF-8-codiertes oder Base64-codiertes Format.

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

Mit JWKS soll es jeder Partei ermöglicht werden, 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 liefert. Wenn ein Unternehmen oder System, das signierte JWS oder JWT generiert, z. B. ein Identitätsanbieter, seine öffentlichen Schlüssel veröffentlicht, können alle Systeme oder Anwendungen, die die öffentlichen Schlüssel lesen können, von der signierenden Partei generierte Signaturen überprüfen. Umgekehrt kann jedes System oder jede App, 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. Innerhalb eines einzelnen Schlüsselsatzes dürfen keine Duplikate vorhanden sein. 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 beabsichtigte Verwendungszweck des Schlüssels. Typische Werte sind „sig“ für Signatur und Überprüfung oder „enc“ für Verschlüsselung und Entschlüsselung.

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 überprüfen, 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 erzeugt 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.
  • Bei einem 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 verifiziert werden kann.

  • Bei einem 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.
  • Bei einem HS*-Algorithmus müssen Sie denselben symmetrischen Schlüssel angeben, der zum Signieren des JWS oder 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 eine kid und ein JWKS an. Sie können das JWKS direkt oder indirekt über eine HTTP-URL angeben, unter der 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.

In den folgenden Beispielen wird veranschaulicht, 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 bereit, die den base64url-codierten geheimen Schlüssel enthält.

    <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. In diesem Fall ist ein symmetrischer Schlüssel erforderlich. Wie im obigen Beispiel enthält diese Richtlinie eine Kontextvariable, die den Base64url-codierten geheimen Schlüssel enthält.

    <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. In diesem Fall ist der erforderliche Schlüssel ein öffentlicher RSA-Schlüssel. Diese Richtlinie stellt eine Kontextvariable bereit, die den PEM-codierten öffentlichen Schlüssel enthält.

    <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 bei der Überprüfung eines JWS oder signierten JWT

Wenn ein System oder eine App ein JWS/JWT generiert, fügt es normalerweise eine Schlüssel-ID (die Anforderung kid) in den JWS/JWT-Header ein. Der Schlüssel gibt jedem Leser des JWS/JWT an, 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. dem Google Identity-Endpunkt oder dem Firebase Authentication-Endpunkt. Andere Anbieter haben eigene öffentliche Endpunkte, über die Schlüssel im JWKS-Format veröffentlicht werden.

Wenn Sie mit Apigee ein JWS oder ein signiertes JWT mit öffentlichen Schlüsseln überprüfen, die über einen JWKS-Endpunkt freigegeben 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 führt Apigee folgende Schritte aus:

    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 löst einen Fehler aus.
    4. Extrahieren Sie aus dem JWKS das JWK mit der im JWS/JWT-Header angegebenen Schlüssel-ID. Es wird eine Fehlermeldung ausgegeben, wenn kein Schlüssel mit dieser Schlüssel-ID vorhanden ist.
    5. Prüfen Sie, ob der Algorithmus für das 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 im Element <PublicKey/JWKS> eine Variable an, die die JWKS-Endpunkt-URI 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. Das Caching gilt weiterhin.

  • 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 wird diese Kontextvariable aus einem ServiceCallout, einer KVM oder einer mit dem Proxy verknüpften 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 Möglichkeiten, den Schlüssel für die GenerateJWT-Richtlinie bereitzustellen.

Normalerweise wird die JWKS-Endpunkt-URI in der Richtlinienkonfiguration im Element <PublicKey/JWKS> angegeben. 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 führt Apigee folgende Schritte aus:

  1. Stellen Sie die nicht codierte Nutzlast und den Header für das JWT basierend auf der Richtlinienkonfiguration zusammen.
  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. Derzeit beträgt die Cache-TTL 5 Minuten.
  3. Extrahieren Sie das JWK mit der im PublicKey/Id-Element angegebenen Schlüssel-ID aus dem JWKS. Einen Fehler auslösen, wenn kein Schlüssel mit dieser Schlüssel-ID vorhanden ist.
  4. Prüfen Sie, ob der Algorithmus für das JWK mit dem in der Richtlinienkonfiguration angegebenen Algorithmus übereinstimmt. Gib 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. Verschlüsseln Sie die Nutzlast mit dem Inhaltsverschlüsselungsschlüssel.
  8. Stellen Sie abschließend alle Teile in 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. Wenn dieser JWKS-Endpunkt bereits verwendet wurde, liest Apigee das JWKS aus einem internen Cache.