SAML2 vs JWT: Grundlegendes zum JSON-Web-Token (JWT)

In diesem Beitrag beginnen wir mit der Erforschung der JSON-Web-Token-Spezifikation (JWT) als Teil der SAML v2.0 vs JWT-Serie. Um die Anwendungsfälle von JWT zu verstehen, müssen wir uns auch OpenID Connect v1.0, OAuth v2.0 und einige verwandte Spezifikationen ansehen - die JWT-Spezifikation selbst ist nicht sehr interessant oder nützlich. Wir haben dies bei SAML 2.0 gesehen, das Teil dieser Serie ist - auf WS-Trust, WS-Security, XML DSig und zahlreiche andere grundlegende Spezifikationen wird verwiesen. Die JWT-Spezifikation ist viel kleiner als die SAML2-Spezifikation. Es ist viel grundlegender und definiert nur die Struktur des Tokens, aber keines der Protokolle, die das Token verwenden und es in der realen Welt nützlich machen. Die OAuth2- und OpenID Connect-Spezifikationen machen das - das kommt bald. Wie üblich komme ich dazu aus der Perspektive des Enterprise-IT-Shops; Ich denke groß, prozessorientiert, prüfend, viele Regeln, viele Sicherheitsanforderungen usw. Es ist möglicherweise nicht alles relevant für Ihre Situation, aber wahrscheinlich ist vieles davon. In diesem Beitrag geht es nicht um OAuth2 und OpenID Connect - wir werden bald darauf zugreifen.

Eine kurze Geschichte von JWT

Die frühesten Entwürfe der JWT-Spezifikation hießen OpenID Artifact Binding Proposal. Der erste Entwurf der JWT-Spezifikation wurde im Juli 2011 veröffentlicht. Beachten Sie, dass diese früheste veröffentlichte Spezifikation nicht auf JSON Web Signature (JWS) oder JSON Web Encryption (JWE) verweist. Frühere Versionen dieser Spezifikation wurden durch den Wunsch beeinflusst, ein JSON-basiertes Identitätstoken zu haben, das Signaturen und Verschlüsselung unterstützt, aber auch mehrere Krypto-Algorithmen unterstützt, während die Einfachheit von Salmon Protocols Magic Signature beibehalten wurde. Im Juli 2011 hat die IETF WOES-Arbeitsgruppe (Web Object Encryption Signing) (ein unglücklicher Name) damit begonnen, die Arbeit von der CMS-Spezifikation (Cryptographic Message Syntax) (RFC 3852) auszuweiten. Später in diesem Jahr schlossen sich die Arbeitsgruppen JWT und WOES zur Arbeitsgruppe JSON Object Signing Encryption (JOSE) zusammen. Diese Arbeitsgruppe führte unter anderem zu den JWS- und JWE-Spezifikationen - dies sind grundlegende Bausteine ​​für die JWT-Spezifikation. Die JWT-Spezifikation (RFC 7519), die JWS-Spezifikation (RFC 7515) und die JWE-Spezifikation (RFC 7516) wurden im Mai 2015 veröffentlicht.

Was ist JWT?

Die JSON-Web-Token-Spezifikation (RFC 7519) definiert einen Typ von Träger-Token, der Schlüssel-Wert-Paare von Attributen enthalten kann, die zur Erfüllung der Sicherheitsmodelle der rollenbasierten Zugriffssteuerung (RBAC) oder der attributbasierten Zugriffssteuerung (ABAC) verwendet werden. Aus der Spezifikation,

JSON Web Token (JWT) ist ein kompaktes, URL-sicheres Mittel zur Darstellung von Ansprüchen, die zwischen zwei Parteien übertragen werden sollen. Die Ansprüche in einem JWT werden als JSON-Objekt codiert, das als Nutzdaten einer JWS-Struktur (JSON Web Signature) oder als Klartext einer JWE-Struktur (JSON Web Encryption) verwendet wird, sodass die Ansprüche digital signiert oder durch Integrität geschützt werden können mit einem Message Authentication Code (MAC) und / oder verschlüsselt.

