Ich kenne was, was Du nicht kennst: Passport

Express gilt als das De-Facto-Framework zur Entwicklung serverseitiger Webanwendungen auf Basis von Node.js, enthält aber keine eingebaute Lösung für Authentifizierung. Das Middleware-Modul Passport schafft Abhilfe.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 6 Min.
Von
  • Golo Roden
Inhaltsverzeichnis

Express gilt als das De-Facto-Framework zur Entwicklung serverseitiger Webanwendungen auf Basis von Node.js, enthält aber keine eingebaute Lösung für Authentifizierung. Das Middleware-Modul Passport schafft Abhilfe.

Mehr Infos

Neue Artikelserie

"Ich kenne was, was Du nicht kennst" ist eine gemeinsame Serie von Golo Roden und Philip Ackermann, in der die beiden regelmäßig Module für JavaScript und Node.js vorstellen. Die erste Folge widmet sich dem Thema Authentifizierung.

Das Framework Express dient zahlreichen Entwicklern als Basis für die Entwicklung serverseitiger Webanwendungen. Einige Aufgaben wie Routing sind bereits enthalten, Express lässt sich aber individuell anpassen: Dazu dienen Erweiterungen, die Express als "Middleware" bezeichnet.

Eine der Aufgaben, die Express nicht serienmäßig wahrnimmt, ist die Authentifizierung von Anwendern. Dafür gibt es einen guten Grund: Das Framework müsste zahlreiche Verfahren implementieren, von denen in der Regel allerdings nur eins zeitgleich genutzt würde. Die Entscheidung, die Funktion bei Bedarf per Middleware nachzurüsten, trägt daher maßgeblich dazu bei, das Framework nicht unnötig zu vergrößern.

Passport ist eine Middleware für diesen Zweck. Sie lässt sich auf einfache Weise in Express integrieren und unterstützt über 140 Verfahren zur Authentifizierung, unter anderem die offenen und weit verbreiteten Standards OAuth und OpenID. Die einzelnen Verfahren sind ihrerseits wiederum als Erweiterungen für Passport implementiert, sodass nur jene geladen werden müssen, die tatsächlich benötigt werden.

Die Installation von Passport erfolgt auf dem in Node.js üblichen Weg, das heißt mit Hilfe von npm in das lokale node_modules-Verzeichnis der Anwendung:

$ npm install passport

Außerdem ist das Modul zu installieren, das das gewünschte Verfahren implementiert. Im einfachsten Fall, wenn die Authentifizierung weitgehend selbst entwickelt werden soll, ist das Modul passport-local erforderlich:

$ npm install passport-local

Anschließend sind beide Module mit Hilfe der require-Funktion in der Anwendung zu importieren. Nahezu alle Module, die ein Verfahren zur Authentifizierung implementieren, exportieren einen Konstruktor unter dem Namen Strategy:

var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;

Um das Verfahren anzuwenden, sind zwei Schritte erforderlich: Zum einen muss das Verfahren an sich konfiguriert werden, zum anderen ist es im Kontext einer Route einzusetzen. Die Konfiguration gelingt mit wenigen Zeilen:

passport.use(new LocalStrategy(function (user, password, done) {
// ...
}));

Die Callback-Funktion erhält den vom Anwender eingegebenen Benutzernamen und das Kennwort als Parameter. Es obliegt dem Entwickler, diese Werte zu verifizieren, beispielsweise im Rahmen einer Datenbankabfrage. Anschließend ist die done-Funktion auf eine von drei Arten aufzurufen:

  • Ist bei der Verifikation ein technischer Fehler aufgetreten, ist done mit einem Fehlerobjekt aufzurufen.
  • Ist die Authentifizierung inhaltlich fehlgeschlagen, weil der Anwender beispielsweise ein falsches Kennwort angegeben hat, muss done mit den Literalen null und false als Parameter aufgerufen werden.
  • Konnte der Anwender erfolgreich authentifiziert werden, wird ebenfalls null übergeben, an die Stelle von false tritt nun aber ein Objekt, das den Anwender identifiziert. Wie das Objekt gestaltet wird, obliegt dem Entwickler.

Das Grundgerüst der Funktion könnte daher ungefähr wie folgt aussehen:

passport.use(new LocalStrategy(function (user, password, done) {
verifyUser(function (err, profile) {
if (err) {
return done(err);
}
if (!profile) {
return done(null, false);
}
done(null, profile);
});
}));

Um das Verfahren nun für die Authentifizierung zu verwenden, muss Passport in der Express-Anwendung aktiviert werden. Dazu ist die Funktion passport.initialize() als Middlewarezu registrieren:

app.use(passport.initialize());

Für das Durchführen der Authentifizierung muss die Funktion passport.authenticate() als Middleware einer Route aufgerufen werden. In der Regel entspricht das der POST-Route /login oder einer ähnlichen Route. Das Modul passport-local geht davon aus, dass sich der Benutzername und das Kennwort in den Feldern username und password befinden. Das lässt sich bei Bedarf allerdings anpassen.

app.post('/login, passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login'
}), function (req, res) {
// ...
});

Um eine Ressource gezielt vor nicht authentifiziertem Zugriff zu schützen, bedarf es einer weiteren Middleware, die allerdings selbst geschrieben werden muss:

var ensureAuthenticated = function (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login');
};

Damit das funktioniert, muss man eine erfolgte Authentifizierung allerdings persistieren. Ansonsten gehen die Anmeldedaten direkt nach der Verarbeitung verloren und müssen bei jeder Anfrage erneut übertragen werden.

Als Lösung dient in der Regel die Verwendung einer Session. Zu diesem Zweck ist die Funktion passport.session() als Middleware aufzurufen. Allerdings muss man darauf achten, dass die Express-eigene Verwaltung von Sessions zu diesem Zeitpunkt bereits aktiviert sein muss:

app.use(passport.session());

Für das Verwalten der Daten des Anwenders in der Session stellt Passport zwei Funktionen zur Verfügung, serializeUser und deserializeUser, die vom Entwickler mit Leben befüllt werden müssen. In der Regel genügt es, beim Serialisieren die ID des Anwenders zu extrahieren,

passport.serializeUser(function (user, done) {
done(null, user.id);
});

und aus ihr beim Deserialisieren wieder das vollständige Profil zu laden:

passport.deserializeUser(function (id, done) {
getUserById(id, function (err, profile) {
done(err, profile);
});
});

Wird irgendwann die Entscheidung getroffen, alternativ oder ergänzend ein anderes Verfahren zur Authentifizierung des Anwenders zu verwenden, genügt es, das passende Modul für Passport zu installieren und zu konfigurieren – beispielsweise OAuth oder OpenID. Eine vollständige Liste aller verfügbaren Strategien findet sich im Wiki von Passport.

tl;dr: Das Framework Express lässt sich durch das Modul Passport um Möglichkeiten zur Authentifizierung erweitern. Unterstützt werden über 140 Verfahren, unter anderem OAuth und OpenID. Der Wechsel der verschiedenen Verfahren fällt auf diesem Weg ausgesprochen leicht. ()