© Sentavio/Shutterstock.com
Authentifizierung mit React und Express umgesetzt

Erhöhte Sicherheitsvorkehrungen


Bei der Implementierung einer Single-Page-Applikation gibt es eine Reihe von Standardfunktionalitäten, die in fast jeder Applikation anzutreffen sind. Dazu zählen die Anzeige von Informationen, die Kommunikation mit einem Server sowie die Umsetzung von Formularen. Was allerdings in vielen Tutorials außen vor bleibt, ist die Authentifizierung von Benutzern. Es lohnt sich, dieses Thema einmal näher zu beleuchten.

Die Authentifizierung von Benutzern ist ein wesentliches Feature in vielen Applikationen, denn nicht jeder Benutzer darf jeden Teil einer Applikation verwenden und auch nicht alle Daten sehen oder modifizieren. Aus diesem Grund beschäftigen wir uns in diesem Artikel mit der konkreten Implementierung einer Authentifizierungsstrategie in einer Single-Page-Applikation. Das Frontend wird mit React, das Backend mit Express umgesetzt.

Authentifizierung – das Warum und das Wie

Warum Authentifizierung notwendig ist, lässt sich leicht anhand eines praktischen Beispiels erklären. Stellen Sie sich vor, Sie arbeiten mit einer Applikation, mit der Sie Benutzerdaten verwalten können. In der Applikation werden neben dem Namen und der Adresse auch Kontaktinformationen wie Telefonnummer und E-Mail-Adresse sowie Konto- und Kreditkartendaten gespeichert. Auf solche Daten dürfen natürlich nur berechtigte Personen zugreifen. Üblicherweise gibt sich ein Benutzer mit einer Kombination aus einem Benutzernamen und einem Passwort gegenüber einem System zu erkennen. Basierend auf diesen Informationen können Sie ein Rollen- und Rechtesystem aufbauen, mit dessen Hilfe sich der Zugriff auf bestimmte Ressourcen noch besser steuern lässt.

Nach der Eingabe der Daten werden diese zum Server übermittelt. Hier entsteht das erste potenzielle Sicherheitsproblem, da die Daten so gesendet werden müssen, dass kein potenzieller Angreifer in der Lage ist, sie abzufangen. Nach einer Prüfung durch den Server erhält der Benutzer entweder eine positive oder eine negative Rückmeldung. War die Anmeldung erfolgreich, müssen Sie dafür sorgen, dass der Benutzer über eine gewisse Zeitspanne angemeldet bleibt, damit er nicht bei jeder Anfrage erneut Benutzernamen und Passwort übermitteln muss. Der letzte Schritt im Authentifizierungsprozess ist die Abmeldung. Hat der Benutzer seine Interaktion beendet, wird die aktuelle Sitzung entweder nach Ablauf der Gültigkeitsfrist automatisch beendet oder der Benutzer führt dies manuell durch.

Neben einigen Sicherheitsgesichtspunkten, die Sie beachten sollten, ist die Entscheidung für einen konkreten Authentifizierungsmechanismus einer der ersten und wichtigsten Aspekte für die konkrete Implementierung einer Authentifizierung in Ihrer Applikation. Hier stehen Ihnen mehrere etablierte Verfahren zur Verfügung, die alle ihre Vor- und Nachteile haben.

Cookiebasierte Sessions

So können Sie beispielsweise die Anmeldesitzung eines Benutzers cookiebasiert aufrechterhalten. Der Server stellt in diesem Fall einen Cookie für den Browser aus, der die Information enthält, dass der Benutzer angemeldet ist. Bei jeder Anfrage an den Server wird dieser Cookie ausgelesen und damit sichergestellt, dass nur angemeldete Benutzer Zugriff auf die Ressourcen erhalten. Dieser Mechanismus ist seit vielen Jahren für Webapplikationen etabliert und sehr gebräuchlich bei klassischen Multipage-Applikationen. Bei moderneren Single-Page-Applikationen kommen cookiebasierte Sessions eher selten zum Einsatz, da hier die Kopplung zwischen Frontend und Backend erhöht wird. Der Konsument, in diesem Fall das Frontend, muss Cookies unterstützen und bei der Verwendung der Schnittstelle einem festgelegten Workflow folgen.

Tokenbasierte Authentifizierung