JWT-Token sind eine JSON-Datenstruktur (RFC 4627) mit Name: Wert-Paaren, die Ansprüche darstellen, aus denen die Nutzdaten einer JWS-Struktur (oder JWE-Klartext wie oben beschrieben) bestehen. Die JWS-Signaturfunktionen bedeuten, dass die Informationen im Token und dessen Quelle von Dritten validiert werden können, ohne dass auf den Identitätsanbieter zurückgegriffen werden muss, der das Token generiert hat. Die JWE-Verschlüsselungsfunktionen bedeuten, dass nur die gewünschten Parteien den Inhalt des Tokens lesen können.

Ein JWT enthält JSON-basierten Text, der Informationen enthält (oder enthalten kann) über:

  • Der authentifizierte Auftraggeber (Betreff)
  • Benutzerdefinierte Sicherheitsattribute, die den Benutzer beschreiben (private Ansprüche)
  • Informationen zum IdP (Emittenten)
  • Informationen zum SP (Zielgruppeninformationen)
  • Gültiger Zeitrahmen (Startdatum, Ablaufdatum, Ausstellungsdatum)
  • Digitale Unterschrift
  • Wie der Auftraggeber authentifiziert wurde
  • Verschlüsselungsinformationen

Ich habe eine fast identische Liste in der ursprünglichen Beschreibung von SAML2 in dieser Reihe geschrieben, was darauf hindeutet, dass diese beiden Technologien sehr ähnlich sind.

So wie wir es im JWS-Blogbeitrag gesehen haben, enthält die JWT-Token-Struktur Folgendes:

  • Header
  • Nutzlast
  • Unterschrift

Ein typisches Beispiel für eine JWT-Nutzlast (von AAD generiert) wäre:

{
  "Aud": "https://app1.levvel.io/login",
  "Iss": "https://sts.windows.net/75de389c-8f67-4084-9065-3a9c31e1db13/",
  "Iat": 1483691542,
  "Nbf": 1483691542,
  "Exp": 1483695442,
  "Acr": "1",
  "Amr": [
    "Pwd"
  ],
  "Appid": "80363411-f180–4a51–80ba-9b63770b9ac4",
  "Appidacr": "0",
  "Familienname": "Benutzer1",
  "Vorname": "Test",
  "Ipaddr": "1.1.1.1",
  "Name": "Test User1",
  "Oid": "42cd4e91–1c39–45ec-a0cb-13361157487b",
  "Platf": "14",
  "Scp": "user_impersonation",
  "Sub": "Hd6Ymh1ICumL3_MxJcdM1LaVFlbkSCNmmo6wlG7OFDg",
  "Tid": "75de389c-8f67–4084–9065–3a9c31e1db13",
  "Unique_name": "test1@rcbj.net",
  "Upn": "test1@rcbj.net",
  "Ver": "1.0"
  "Rollen": [
    "Benutzer"
  ]
}

Der JWT Header würde ungefähr so ​​aussehen:

{
 Typ: "JWT",
 alg: "RS256",
 x5t: "kriMPdmBvx68skT8-mPAB3BseeA"
}

Für dieses Beispiel habe ich ein AAD-JWT-Token verwendet, da es sich um eine Plattform handelt, mit der ich sehr vertraut bin und die viele nützliche Funktionen im Bereich der Unternehmensidentität bietet.

Diese Komponenten sind Base-64-codiert und durch "." Getrennt. Also haben wir:

BASE64URL (UTF8 (JWS-geschützter Header)) || ‘.’ || BASE64URL (JWS-Nutzlast) || ‘.’ || BASE64URL (JWS-Signatur)

als allgemeine Struktur des JWT-Tokens. Das wird so aussehen:

eyJhbGciOiJSUzI1NiJ9.eyJhIjoiYiIsImMiOiJkIiwiZSI6MX0.CNMaYaDGU3ZhFV1ve6p3sAdYXhEklej8DVIAMqIWCkpNmT6Jp7iigcndXwH5q3WQFHiswgIQU5 -_- 4rV3jKGptCROmEyWPW8_elhYH1apzAyjOjyZ55ygv37xKHzIFhixzAwmXlAv4pfD4lVelYWVNOSN7REA0QJeCy2vKdqZ5cjqCXQ1lkQUlzOE7dpuNoAkhAhAJJ8HaamFKy7Gl7uwmqbIr-dVYv21d_9O7mO26n0gy3zWXD2nJDxU5Mzl2pZd8-sFvUr9Kmp_YkeRMh4bSe0fr1Uc_YgkjpmYUyu7kaxRWTbAdJ3GwqWFMUDiyfhHdzvZPZyU4VkWreimoydMA

Die Details zur Generierung der Signatur finden Sie hier. Wir gehen auch davon aus, dass keine Verschlüsselung (JWE) verwendet wird.

Die JWT-Spezifikation definiert die folgenden optionalen Ansprüche (detaillierte Beschreibungen sind in der Spezifikation enthalten):

"Iss" (Issuer) Claim: der Auftraggeber, der das JWT ausgestellt hat. Dieser Anspruch ist fakultativ.

Unteranspruch (Subjektanspruch): der von der JWT beschriebene Auftraggeber. Die Behauptungen in einem JWT sind normalerweise Aussagen zu diesem Thema.

"Aud" (Audience) Claim: der Empfänger, für den das JWT bestimmt ist. Dieser Wert ist stark anwendungsspezifisch (kontextspezifisch).

„Exp“ (Expiration Time) Claim: Die Expiration Time des JWT. Es ist eine Zahl, die einen NumericDate-Wert enthält.

“Nbf” (Not Before) Claim: Die Zeit, vor der die JWT ungültig ist. Der Anspruch ist fakultativ.

"Iat" (Issued At) -Anspruch: Der Zeitpunkt, zu dem das JWT ausgestellt wurde - bestimmt das Alter des Tokens. In der Regel dasselbe wie die Behauptung „nbf“.

„Jti“ (JWT ID) Claim: Eine eindeutige Kennung für die JWT vom generierenden Identitätsanbieter.

Darüber hinaus definiert die JWS-Spezifikation diese Parameter, die in JWT-Token verwendet werden können. Zwischen den Ansprüchen der JWS-Spezifikation und der obigen Liste gibt es nicht viele Parameter, die tatsächlich erforderlich sind - ein weiterer Aspekt des Laufwerks zur Vereinfachung. Aus praktischer Sicht wird jeder nicht-triviale Anwendungsfall viele dieser Parameter haben und wahrscheinlich auch eine Vielzahl von privaten Ansprüchen.

Weitere private Ansprüche können geltend gemacht werden, solange der Hersteller und der Verbraucher des JWT-Tokens über deren Verwendung einverstanden sind. Wir können ein Beispiel für einen privaten Anspruch im obigen AAD JWT-Token mit dem Anspruch "upn" sehen. Der Benutzerprinzipalname (UPN) ist ein Active Directory-Attribut, das einen Benutzer eindeutig beschreibt, der in die Azure Active Directory-Welt übertragen wurde. Weitere Informationen zu Azure Active Directory-Token und -Ansprüchen finden Sie hier.

Für das oben angegebene AAD-generierte JWT:

Zielgruppe (Aud): https://app1.levvel.io/login; Diese Zielgruppe repräsentiert eine Webanwendung mit dieser URL.

Emittent (iss): enthält https://sts.windows.net/75de389c-8f67-4084-9065-3a9c31e1db13/; Dadurch wird der AAD-Mandant eindeutig identifiziert, der dieses Token generiert hat.

