Durchsuchbare Dokumentation aufrufen | Zurück zur Dokumentationsübersicht
Navigation: Dokumentationen agorum core > Übersicht tags
Ab welcher Version verfügbar?
• agorum core 9.0.7
Dieses Modul bietet Funktionen für die Erstellung und Dekodierung von JWT (JSON Web Tokens).
JWT können genutzt werden, um Zugriff auf bestimmte Services zu gewähren, ohne zuvor ein Login machen zu müssen. Die häufigste Verwendung ist folgende:
secret
die decode-Funktion dieser Library auf und kann somit prüfen, ob der Aufruf zulässig ist. In dem JWT können auch Informationen hinterlegt sein, wie z. B. ein Benutzername oder Ähnliches. Wichtig ist, dass nichts Geheimes darin enthalten ist, da JWTs grundsätzlich lesbar sind. Da das JWT allerdings auch wie ein Passwort funktioniert, sollte dieses auch auf dem Fremdsystem so gehalten werden, dass niemand rankommt.Die Signaturmethode ist HS256.
Im HTTP-Header wird solch ein Token in der Regel folgendermaßen mitgegeben:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Hinweis: Im Moment ist ein JWT nur in custom-services nutzbar. Dies wird sich in Zukunft auf alle agorum core API Services ausweiten.
let jwt = require('common/jwt');
Diese Funktion erstellt ein neues Token.
Aufruf
let token = jwt.create(id, issuer, subject, audience, secret, ttlMillis);
Parameter
Letztendlich handelt es sich um diverse Zeichenketten, bei denen man an sich beliebige Werte hinterlegen kann.
Definition: https://de.wikipedia.org/wiki/JSON_Web_Token
Parameter | Beschreibung |
---|---|
id | Eine eindeutige case-sensitive Zeichenfolge, welche das Token eindeutig identifiziert. Hiermit kann verhindert werden, dass das Token mehrfach verwendet wird. Hierbei kann es sich etwa um eine durchgezählte Nummer, einen GUID oder einen Hashwert handeln. |
issuer | Der Aussteller des Tokens, z. B. agorum core oder der Benutzer, der es ausstellt. |
subject | Definiert, für welches Subjekt die Claims gelten. Das Feld definiert also, für wen oder was die Claims getätigt werden. |
audience | (optional) Die Zieldomäne, für die das Token ausgestellt wurde. Letztendlich kann hier ein String hinterlegt werden, um für einen Benutzer für verschiedene Bereiche / Systeme die Gültigkeit zu bestimmen. |
secret | Ein geheimer Schlüssel, der zur digitalen Unterschrift der Informationen dient. Dieser Schlüssel muss geheim bleiben. Mit diesem Schlüssel wird die Nachricht auch mit der Funktion "decode" wieder dekodiert. Der Schlüssel sollte eine gewisse Länge besitzen, je länger, desto sicherer. Empfehlung Mindestens 32 Zeichen |
ttlMillis | time-to-live in Millisekunden. Wird ein Wert > 0 eingetragen, so erhält das Token eine Gültigkeitsdauer, die durch die Angabe von ttlMillis definiert ist. Wird 0 mitgegeben, so ist die Gültigkeit unendlich. |
Beispiel
let jwt = require('common/jwt'); let token = jwt.create('id1', 'issuer1', 'subject1', 'audience1', 'mytopsecret01', 60000); // Rückgabe des Tokens eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJpZDEiLCJpYXQiOjE1NTYxMTQxOTgsInN1YiI6InN1YmplY3QxIiwiYXVkIjoiYXVkaWVuY2UxIiwiaXNzIjoiaXNzdWVyMSIsImV4cCI6MTU1NjExNDI1OH0.8xhmXc9IEZ5AQ_jO95hm4EGWV-PUIti4Lub9DZyX0b0
Mit dem folgenden Skript lassen Sie das System die Authentifizierung mittels JSON Web Token prüfen. Anschließend verarbeitet das System die Parameter und die hochgeladene Datei.
FileObject
angelegt./* global sc, request */ //imports let objects = require('common/objects'); let metadb = require('common/metadb'); let jwt = require('common/jwt'); // Java imports /* Konvertiert einen Stream in einen lesbaren String * * Param InputStream <is>: Der input stream, der die Daten enthält * Param String <encoding>: Die Codierung des Streams. Meistens 'UTF-8' */ let streamToString = Packages.agorum.commons.string.StringConverterUtils.toString; // (InputStream is, String encoding) /* [Singleton] Objekt, das den Zugriff auf die Agorum-Protokolle und -Statistiken ermöglicht * * [static] instance: Die Instanz des Singleton-Objekts * * function <error>, Params: (String error) - loggt einen Fehler in den Server-Log */ let scs = Packages.agorum.roi.statistic.SessionControllerStatistic; // der Pre-Shared Key wird in der MetaDb gespeichert const encryptedPSK = metadb.read('MAIN_MODULE_MANAGEMENT/customers/agorum/secret'); /* metaddb.decrypt ist verfügbar für agorum [Internal] 9.5.3 oder [External] 10.0. * bei älteren Versionen kommentieren Sie die Nachfolgende Zeile aus [HACK!] */ //metadb.decrypt = (encrypted) => Packages.agorum.roi.ejb.common.CryptKeyController().tryDecrypt(encrypted, 'metadb', sc); /* Diese Funktion prüft das vom Client gesendete Autorisierungs-Token. * * Param <authToken>: Das vom Client gesendete Autorisierungs-Token. * * Param <psk>: Der verschlüsselte Pre-Shared Key. * * Param <logFailedAuth>: Wenn dieser Parameter auf einen <truthy>-Wert gesetzt ist, wird jede fehlgeschlagene Authentifizierungsanfrage * protokolliert, sodass sie in den Agorum-Serverprotokollen sichtbar ist. * * Rückkgabe: */ let checkAuth = (authToken, psk, logFailedAuth) => { try { return jwt.decode(authToken.slice(7), metadb.decrypt(psk)); } catch (ex) { if (logFailedAuth) { scs.instance.error(ex); } return null; } }; let saveFile = (file, target) => { return objects.create('file', { name: file.parameters.filename, content: file.stream, target: target || objects.find('home:MyFiles') }); }; /* <request.header> is an JSON Object, containing all html headers as key-value pairs. * The values are always represented as array of values. */ // Prüfen, ob der Client ein Autorisierungs-Token sendet if (!request.header.authorization || !request.header.authorization[0]) { throw new Error('401 - Authorization needed'); } // Validiert das Autorisierungs-Token // authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJpZDEiLCJpYXQiOjE2MDgyODU5MDksInN1YiI6ImtvcHAuZG9jdW1lbnQudXBsb2FkIiwiYXVkIjoia29wcCIsImlzcyI6ImFnb3J1bSJ9.fNRGid5q_AO5sgZwkXkApXzDavxAUlrp-iRYEHE5n0E let claim = checkAuth(request.header.authorization[0], encryptedPSK, true); if (!claim) { throw new Error('403 - Authorization failed'); } // Sie können das Auth-Token jetzt validieren. Der Ablauf wird von der Decode-Funktion geprüft! /* claim: { * id: '<ID>', // Eindeutige Kennung * * issuedAt '<Date>', // Zeitstempel der Ausgabe * expiration: null | '<Date>', // Zeitstempel des Ablaufs * * issuer: 'agorum', // Wer den Token ausgegeben hat * audience: '<audience>', * subject: '<subject>', * } */ // Starten /* Definierte input-Parameter: * File <file>: Datei, die hochgeladen wird * String <type>: String, der den Dateityp beschreibt * String <year>: Jahr, in dem die Dateien erstellt wurden * String <customerNumber>: Nummer des Kunden, der die Datei gesendet hat */ /* Jeder Anhang hat die folgenden Eigenschaften: * { * stream: // Wert | stream * type: // mime-Type des Streams * parameters: { // Eigenschaften des Anhangs * name: //Name der Eigenschaft * [filename]: //Nur bei der Eigenschaft'FILE': originaler Dateiname * ...? * } * } */ let attachments = request.attachments; // Wenn Sie den URL-Parameter anstelle des HTML-Bodys verwenden // let urlParams = request.params; let file, params = {}; request.attachments.forEach(attachment => { if (attachment.parameters.filename) { // wenn 'fileName' definiert ist, muss der Parameter die Upload-Datei sein! file = attachment; } else { // Wenn 'filename' nicht vorhanden ist, kann der Parameter-Stream ausgelesen werden, um seinen Wert zu erhalten params[attachment.parameters.name] = streamToString(attachment.stream, 'UTF-8'); } }); // Prüfen, ob etwas hochgeladen wurde if (!file) { throw new Error('400 - Missing upload file'); } file = saveFile(file /*, '/roi/agorum/path/to/upload/dir' */); // Platz für zusätzliche Code: // // Vielleicht möchten Sie hier einen Workflow starten oder etwas anderes mit dieser Datei machen... // // Sie können die Urls angeben, unter denen Ihre Datei in agorum zu finden ist // SSO: Single Sign on - wenn aktiviert, können Sie direkt zu dieser Datei navigieren // Redirect: Wenn es kein SSO gibt, gelangt der Benutzer auf eine Anmeldeseite und wird zur Datei weitergeleitet, // wenn er sich erfolgreich authentifiziert hat (per Cookie, per Passwort, per was auch immer) let domain = 'https://your.agorum'; let ssoPath = 'https://agorumdocproxy.agorum.com/api/rest/object/embed/' + file.UUID; let redirectPath = '/roiwebui/home_module/?url=' + encodeURIComponent(ssoPath); // Schließlich wird das Ergebnis der Anfrage zurückgegeben ({ uuid: file.UUID, sso_url: domain + ssoPath, red_url: domain + redirectPath });
Diese Funktion dekodiert ein Token und prüft, ob die Signatur noch gültig ist.
Aufruf
let claim = jwt.decode(token, secret); // Rückgabe { "audience" : "audience1", "subject" : "subject1", "expiration" : null, "issuedAt" : "2019-04-24T14:24:57.000Z", "id" : "id1", "issuer" : "issuer1" }
Parameter
Parameter | Beschreibung |
---|---|
token | Angabe des JWT. |
secretz | Angabe des Secret-Keys (siehe create) |
Return
Es werden die Werte zurückgegeben, die bei der Erstellung definiert wurden
Exceptions
Das nachfolgende Skript ist eine Klasse, die ein Token erstellt und dieses im Anschluss direkt entschlüsselt. Damit wird ebenfalls geprüft, ob die angegebenen Daten (vornehmlich das Secret) auch funktionieren. Die Ausgabe zeigt, was alles im JWT codiert ist und wie das Token am Ende aussieht.
let jwt = require('common/jwt'); let createAndShow = () => { let result = { psk: 'ep1$a/&E0u8|=QuL?5V=yrS-SLQG$G2q', id: 'cb63dc3d-fb17-4a04-8a10-69eeb0552016', issuer: 'agorum', subject: 'customer.document.upload', audience: 'customer', ttl: 100000 }; /* * Param <id>: asd * Param <issuer>: asd * Param <subject>: asd * Param <audience>: asd * Param <secret>: secret Schlüssel, mindestens 32 Zeichen lang (alphanumerische Zeichen and Sonderzeichen erlaubt) * Param <ttlMillis>: 0 = unendlich; 1+ = TTL in Millisekunden */ result.token = jwt.create(result.id, result.issuer, result.subject, result.audience, result.psk, result.ttl); /* * Param <token>: asd * Param <secret>: secret Schlüssel, mindestens 32 Zeichen lang (alphanumerische Zeichen und Sonderzeichen erlaubt) */ result.decrypted = jwt.decode(result.token, result.psk); return result; }; createAndShow();