Der Kern der Single-Sign-On-Authentifizierung ist eine Technologie namens JSON Web Token (JWT), die Zendesk erlaubt, den von Ihren Systemen gesendeten Login-Anfragen zu vertrauen. Weitere Informationen finden Sie unter Aktivieren von Single-Sign-On über JWT (JSON Web Token).
Eine JSON Web Token-Authentifizierungsanforderung sieht folgendermaßen aus:
https://joeandco.zendesk.com/access/jwt?jwt=eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpYXQiOjEzNzIxMTMzMDUsImp0aSI6ODg4MzM2MjUzMTE5Ni4zMjYsIm5hbWUiOiJUZXN0IFVzZXIiLCJlbWFpbCI6InR1c2VyQGV4YW1wbGUub3JnIiwiZXh0ZXJuYWxfaWQiOiI1Njc4Iiwib3JnYW5pemF0aW9uIjoiQXBwbGUiLCJ0YWdzIjoidmlwX3VzZXIiLCJyZW1vdGVfcGhvdG9fdXJsIjoiaHR0cDovL21pdC56ZW5mcy5jb20vMjA2LzIwMTEvMDUvQmFybmFieV9NYXR0X2Nyb3BwZWQuanBnIiwibG9jYWxlX2lkIjoiOCJ9.Zv9P7PNIcgHfxZaMwQtMpty3TZnmVHRWcsmAMM-mNHg
Wenn der Benutzer die URL mit diesem Token in einem Browser aufruft, wird er automatisch bei seiner Zendesk-Instanz angemeldet.
So einfach ist das. Mehr ist nicht nötig. Keine Server, die im Hintergrund miteinander verhandeln. Alles geschieht in einer URL.
Es genügt, dass ein Remote-Authentifizierungsskript eine URL mit einem solchen Token erstellt und der Benutzer sie in seinem Browser aufruft.
Sehen wir uns die Bestandteile des Tokens genauer an.
https://joeandco.zendesk.com/access/jwt?jwt=
Der erste Teil ist der URL-Endpunkt, an den die Remote-Authentifizierungsanforderungen gestellt werden müssen. Darauf folgt ein Fragezeichen (?), das den Parameterblock einleitet. Die Parameter übergeben verschiedene Informationen an das Skript am Zielendpunkt (https://joeandco.zendesk.com/access/jwt). Das Skript muss so ausgelegt sein, dass es diese Parameter akzeptiert. Deshalb wird es an /access/jwt gesendet und nicht einfach an irgendeine beliebige Adresse.
Nach dem Fragezeichen folgt der Name des Parameters„jwt“ und dann ein Gleichheitszeichen (=), das die anschließende Zeichenfolge als den Wert des Parameters kennzeichnet.
Der Rest sind Daten. Bei genauerer Betrachtung erkennen Sie, dass diese Daten durch Punkte in verschiedene Abschnitte aufgeteilt sind. Sehen wir uns diese Abschnitte der Reihe nach an.
Abschnitt 1: JWT-Header
Der erste Abschnitt ist der JWT-Header. Er kennzeichnet den Aufruf als JWT-Anforderung und gibt den Typ des verwendeten Hashing-Algorithmus an. (Dazu später mehr.)
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
Das Entscheidende an diesen (und allen weiteren) Daten ist, dass sie base64-codiert sind. Sie sind also nicht wirklich verschlüsselt und können beispielsweise mit den folgenden Tools mühelos decodiert werden:
- Web-Tool: http://www.base64decode.org/
- Terminal: http://drewsymo.com/how-to/quick-and-simple-base64-encode-on-mac-osx-terminal/
Die decodierte Zeichenfolge sieht folgendermaßen aus:
{"typ":"JWT",
"alg":"HS256"}
Wie Sie sehen, weist sie eine JSON-Struktur auf und enthält die beiden Schlüssel-Wert-Paare type: JWT
und Algorithm: HMAC SHA 256
. SHA 256 ist ein 256-Bit-Verschlüsselungsalgorithmus, der von der U.S. National Security Agency entwickelt wurde. Mit seiner Hilfe wird der dritte Abschnitt – die Signatur – generiert. Dazu kommen wir gleich.
Abschnitt 2: JWT-Claimset/Payload
Der zweite Abschnitt enthält die eigentlichen Daten und ist deshalb erheblich länger. Er wird als „JWT-Claimset“ bezeichnet.
eyJpYXQiOjEzNzIxMTMzMDUsImp0aSI6ODg4MzM2MjUzMTE5Ni4zMjYsIm5hbWUiOiJUZXN0IFVzZXIiLCJlbWFpbCI6InR1c2VyQGV4YW1wbGUub3JnIiwiZXh0ZXJuYWxfaWQiOiI1Njc4Iiwib3JnYW5pemF0aW9uIjoiQXBwbGUiLCJ0YWdzIjoidmlwX3VzZXIiLCJyZW1vdGVfcGhvdG9fdXJsIjoiaHR0cDovL21pdC56ZW5mcy5jb20vMjA2LzIwMTEvMDUvQmFybmFieV9NYXR0X2Nyb3BwZWQuanBnIiwibG9jYWxlX2lkIjoiOCJ9
Dieser Abschnitt enthält einen Zeitstempel, einen Zufallswert, einen Benutzernamen, eine E-Mail-Adresse, eine externe ID und einige Tags. Darüber hinaus sind noch weitere Optionen verfügbar. Nach der base64-Decodierung sind auch diese Daten lesbar. Zum leichteren Verständnis teilen wir sie hier in Zeilen auf.
{
"iat":1372113305,
"jti":8883362531196.326,
"name":"Test User",
"email":"tuser@example.org",
"external_id":"5678",
"organization":"Apple",
"tags":"vip_user",
"remote_photo_url":"http://mit.zenfs.com/206/2011/05/Barnaby_Matt_cropped.jpg",
"locale_id":"8"
}
Erforderlich
IAT
Der erste Schlüssel heißt iat, was für issued at steht. Dieser Zeitstempel gibt den Zeitpunkt der Ausgabe in vollen Sekunden seit dem 1. Januar 1970, einem standardmäßigen UNIX-Zeitformat, an. Der Zeitstempel muss als Ganzzahl (ohne Dezimalstellen) und in UTC angegeben sein. Außerdem darf der angegebene Zeitpunkt maximal drei Minuten vor dem Eingang der Anforderung beim Zendesk-Server liegen. Jede Remote-Authentifizierungsanforderung ist mit einem Selbstzerstörungsmechanismus versehen, der verhindert, dass sie länger als 3 Minuten nach ihrer Erstellung verwendet wird.
JTI
Der zweite Schlüssel heißt jti, was für JSON Token ID steht. Diese Zeichenfolge muss ausreichend lang und zufällig sein, damit so gut wie ausgeschlossen ist, dass sie in diesem Konto ein zweites Mal verwendet wird. Falls sie versehentlich in einer weiteren Authentifizierungsanforderung wiederverwendet wird, schlägt diese fehl. Es handelt sich also um einen Einmalschlüssel. Mithilfe eines solchen (obligatorischen) Zufallswerts sorgen wir dafür, dass niemals zwei Authentifizierungsanfragen identisch sind. Dadurch wird die Wiederverwendung einer gültigen Anfrage-URL verhindert. Angenommen, es ist jemandem gelungen, Malware auf Ihrem Computer oder Netzwerk zu installieren und Ihren Datenverkehr zu protokollieren. Dadurch kann er nun jede URL sehen, die Sie aufrufen. Wenn er auf diese Weise erfährt, welche URL Sie für die Anmeldung bei Zendesk verwenden, könnte er sich – wäre der Schlüssel mehrfach verwendbar – innerhalb von 3 Minuten selbst in Ihrem Namen anmelden.
Name
Der nächste Schlüssel ist der vollständige Name des Benutzers mit Leerzeichen zwischen seinen Bestandteilen. Zendesk verwendet immer den in diesem Schlüssel übergebenen Namen, auch wenn zuvor ein anderer Name angegeben war.
Anschließend folgt die E-Mail-Adresse des Benutzers. Sie wird als eindeutige Kennung für einen Benutzer verwendet, sofern keine externe ID empfangen wird*. Wenn also eine E-Mail-Adresse und eine externe ID übergeben wird, versuchen wir zuerst, die ID zuzuordnen. Wenn dies gelingt, aktualisieren wir diesen Benutzer mit der angegebenen E-Mail-Adresse.
*Hinweis: Wenn in Zendesk die Option Aktualisierung externer IDs zulassen? aktiviert ist, wird die E-Mail-Adresse auch dann verwendet, wenn eine externe ID angegeben ist. Wenn die E-Mail-Adresse und die externe ID voneinander abweichen, ändern wir die ID.
Optional
Externe ID
Die externe ID ist eine optionale ID, die Sie anstelle der E-Mail-Adresse (siehe oben) verwenden können, um Benutzer zu identifizieren.
Organisation
Sie können auch den Wert organization übergeben, um einer Organisation einen Benutzer hinzuzufügen. Die genannte Organisation muss bereits vorhanden sein und genau den angegebenen Namen aufweisen. Andernfalls wird keine Aktion ausgeführt.
Stichwörter
Mit dem Schlüssel tags können Sie dem anzumeldenden Benutzer Stichwörter zuweisen. Gehen Sie hierbei mit Bedacht vor, da bereits vorhandene Stichwörter durch die angegebenen Stichwörter ersetzt werden. Wenn Sie einen leeren Stichwortparameter übergeben, entfernen Sie alle Schlüsselwörter des betreffenden Benutzers.
Remote-Foto-URL
Mit dem Schlüssel remote_photo_url können Sie die öffentliche URL-Adresse eines Fotos übergeben, das Sie als Profilbild des Benutzers verwenden möchten.
Gebietsschema (Sprache)
Sie können einen Wert für locale_id übergeben, um die Sprache des authentifizierten Benutzers in Zendesk festzulegen oder zu ändern. Der Wert muss eine Zahl sein, die ein in Ihrem Zendesk aktiviertes Gebietsschema bezeichnet. Sie finden die Gebietsschemas mit dem Endpunkt „locales.json“ unserer API: http://developer.zendesk.com/documentation/rest_api/locales.html#list-locales
Benutzerfelder (im Beispiel nicht dargestellt)
Dies muss ein JSON-Objekt sein, das Schlüssel-Wert-Paare für jeden Feldschlüssel und Wert enthält. Der Feldschlüssel kann in der Benutzeroberfläche unter „Benutzerfelder“ abgerufen oder definiert werden. Beachten Sie, dass nur angepasste Benutzerfelder übergeben werden können.
Beispiel:
"user_fields": {"checked": false,"date_joined": "2013-08-14T00:00:00+00:00","region": "EMEA","text_field": null}
Kontrollkästchen verwenden boolesche Werte, Datumscodes folgen dem obigen Beispiel und Dropdownlisten können den Namen der Option enthalten. Textfelder ermöglichen die Eingabe von Zeichenfolgen.
Telefonnummer (im Beispiel nicht dargestellt)
Akzeptiert eine Zeichenfolge für eine Telefonnummernidentität. Die Telefonnummer muss in einem akzeptierten Format angegeben werden. Weitere Informationen finden Sie unter Wie lauten die anerkannten Telefonnummer-Formate für Talk?
Abschnitt 3: JWS-Signatur
Der letzte Abschnitt der Anfrage ist der verschlüsselte Teil. Über ihn brauchen Sie sich weiter keine Gedanken zu machen. Er enthält die oben genannten Daten (iat, jti, name, email usw.) mit dem Shared Secret in einer verschlüsselten Zeichenfolge. Aus dieser verschlüsselten Zeichenfolge wird gemäß den JWT-Standards die Prüfsumme (checksum) errechnet und daraus wiederum die JWS-Signatur gebildet.
Wieso ist das sicher?
Um eine gültige verschlüsselte Zeichenfolge zu generieren, müssen Sie das Shared Secret kennen.
Die Verschlüsselung ist so konzipiert, dass von der verschlüsselten Zeichenfolge kein Rückschluss auf die Daten und den Schlüssel möglich ist. Selbst wenn Sie Zugriff auf den Dateninhalt haben, gibt es praktisch keine Möglichkeit, den Schlüssel abzuleiten.
Doch da sowohl Sie als auch wir über den Schlüssel verfügen und Sie uns dieselben Daten in unverschlüsselter und in verschlüsselter Form senden, können wir die Signatur selbst generieren und prüfen, ob sie mit der übereinstimmt, die Sie gesendet haben.
Dadurch wird auch sichergestellt, dass die Daten während der Übertragung nicht manipuliert werden können.
Der Aufbau in Pseudo-Code:
URLBase64Encode(
HMAC-SHA256(
URLBase64Encode( header_json ).URLBase64Encode( payload_json )
)
)
Beim Generieren des HMAC-SHA256-Codes für den Header und die Daten binden Sie das Shared Secret ein.
Das ist das Ergebnis:
Zv9P7PNIcgHfxZaMwQtMpty3TZnmVHRWcsmAMM-mNHg