Ü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. Dadurch können nachfolgende Richtlinien im Apigee-Ablauf die Anforderungen im JWT oder JWS prüfen und Entscheidungen anhand dieser Anforderungen 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 Anforderungen 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 prüfen, unabhängig davon, ob das JWS/JWT von Apigee oder einem Drittanbieter generiert wurde. Für ein verschlüsseltes 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 untersucht 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 getrennte Teile:

Header.Key.InitializationVector.Payload.AuthenticationTag

Die GenerateJWT- und VerifyJWT-Richtlinien erstellen oder prüfen alle diese Teile. Das DecodeJWT 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 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 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.

Bei Verwendung von GenerateJWS 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 der "Nutzlastanforderung". Außerdem unterstützt die GenerateJWS-Richtlinie das Hinzufügen von Anforderungen mit beliebigen Namen zur Nutzlast nicht. Es ist möglich, die GenerateJWS-Richtlinie zu verwenden, um dem Header der JWS Anforderungen mit beliebigen Namen hinzuzufü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 besonders bei großen Nutzlasten platzsparender und mit mehreren Sicherheitsstandards verbunden sein.

Signieren im Vergleich zu Verschlüsselung

Apigee kann signiertes oder verschlüsseltes JWT generieren. Wählen Sie ein signiertes JWT aus, wenn die Nutzlast nicht geheim sein muss. Es ist aber wichtig, den Lesern Integritäts- und Nachweisbarkeit zu gewähren. Ein signiertes JWT sorgt dafür, dass sich die Nutzlast seit dem Signieren 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 sorgt für die Vertraulichkeit der Nutzlast, da nur der entsprechende Schlüsselinhaber sie entschlüsseln kann.

Es ist möglich, sowohl verschlüsseltes als auch signiertes JWT 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. Kombinieren Sie die Signatur mit Verschlüsselung, um dieses Problem zu beheben. 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 generieren.

Das Einbetten einer signierten Nutzlast in ein verschlüsseltes JWT mit diesem Ansatz bietet sowohl Nachweisbarkeit als auch Vertraulichkeit. Apigee-Richtlinien können solche Kombinationen erstellen und 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 DecodeJWS- und DecodeJWT-Richtlinien 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 durch die Namen 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 verwenden die Namen PS256, PS384 und PS512. Wie bei den 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 mit denen der RS*-Algorithmen identisch.

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 Curve 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 zur Verarbeitung des verschlüsselten JWT verwenden, unterstützen die Richtlinien diese 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 u. a. JWS, signiertes und verschlüsseltes JWT abdecken, beschreiben, wie kryptografische Schlüssel zum Signieren oder Verschlüsseln von Informationen verwendet werden. Zu den grundlegenden Elementen für kryptografische Vorgänge gehören der Algorithmus und der Schlüssel. Unterschiedliche Algorithmen erfordern unterschiedliche Schlüsseltypen und in einigen Fällen unterschiedliche Schlüsselgrößen.

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 und jeder kann den öffentlichen Schlüssel verwenden, um die Signatur zu verifizieren. Bei der Verschlüsselung verwendet der Verschlüsseler den öffentlichen Schlüssel zum Verschlüsseln und der Entschlüsseler verwendet den privaten Schlüssel zum Entschlüsseln. Öffentliche Schlüssel sind, wie der Name schon sagt, öffentlich zugänglich und müssen nicht geheim gehalten werden.

Es gibt verschiedene Möglichkeiten, kryptografische Schlüssel in ein Textformat zu serialisieren. Apigee-Richtlinien akzeptieren Schlüssel, die in verschiedenen Formen serialisiert sind: PEM-codierte Form, JWKS-Form oder für freigegebene Schlüssel UTF-8-codierte oder base64-codierte Form.

PEM-Format

Für öffentliche oder private Schlüssel ist die Verwendung der PEM-Codierung üblich, die in IETF RFC 7468 definiert ist. Hier sehen Sie 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 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 finden Sie unter Anhang A. Beispiele für JSON-Webschlüsselsets.

JWKS soll es jeder Partei ermöglichen, einen Satz 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, die von der signierenden Partei generierten Signaturen prüfen. Umgekehrt kann jedes System oder jede Anwendung, 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 des Unternehmens abrufen und ein verschlüsseltes JWT für diesen Zweck erfüllen.

In RFC7517 werden die JWKS-Schlüsselelemente für jeden Schlüsseltyp wie RSA oder EC beschrieben. Die folgenden 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. In einem Schlüsselsatz sollten 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. Übliche Werte sind "sig" für das Signieren und Verifizieren oder "enc" für die 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 JWS- und JWT-Richtlinien angeben

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

Wenn Sie ein signiertes JWT generieren, müssen Sie einen Schlüssel angeben, der die Signatur erzeugen 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.

  • Im Fall 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.
  • Bei einem HS*-Algorithmus müssen Sie den gleichen symmetrischen Schlüssel angeben, mit dem das JWS oder JWT signiert 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 einen kid und einen JWKS an. Sie können das JWKS direkt oder indirekt über eine HTTP-URL angeben, unter der Apigee den JWKS abrufen kann.

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

Die folgenden Beispiele zeigen, wie Sie Schlüssel in verschiedenen Szenarien direkt bereitstellen 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. Der erforderliche Schlüssel in diesem Fall ist ein symmetrischer Schlüssel. Wie im obigen Beispiel stellt diese Richtlinie eine Kontextvariable bereit, 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>
  • Prüfen Sie ein JWT, das mit dem PS256-Algorithmus signiert wurde. Der erforderliche Schlüssel ist in diesem Fall 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. Der erforderliche Schlüssel in diesem Fall ist ein privater RSA-Schlüssel. 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 Verifizieren eines JWS oder signierten JWT

Wenn ein System oder eine Anwendung ein JWS/JWT generiert, fügt das System oder die Anwendung in der Regel eine Schlüsselkennung (die Anforderung kid) in den JWS/JWT-Header ein. Der Schlüssel teilt jedem Leser des JWS/JWT mit, welcher Schlüssel zur Überprüfung der Signatur auf dem signierten JWS/JWT oder zum Entschlüsseln des verschlüsselten JWT erforderlich ist.

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 wie dem Google Identity-Endpunkt oder dem Firebase Authentication-Endpunkt verfügbar. Andere Anbieter haben eigene öffentliche Endpunkte, die Schlüssel im JWKS-Format veröffentlichen.

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

  • Option 1: Geben Sie in der Richtlinienkonfiguration den 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 Folgendes aus:

    1. Untersuchen Sie den JWS/JWT-Header, um den Signaturalgorithmus (alg) wie RS256 zu finden, 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 des untergeordneten Elements zum Verifizierungsschlüssel nicht möglich und Apigee gibt einen Fehler aus.
    4. Extrahieren Sie das JWKS, das JWK mit der Schlüssel-ID, die im JWS/JWT-Header angegeben ist. Wenn kein Schlüssel mit dieser Schlüssel-ID vorhanden ist, wird ein Fehler ausgegeben.
    5. Prüfen Sie, ob der Algorithmus für das JWK mit dem in der Richtlinienkonfiguration angegebenen Algorithmus übereinstimmt. Die Prüfung ablehnen und einen Fehler ausgeben, 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 den 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 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 Kontextvariable abruft, die Sie im Attribut ref angeben. Normalerweise hätten Sie diese Kontextvariable aus einem ServiceCallout, einer KVM oder einer mit dem Proxy verknüpften Attributdatei 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 zur Verschlüsselung. Sie haben die Möglichkeit, den Schlüssel für die GenerateJWT-Richtlinie bereitzustellen.

Ein typischer Ansatz besteht darin, in der Richtlinienkonfiguration den 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 führt Apigee Folgendes 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 die JWK mit der Schlüssel-ID, die im Element PublicKey/Id aus dem JWKS angegeben ist. Wenn kein Schlüssel mit dieser Schlüssel-ID vorhanden ist, wird ein Fehler ausgegeben.
  4. Prüfen Sie, ob der Algorithmus für das JWK mit dem in der Richtlinienkonfiguration angegebenen Algorithmus übereinstimmt. Wenn die Algorithmen nicht übereinstimmen, wird ein Fehler ausgegeben.
  5. Generieren Sie eine zufällige Sequenz, die als Inhaltsverschlüsselungsschlüssel verwendet werden soll.
  6. Verwenden Sie den ausgewählten öffentlichen Schlüssel, um den Schlüssel zur Inhaltsverschlüsselung zu verschlüsseln.
  7. Verwenden Sie den Inhaltsverschlüsselungsschlüssel, um die Nutzlast zu verschlüsseln.
  8. Stellen Sie schließlich 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 anstelle eines hartcodierten URI aus dem URI abruft, der in der Variable angegeben ist, auf die im Attribut uriRef verwiesen wird. Apigee liest das JWKS aus einem internen Cache, wenn dieser JWKS-Endpunkt bereits verwendet wurde.