"Ausgestellt um" (iat), "nicht vor" (nbf) und verfällt (exp): Enthält die Zeitpunkte (bis auf die Sekunde genau), zu denen das JWT ausgestellt wurde, und den Zeitpunkt, zu dem es nicht gültig ist (normalerweise derselbe Zeitpunkt) wie zum Zeitpunkt der Ausgabe) und die Ablaufzeit. Diese Werte sind in koordinierter Weltzeit angegeben. Die Zahlen können in eine für Menschen lesbare Form umgewandelt werden.

version (ver): Claim hat die Versionsnummer dieses Tokens - die Version der JWT-Spezifikation.

Mandanten-ID (tid): Parameter ist die eindeutige Kennung für den AAD-Mandanten, der dieses Token generiert hat.

Authentifizierungsmethode (amr): Enthält Informationen darüber, wie der Principal authentifiziert wurde (in diesem Fall mit Benutzer-ID + Kennwort).

Rollen: Ein Array von Zeichenfolgen, die lesbare Namen von Anwendungsrollen enthalten, deren Mitglied der von diesem Token beschriebene Principal ist. Diese Informationen können für rollenbasierte Zugriffssteuerungsentscheidungen verwendet werden. Azure Active Directory-Anwendungsrollen gelten für einen anderen Beitrag.

Objekt-ID (oid): Parameter enthält die Objektkennung; Dies beschreibt ein Objekt in AAD eindeutig.

Benutzerprinzipalname (upn): der Benutzername des Principals; Dies ist eine private Microsoft-Behauptung im Format "Benutzer @ Domäne" (sie ähnelt einer E-Mail-Adresse, ist es aber nicht).

unique_name: Ein vom Menschen lesbarer Name für den Benutzer, der innerhalb des Mandanten möglicherweise nicht eindeutig ist. Der Name würde jedoch etwas anderes bedeuten - nicht ganz sicher, was sie dort dachten.

subject-Parameter (sub): unveränderlicher, eindeutiger Bezeichner für das AAD-Objekt, das den vom Token beschriebenen Principal darstellt.

Familienname: Der Familienname (oder Familienname) des Auftraggebers.

Vorname: der Vorname oder Vorname des Auftraggebers.

appid: Die Client-ID, die im OAuth-Aufruf (OpenID Connect) verwendet wurde, der das Token generiert hat.

scope (scp): Identitätswechselberechtigungen, die der durch den Parameter appid beschriebenen Anwendung gewährt werden - in einer zukünftigen Reihe von Beiträgen werden wir auf das Thema Identitätswechsel zurückkommen.

Anwendungsauthentifizierungskontextklassenreferenz (appidacr): Informationen darüber, wie die Clientanwendung authentifiziert wurde. Wenn der Client öffentlich ist, ist der Wert immer "0". Wenn der Kunde vertraulich ist, ist der Wert "1".

Referenz zur Authentifizierungskontextklasse (acr): Informationen darüber, wie der Principal authentifiziert wurde; Der Wert „0“ zeigt an, dass die Authentifizierung die Anforderungen von ISO / IEC 29115 nicht erfüllt.

Die Parameter in der Kopfzeile sind alle in der JWS-Spezifikation definiert und werden in unserer vorherigen Erörterung behandelt.

JWTs können zur Authentifizierung gegenüber serverseitigen Komponenten (z. B. APIs oder anderen Ressourcen) und zur Weitergabe der Identität zwischen API-Akteuren verwendet werden. Ich habe bereits das Konzept der sicheren Identitätsverbreitung angesprochen. Dies ist ein Mechanismus, der die Identität des ursprünglichen Anrufers oder Anforderungsinitiators sicher an nachgelagerte Systeme überträgt, an denen der ursprüngliche Anrufer (insbesondere ein menschlicher Akteur) direkt beteiligt ist, z. B. zwischen einem API-Gateway und einem API-Anbieter.

Im nächsten Teil dieser Reihe werden wir uns mit JWT-Anwendungsfällen befassen.