Token-basierte Authentifizierung leicht gemacht
Erfahren Sie mehr über Token-basierte Authentifizierung und wie Sie JWT einfach in Ihre Anwendungen implementieren können
Token-basierte Authentifizierung
Ein Token ist ein Datenelement, das für sich genommen keine Bedeutung oder Verwendung hat, aber in Kombination mit dem richtigen Tokenisierungssystem zu einem wichtigen Faktor für die Sicherheit Ihrer Anwendung wird. Bei der Token-basierten Authentifizierung wird sichergestellt, dass jede Anfrage an einen Server von einem signierten Token begleitet wird, das der Server auf seine Authentizität hin überprüft und erst dann auf die Anfrage antwortet.
JSON-Web-Token (JWT) ist ein offener Standard (RFC 7519), der eine kompakte und in sich geschlossene Methode für die sichere Übertragung von Informationen zwischen Parteien in Form eines JSON-Objekts definiert. JWT hat aufgrund seiner kompakten Größe, die eine einfache Übertragung von Token über Query-Strings, Header-Attribute und innerhalb des Bodys einer POST-Anfrage ermöglicht, große Popularität erlangt.
Warum Token verwenden?
Die Verwendung von Token hat viele Vorteile im Vergleich zu traditionellen Methoden wie Cookies.
- Token sind zustandslos. Das Token ist in sich geschlossen und enthält alle Informationen, die es für die Authentifizierung benötigt. Dies ist von großem Vorteil für die Skalierbarkeit, da Ihr Server den Sitzungsstatus nicht speichern muss.
- Token können von überall aus generiert werden. Die Token-Generierung ist von der Token-Verifizierung abgekoppelt, sodass Sie die Möglichkeit haben, die Signierung von Token auf einem separaten Server oder sogar über ein anderes Unternehmen wie Auth0 abzuwickeln.
- Fein abgestufte Zugriffskontrolle. Innerhalb des Token-Payloads können Sie ganz einfach Benutzerrollen und -berechtigungen sowie die Ressourcen festlegen, auf die der Benutzer zugreifen kann.
Dies sind nur einige der Vorteile, die JSON-Web-Token bieten. Weitere Informationen finden Sie in diesem Blog-Beitrag, in dem Token mit Cookies für die Verwaltung der Authentifizierung verglichen werden.
Anatomie eines JSON-Web-Token
Ein JSON-Web-Token besteht aus drei Teilen: Header, Payload und Signatur. Der Header und die Payload werden mit Base64 kodiert, anschließend durch einen Punkt verkettet und schließlich wird das Ergebnis algorithmisch signiert, wodurch ein Token in der Form header.claims.signature entsteht. Der Header besteht aus Metadaten, einschließlich des Token-Typs und des zum Signieren des Token verwendeten Hashing-Algorithmus. Die Payload enthält die Claim-Daten, die der Token kodiert. Das Endergebnis sieht wie folgt aus:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJtZXNzYWdlIjoiSldUIFJ1bGVzISIsImlhdCI6MTQ1OTQ0ODExOSwiZXhwIjoxNDU5NDU0NTE5fQ.-yIVBD5b73C75osbmwwshQNRC7frWUYrqaTjTpza2y4
Token sind zum Schutz vor Manipulationen signiert, sie sind nicht verschlüsselt. Das bedeutet, dass ein Token leicht entschlüsselt und sein Inhalt offengelegt werden kann. Wenn wir über jwt.io navigieren und das obige Token einfügen, können wir den Header und die Payload lesen - aber ohne das passende Geheimnis ist das Token nutzlos und wir sehen die Meldung „Ungültige Signatur“ Wenn wir das korrekte Geheimnis hinzufügen, in diesem Beispiel die Zeichenkette L3@RNJWT
, sehen wir nun die Meldung „Signatur verifiziert“ (Signature Verified)
In einem realen Szenario würde ein Mandant eine Anfrage an den Server stellen und das Token mit der Anfrage übergeben. Der Server würde versuchen, das Token zu verifizieren und im Erfolgsfall mit der Bearbeitung der Anfrage fortfahren. Wenn der Server das Token nicht verifizieren kann, sendet er eine Meldung 401 Unautorisiert
(Unauthorized) und eine Nachricht, dass die Anfrage nicht bearbeitet werden konnte, da die Autorisierung nicht verifiziert werden konnte.
Bewährte Praktiken für JSON-Web-Token
Bevor wir uns mit der Implementierung von JWT befassen, sollten Sie einige bewährte Verfahren kennen, um sicherzustellen, dass die Token-basierte Authentifizierung in Ihrer Anwendung ordnungsgemäß implementiert ist.
- Geheim halten. Sicher aufbewahren. Der Signierschlüssel sollte wie jeder andere Zugangscode behandelt werden und nur den Diensten offenbart werden, die ihn unbedingt benötigen.
- Fügen Sie der Payload keine sensiblen Daten hinzu. Token werden zum Schutz vor Manipulationen signiert und sind leicht zu entschlüsseln. Fügen Sie der Payload nur ein Minimum an Claims hinzu, um optimale Leistung und Sicherheit zu gewährleisten.
- Geben Sie Token ein Ablaufdatum. Technisch gesehen ist ein einmal signierter Token für immer gültig, es sei denn, der Signierschlüssel wird geändert oder die Gültigkeitsdauer explizit festgelegt. Dies könnte zu Problemen führen, daher sollten Sie eine Strategie für das Auslaufen und/oder den Widerruf von Token haben.
- Nutzen Sie HTTPS. Senden Sie keine Token über Nicht-HTTPS-Verbindungen, da diese Anfragen abgefangen und Token kompromittiert werden können.
- Berücksichtigen Sie alle Ihre Autorisierungsanwendungsfälle. Das Hinzufügen eines sekundären Token-Verifizierungssystems, das sicherstellt, dass die Token von Ihrem Server generiert wurden, ist vielleicht nicht üblich, kann aber notwendig sein, um Ihre Anforderungen zu erfüllen.
Weitere Informationen und bewährte Verfahren finden Sie in dem Blogbeitrag 10 Dinge, die Sie über Token wissen sollten.
Token-basierte Authentifizierung leicht gemacht
Token-basierte Authentifizierung und JWT werden weitgehend unterstützt. JavaScript, Python, C#, Java, PHP, Ruby, Go und andere verfügen über Bibliotheken zum einfachen Signieren und Verifizieren von JSON-Web-Token. Lassen Sie uns eine API implementieren und sehen, wie schnell wir sie mit JWT sichern können.
Wir haben uns dafür entschieden, unsere API mit NodeJS zu erstellen, da sie den geringsten Einrichtungsaufwand erfordert. Werfen wir einen Blick auf den Code für unsere Implementierung von JWT.
// Laden unserer Abhängigkeiten (Load in our dependencies)
var express = require('express');
var jwt = require('jsonwebtoken');
var app = express();
// Registrieren Sie die Home-Route, die eine Willkommensnachricht anzeigt
// Auf diese Route kann ohne Token zugegriffen werden
app.get('/', function(req, res){
res.send('Willkommen bei unserer API');
})
// Registrieren Sie die Route, um ein neues Token zu erhalten
// In einem realen Szenario würden wir die Benutzeranmeldeinformationen authentifizieren
// bevor ein Token erstellt wird, aber der Einfachheit halber generiert der Zugriff auf diese Route
// ein neues Token, das 2 Minuten lang gültig ist
app.get('/token', function(req, res){
var token = jwt.sign({username:'ado'}, 'supersecret',{expiresIn: 120});
res.send(token)
})
// Registrierung einer Route, die ein gültiges Token erfordert, um Daten anzuzeigen
app.get('/api', function(req, res){
var token = req.query.token;
jwt.verify(token, 'supersecret', function(err, decoded){
if(!err){
var secrets = {'accountNumber' : '938291239','pin' : '11289','account' : 'Finance'};
res.json(secrets);
} else {
res.send(err);
}
})
})
// Start unserer Anwendung auf Port 3000 (Launch our app on port 3000)
app.listen('3000');
Um unsere aktuelle API zu testen, starten wir die Anwendung und navigieren zu localhost:3000
. Wir sehen nur die Meldung „Willkommen bei unserer API“ („Welcome to our API“) Als nächstes navigieren wir zur Route localhost:3000/api
und sehen eine JWT-Fehlermeldung, die besagt, dass wir kein Token erhalten haben. Nun navigieren wir zur Route localhost:3000/token
und sehen, dass ein neues Token generiert wurde. Kopieren Sie dieses Token und navigieren Sie dann zu localhost:3000/api?token={ADD-COPIED-TOKEN-HERE}
und Sie werden die gewünschte Antwort sehen, nämlich die Finanzkonten des Unternehmens.
Mit nur ein paar Zeilen Code konnten wir unseren API-Endpunkt absichern. Wir haben die ordnungsgemäße Benutzerauthentifizierung vor der Generierung eines Token nicht behandelt. Das werden wir jetzt mit Auth0 nachholen.
JWT-Authentifizierung mit Auth0
Wir müssen einige leichte Änderungen an unserem Code vornehmen, um den Authentifizierungsablauf mit Auth0 darzustellen. Schauen wir uns die Änderungen unten an:
// Laden unserer Abhängigkeiten (Load in our dependencies)
var express = require('express');
var jwt = require('express-jwt');
var jwtCheck = jwt({
secret: new Buffer('{YOUR-APP-SECRET}', 'base64'),
Zielgruppe: '{YOUR-APP-CLIENT-ID}'
});
var app = express();
// // Anstatt innerhalb unseres Controllers nach einem Token zu suchen,
// verwenden wir eine Middleware. Wenn das Token ungültig ist,
// stoppen wir die weitere Ausführung der Anfrage.
app.use('/api', jwtCheck);
app.get('/', function(req, res){
res.send('Willkommen bei unserer API');
})
app.get('/api', function(req, res){
var secrets = {'accountNumber' : '938291239','pin' : '11289','account' : 'Finance'};
res.json(secrets);
})
app.listen('3000');
Um zu testen, ob dies funktioniert, starten wir den Server und navigieren zu localhost:3000/api
. Wir sehen eine Meldung, dass wir kein Autorisierungs-Token gesendet haben. Wir gehen zum Auth0 Playground, geben unsere Anmeldedaten ein und erhalten ein Token. Fügen Sie den folgenden Code in den Playground ein:
var domain = '{YOUR-AUTH0-DOMAIN}.auth0.com';
var clientID = '{YOUR-APP-CLIENT-ID}';
var lock = new Auth0Lock(clientID, domain);
lock.show({
focusInput: false,
popup: true,
}, function (err, profile, token) {
alert(token)
});
Um sicherzustellen, dass wir ein Token erhalten können, müssen wir zu unseren App-Einstellungen im Auth0 Dashboard navigieren und https://auth0.github.io/playground
zu unserer Liste der erlaubten Callback-URLs hinzufügen. Melden wir uns nun an oder erstellen ein Konto auf dem Auth0 Playground und wir erhalten ein Popup, in dem unser Token angezeigt wird.
Um den Inhalt unseres Token zu überprüfen, können wir es unter jwt.io entschlüsseln. Um das Token zu überprüfen, benötigen wir das Client Secret
unserer Auth0-App und müssen das Kästchen secret base64 encode aktivieren. Daraufhin sollte die Meldung „Signatur verifiziert“ (Signature Verified) angezeigt werden.
Um zu testen, ob unsere API mit diesem Token funktioniert, müssen wir eine GET
-Anfrage an localhost:3000/api
stellen und das Token in einem Authorization-Header senden. Am einfachsten ist es, eine Anwendung wie Postman zu verwenden, die das Testen von API-Endpunkten vereinfacht. Fügen Sie beim Aufruf einen Authorization-Header hinzu und fügen Sie für den Wert Bearer {TOKEN}
hinzu. Wenn der Aufruf erfolgt, prüft die Middleware jwtCheck
die Anfrage, stellt sicher, dass der Authorization-Header im richtigen Format vorliegt, extrahiert das Token, verifiziert es und verarbeitet, falls verifiziert, den Rest der Anfrage. Wir haben nur die Standardeinstellungen verwendet, um die Möglichkeiten von JWT zu zeigen, aber Sie können in den Dokumenten (docs) noch viel mehr erfahren.
Anwendungsfälle für Token-basierte Authentifizierung
Wir haben gesehen, wie einfach es ist, die JWT-Authentifizierung zu implementieren und unsere API zu sichern. Lassen Sie uns zum Abschluss die Anwendungsfälle untersuchen, für die sich die Token-basierte Authentifizierung am besten eignet.
- Plattform-as-a-Service-Anwendungen – die RESTful APIs bereitstellen, die von einer Vielzahl von Frameworks und Clients genutzt werden.
- Mobile Anwendungen – implementieren native oder hybride mobile Anwendungen, die mit Ihren Diensten interagieren.
- Einzelseitenanwendungen (SPA) – Erstellung moderner Anwendungen mit Frameworks wie Angular und React.
Weitere Ressourcen für den Einstieg in JSON-Web-Token finden Sie in diesem Beitrag.
Die Anmeldung für kostenlos
Beginnen Sie noch heute mit der Entwicklung und sichern Sie noch heute Ihre Anwendungen mit der Auth0-Identitätsplattform.