Eine in Single-Page-Applikationen sehr weit verbreitete Variante sind tokenbasierte Sitzungen. Hierbei meldet sich ein Benutzer, wie schon bei der cookiebasierten Variante, mit seinem Benutzernamen und einem Passwort an. Doch statt dass Sie die Sitzung durch Cookies aufrechterhalten, stellt der Server ein Token aus, das bei jeder Anfrage vom Client an den Server übermittelt und von ihm geprüft wird.

OAuth 2

Bei OAuth 2 handelt es sich um eine Erweiterung der tokenbasierten Authentifizierung. Hierbei wird die Autorisierung von den Ressourcen getrennt. Es existieren zahlreiche OAuth-2-Anbieter wie beispielsweise Google, Twitter oder GitHub. Ihr eigener Server lagert die Autorisierung an einen weiteren Server aus. Damit müssen Sie sich nicht selbst um die Benutzerverwaltung kümmern. Aufgaben wie Registrierung und Passworthandling fallen also weg. Falls das Auslagern der Benutzerkonten für Ihre Applikation keine Option ist, können Sie natürlich auch Ihren eigenen OAuth-2-Server implementieren und damit die Verwaltung der Benutzerkonten wieder in die eigene Hand nehmen.

Die tokenbasierten Varianten etablieren sich zunehmend, da die Frontends immer mehr von den Backends entkoppelt werden. Im Folgenden werden wir uns die tokenbasierte Variante genauer ansehen.

Das Frontend – Create React App

Die einfachste Variante, um mit der Arbeit an einem React-Frontend zu beginnen, ist die mit dem create-react-app-Paket. Die einzige Voraussetzung für die Initialisierung ist eine Installation von Node.js auf dem Entwicklungssystem. Mit dem Kommando npm create react-app todo lassen Sie im aktuellen Verzeichnis ein neues Verzeichnis mit dem Namen todo anlegen. In diesem Verzeichnis werden alle erforderlichen Strukturen erzeugt und alle Abhängigkeiten heruntergeladen. Nach erfolgreicher Installation wechseln Sie mit dem Kommando cd todo in das Verzeichnis und starten die Applikation mit dem Kommando npm start.

Der erste Schritt, den Sie für die Authentifizierung unternehmen müssen, ist die Umsetzung des Anmeldeformulars. Dieses besteht in der Regel aus einem Eingabefeld für den Benutzernamen und einem weiteren für das Passwort; dieses sollte vom Typ Password sein, damit eventuelle Beobachter das Passwort nicht ausspähen können. In Listing 1 sehen Sie eine beispielhafte Implementierung der Login Component.

Listing 1: Login Component

import * as React from 'react'; export default class Login extends React.Component { state = { username: '', password: '', }; handleChange = event => { const { value, name } = event.target; this.setState({ [name]: value }); }; handleSubmit = async event => { event.preventDefault(); const response = await fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(this.state), }); }; render() { return ( <form onSubmit={this.handleSubmit}> <div> <label htmlFor="name">Username:</label> <input type="text" id="username" name="username" onChange={this.handleChange} /> </div> <div> <label htmlFor="password">Username:</label> <input type="password" id="password" name="password" onChange={this.handleChange} /> </div> <button type="submit">Login</button> </form> ); } }

Die Komponente ist als Klassenkomponente umgesetzt. Im State der Component werden Benutzername und Passwort gespeichert. In der render-Methode sorgen Sie für die Darstellung des Formulars. Die beiden Eingabefelder setzen Sie als Controlled Components um. Das bedeutet, dass die Formularfelder mit den jeweiligen Feldern im State verbunden sind. Die handleChange-Methode sorgt dafür, dass der State aktualisiert wird. So können Sie den Benutzernamen und das Passwort eingeben. Anschließend haben Sie über den State Zugriff auf die Werte. Die handleSubmit-Methode sendet die Daten zum Server, um ein Token für den Zugriff auf die Daten zu erhalten. Die einzelnen Methoden einer Component können Sie auch, wie hier im Beispiel, als async-Funktion umsetzen. Somit sind asynchrone Operationen, wie hier der fetch-Aufruf, besser zu handhaben.

Beim fetch-Aufruf selbst setzen Sie die Eigenschaft method auf den Wert POST, um diese HTTP-Methode zu verwenden. In der Headers-Eigenschaft setzen Sie den Content Type auf application/json. Damit weiß die Serverseite, wie die Nac...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang