JSON Web Token

Ein JSON Web Token (JWT, vorgeschlagene Aussprache [dʒɒt]) basiert auf JSON und ist in RFC 7519[1] beschrieben. Das JWT ermöglicht den Austausch von verifizierbaren Claims. Es wird typischerweise verwendet, um in einem System mit einem Drittanbieter die Identität eines Benutzers zwischen einem Identity-Provider und einem Service-Provider auszutauschen. JWT eignen sich vor allem zur Implementierung von „Stateless Sessions“, da sämtliche authentifizierungsrelevanten Informationen im Token übertragen werden können und die Sitzung nicht zusätzlich auf einem Server gespeichert werden muss.

## Aufbau

[Bearbeiten | Quelltext bearbeiten]

Ein JWT besteht aus drei Teilen: dem Header, Payload und der Signatur.

### Header

[Bearbeiten | Quelltext bearbeiten]

Der Header ist ein JSON-Element, welches beschreibt, um welchen Token-Typ es sich handelt und welche Signaturmethode zum Einsatz kommt.

Feld | Name | Bedeutung

|
|

typ | Type | Beschreibt den IANA-Medientyp des Tokens. Dieser Wert ist immer `JWT`, um den Medientyp `application/jwt` zu beschreiben.
cty | Content Type | Dieses Feld wird benötigt, wenn das JWT ein anderes JWT als Payload enthält. In diesem Fall wird es auf `JWT` gesetzt. Andernfalls sollte dieses Feld weggelassen werden.
alg | Algorithm  | Beschreibt, welche Signaturmethode zum Einsatz kommt. Als Signaturmethode kommt üblicherweise HMAC mit SHA-256 (`HS256`) oder RSA mit SHA-256 (`RS256`) zum Einsatz. Es ist möglich, keine Signatur zu verwenden (`none`), was jedoch nicht empfohlen wird. Die möglichen Werte sind durch die JSON Web Encryption (JWE) nach RFC 7516[2] genormt.

Der Header sieht beispielsweise wie folgt aus:

"alg": "HS256",
"typ": "JWT"

### Payload

[Bearbeiten | Quelltext bearbeiten]

Beim Payload handelt es sich um ein JSON-Element, welches die Claims beschreibt.

"sub": "1234567890",
"name": "John Doe",
"admin": true

Einige Claims sind hierbei reserviert:

Feld  | Name  | Bedeutung

|
|

iss | Issuer  | Der Aussteller des Tokens
sub | Subject  | Definiert für welches Subjekt die Claims gelten. Das `sub`-Feld definiert also für wen oder was die Claims getätigt werden.
aud | Audience | Die Zieldomäne, für die das Token ausgestellt wurde.
exp | Expiration Time  | Das Ablaufdatum des Tokens in Unixzeit, also der Anzahl der Sekunden seit `1970-01-01T00:00:00Z`.
nbf | Not Before  | Die Unixzeit, ab der das Token gültig ist.
iat | Issued At  | Die Unixzeit, zu der das Token ausgestellt wurde.
jti | JWT ID  | Eine eindeutige case-sensitive Zeichenfolge, welche das Token eindeutig identifiziert. Hiermit kann verhindert werden, dass das Token repliziert wird. Hierbei kann es sich etwa um eine durchgezählte Nummer, einen GUID oder einen Hashwert handeln. Falls der Token-Empfänger von mehreren Ausstellern einen Token empfängt, kann es sein, dass die JWT ID nicht eindeutig ist. Durch die Kombination des Ausstellers (iss) und der JWT ID (jti) kann diese wieder eindeutig werden.[3]

Des Weiteren sind noch Public Claims durch die IANA definiert.[4] Zudem kann der Aussteller des JWT auch einen Private Claim definierten URI verwenden, welche jedoch nicht standardisiert ist. Beispielsweise kann hier eine Ontologie wie Dublin Core oder FOAF zum Einsatz kommen.

### Signatur

[Bearbeiten | Quelltext bearbeiten]

Der Aufbau der Signatur wird durch JSON Web Signature (JWS), einem nach RFC 7515[5] genormten Standard, definiert.

Die Signatur wird dadurch erzeugt, dass der Header und der Payload im Base64 kodierten und durch einen Punkt getrennten Format mit der spezifizierten Hashmethode (z. B. SHA-256) gehasht und verschlüsselt (z. B. HMAC) wird:

var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, secret);

### Codierung

[Bearbeiten | Quelltext bearbeiten]

Header, Payload und Signatur werden jeweils mit Base64-URL kodiert und durch jeweils einen Punkt voneinander getrennt. Ein JWT Token kann wie folgt aussehen:

var jwt = base64UrlEncode(header) + "." + base64UrlEncode(payload) + "." + base64UrlEncode(signature)

`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY290Y2guaW8iLCJleHAiOjEzMDA4MTkzODAsIm5hbWUiOiJDaHJpcyBTZXZpbGxlamEiLCJhZG1pbiI6dHJ1ZX0.03f329983b86f7d9a9f5fef85305880101d5e302afafa20154d094b229f75773`

## Übertragung mit HTTP

[Bearbeiten | Quelltext bearbeiten]

Das JWT kann in der URL oder im HTTP-Header übertragen werden.

`http://example.com/path?jwt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…`

Für die Übertragung im HTTP-Header gibt es zwei Möglichkeiten: Das Authorization-Feld oder das Cookie-Feld.

* im Authorization-Feld als Bearer-Token: `Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…`
* im Cookie-Feld: `Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…`

Die beiden Methoden haben unterschiedliche Vor- und Nachteile:

s | Bearer-Token | Cookie

|
|

Header  |

`Authorization: Bearer <JWT>`

`Cookie: token=<JWT>`

CORS | Funktioniert mit CORS, jedoch ist eine Implementierung in JavaScript nötig.  | Das Cookie wird vom Browser nur für die aktuelle Domäne übermittelt. CORS ist nicht möglich.
Speicherung  | Alle durch JavaScript ansprechbaren Speichermethoden wie WebStorage und der Cookie-Store sind möglich.  | Cookie wird im Cookie-Store hinterlegt.
Schutz gegen MITM | Das Vorhandensein von TLS muss in JavaScript geprüft werden.  | Wenn das Flag `secure` am Cookie gesetzt wird, wird TLS erzwungen.
Schutz gegen XSS | Muss in JavaScript implementiert werden.  | Implizit, wenn das Flag `HttpOnly` am Cookie gesetzt wird, um den Zugriff mittels JavaScript zu verhindern.
Schutz gegen CSRF | Implizit, da Header vom Browser im Gegensatz zu Cookies nicht automatisch gesendet werden.  | Muss in JavaScript implementiert werden.

## Implementierungen

[Bearbeiten | Quelltext bearbeiten]

Implementierungen für JWT steht für eine Vielzahl von Plattformen zur Verfügung. Eine aktuelle Liste findet sich beispielsweise auf der Seite JWT.io.[6]

## Security Event Token

[Bearbeiten | Quelltext bearbeiten]

Ein Security Event Token (SET) erweitert den JWT Standard um den `events` Claim, welcher eine Liste von sicherheitsrelevanten Ereignissen aufzeichnet.[7] Diese Tokens haben einen digitalen Zeitstempel und unbegrenzte Gültigkeit. Ein SET-Payload kann wie folgt aussehen:

"iss": "https://server.example.com",
"sub": "248289761001",
"aud": "s6BhdRkqt3",
"iat": 1471566154,
"jti": "bWJq",
"sid": "08a5019c-17e1-4977-8f42-65a12843ea02",
"events": {
"http://schemas.openid.net/event/backchannel-logout": {}

SETs kommen beim Auditing zum Einsatz. SETs werden in RFC 8417[8] spezifiziert.

## Siehe auch

[Bearbeiten | Quelltext bearbeiten]

* Security Assertion Markup Language (SAML)
* OAuth und OpenID

## Weblinks

[Bearbeiten | Quelltext bearbeiten]

* Bernd Schönbach: Nutzer-Authentifizierung in Microservice-Umgebungen. In: Heise Developer. 9. Juni 2017, abgerufen am 11. Juni 2017.

## Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]

1. ↑ RFC: 7519 – JSON Web Token (JWT). Mai 2015 (englisch).
2. ↑ RFC: 7516 – JSON Web Encryption (JWE). Mai 2015 (englisch).
3. ↑ Prabath Siriwardena: Advanced API Security: OAuth 2.0 and Beyond. Apress, New York 2020, ISBN 978-1-4842-2049-8, S. 163.
4. ↑ JSON Web Token Claims. 23. Februar 2017, abgerufen am 14. Mai 2017 (Liste der JWT Public Claims).
5. ↑ RFC: 7515 – JSON Web Signature (JWS). Mai 2015 (englisch).
6. ↑ JWT. Auth0, abgerufen am 14. Mai 2017 (englisch).
7. ↑ Security Event Token (SET) Specification and IETF Security Events Working Group. Abgerufen am 14. Mai 2017 (englisch).
8. ↑ RFC: 8417 – Security Event Token (SET). Juli 2018 (englisch).