Authentifizierung in Next.js implementieren
Das Verständnis von Authentifizierung ist entscheidend, um die Daten Ihrer Anwendung zu schützen. Diese Seite führt Sie durch die React- und Next.js-Funktionen, die Sie für die Implementierung von Authentifizierung verwenden können.
Bevor Sie beginnen, ist es hilfreich, den Prozess in drei Konzepte zu unterteilen:
- Authentifizierung: Überprüft, ob der Benutzer derjenige ist, für den er sich ausgibt. Der Benutzer muss seine Identität mit etwas nachweisen, das er besitzt, wie z.B. einem Benutzernamen und Passwort.
- Sitzungsverwaltung: Verfolgt den Authentifizierungsstatus des Benutzers über Anfragen hinweg.
- Autorisierung: Entscheidet, auf welche Routen und Daten der Benutzer zugreifen kann.
Dieses Diagramm zeigt den Authentifizierungsfluss mit React- und Next.js-Funktionen:

Die Beispiele auf dieser Seite zeigen aus didaktischen Gründen eine grundlegende Authentifizierung mit Benutzername und Passwort. Obwohl Sie eine eigene Authentifizierungslösung implementieren können, empfehlen wir aus Sicherheits- und Einfachheitsgründen die Verwendung einer Authentifizierungsbibliothek. Diese bieten integrierte Lösungen für Authentifizierung, Sitzungsverwaltung und Autorisierung sowie zusätzliche Funktionen wie Social Logins, Multi-Faktor-Authentifizierung und rollenbasierte Zugriffskontrolle. Eine Liste finden Sie im Abschnitt Authentifizierungsbibliotheken.
Authentifizierung
Registrierungs- und Anmeldefunktionalität
Sie können das <form>
-Element mit Server Actions von React und useActionState
verwenden, um Benutzeranmeldedaten zu erfassen, Formularfelder zu validieren und die API oder Datenbank Ihres Authentifizierungsanbieters aufzurufen.
Da Server Actions immer auf dem Server ausgeführt werden, bieten sie eine sichere Umgebung für die Handhabung der Authentifizierungslogik.
Hier sind die Schritte zur Implementierung der Registrierungs-/Anmeldefunktionalität:
1. Benutzeranmeldedaten erfassen
Um Benutzeranmeldedaten zu erfassen, erstellen Sie ein Formular, das beim Absenden eine Server Action aufruft. Beispielsweise ein Registrierungsformular, das den Namen, die E-Mail und das Passwort des Benutzers akzeptiert:
2. Formularfelder auf dem Server validieren
Verwenden Sie die Server Action, um die Formularfelder auf dem Server zu validieren. Falls Ihr Authentifizierungsanbieter keine Formularvalidierung bietet, können Sie eine Schema-Validierungsbibliothek wie Zod oder Yup verwenden.
Am Beispiel von Zod können Sie ein Formularschema mit entsprechenden Fehlermeldungen definieren:
Um unnötige Aufrufe an die API oder Datenbank Ihres Authentifizierungsanbieters zu vermeiden, können Sie in der Server Action frühzeitig return
aufrufen, falls Formularfelder nicht dem definierten Schema entsprechen.
Zurück in Ihrer <SignupForm />
können Sie den useActionState
-Hook von React verwenden, um Validierungsfehler während des Formularversands anzuzeigen:
Wissenswert:
- In React 19 enthält
useFormStatus
zusätzliche Schlüssel im zurückgegebenen Objekt, wie data, method und action. Falls Sie nicht React 19 verwenden, ist nur derpending
-Schlüssel verfügbar.- Bevor Sie Daten mutieren, sollten Sie stets sicherstellen, dass ein Benutzer auch autorisiert ist, die Aktion durchzuführen. Siehe Authentifizierung und Autorisierung.
3. Benutzer erstellen oder Anmeldedaten prüfen
Nach der Validierung der Formularfelder können Sie ein neues Benutzerkonto erstellen oder überprüfen, ob der Benutzer existiert, indem Sie die API oder Datenbank Ihres Authentifizierungsanbieters aufrufen.
Fortsetzung des vorherigen Beispiels:
Nach erfolgreicher Erstellung des Benutzerkontos oder Überprüfung der Anmeldedaten können Sie eine Sitzung erstellen, um den Authentifizierungsstatus des Benutzers zu verwalten. Abhängig von Ihrer Sitzungsverwaltungsstrategie kann die Sitzung in einem Cookie oder einer Datenbank oder beidem gespeichert werden. Fahren Sie mit dem Abschnitt Sitzungsverwaltung fort, um mehr zu erfahren.
Tipps:
- Das obige Beispiel ist ausführlich, da es die Authentifizierungsschritte zu Schulungszwecken aufschlüsselt. Dies zeigt, dass die Implementierung einer eigenen sicheren Lösung schnell komplex werden kann. Erwägen Sie die Verwendung einer Auth Library, um den Prozess zu vereinfachen.
- Um die Benutzererfahrung zu verbessern, können Sie nach doppelten E-Mails oder Benutzernamen früher im Registrierungsprozess suchen. Zum Beispiel während der Benutzer einen Benutzernamen eingibt oder das Eingabefeld den Fokus verliert. Dies kann unnötige Formularübermittlungen verhindern und dem Benutzer sofortiges Feedback geben. Sie können Anfragen mit Bibliotheken wie use-debounce entprellen, um die Häufigkeit dieser Prüfungen zu steuern.
Sitzungsverwaltung
Die Sitzungsverwaltung stellt sicher, dass der authentifizierte Zustand des Benutzers über Anfragen hinweg erhalten bleibt. Sie umfasst das Erstellen, Speichern, Aktualisieren und Löschen von Sitzungen oder Token.
Es gibt zwei Arten von Sitzungen:
- Zustandslos (Stateless): Sitzungsdaten (oder ein Token) werden in den Cookies des Browsers gespeichert. Der Cookie wird mit jeder Anfrage gesendet, was die Überprüfung der Sitzung auf dem Server ermöglicht. Diese Methode ist einfacher, kann aber weniger sicher sein, wenn sie nicht korrekt implementiert wird.
- Datenbank (Database): Sitzungsdaten werden in einer Datenbank gespeichert, wobei der Browser des Benutzers nur die verschlüsselte Sitzungs-ID erhält. Diese Methode ist sicherer, kann aber komplex sein und mehr Serverressourcen verbrauchen.
Gut zu wissen: Während Sie beide Methoden oder beide verwenden können, empfehlen wir die Verwendung einer Sitzungsverwaltungsbibliothek wie iron-session oder Jose.
Zustandslose Sitzungen (Stateless Sessions)
Um zustandslose Sitzungen zu erstellen und zu verwalten, müssen Sie einige Schritte befolgen:
- Generieren Sie einen geheimen Schlüssel, der zum Signieren Ihrer Sitzung verwendet wird, und speichern Sie ihn als Umgebungsvariable.
- Schreiben Sie Logik zum Verschlüsseln/Entschlüsseln von Sitzungsdaten mit einer Sitzungsverwaltungsbibliothek.
- Verwalten Sie Cookies mit der Next.js
cookies
API.
Zusätzlich zu den oben genannten Punkten sollten Sie Funktionen hinzufügen, um die Sitzung zu aktualisieren (oder zu erneuern), wenn der Benutzer zur Anwendung zurückkehrt, und die Sitzung zu löschen, wenn der Benutzer sich abmeldet.
Gut zu wissen: Überprüfen Sie, ob Ihre Auth Library Sitzungsverwaltung beinhaltet.
1. Generieren eines geheimen Schlüssels
Es gibt mehrere Möglichkeiten, einen geheimen Schlüssel zum Signieren Ihrer Sitzung zu generieren. Zum Beispiel können Sie den Befehl openssl
in Ihrem Terminal verwenden:
Dieser Befehl generiert eine 32-stellige zufällige Zeichenfolge, die Sie als geheimen Schlüssel verwenden und in Ihrer Umgebungsvariablendatei speichern können:
Sie können dann auf diesen Schlüssel in Ihrer Sitzungsverwaltungslogik verweisen:
2. Verschlüsseln und Entschlüsseln von Sitzungen
Als Nächstes können Sie Ihre bevorzugte Sitzungsverwaltungsbibliothek verwenden, um Sitzungen zu verschlüsseln und zu entschlüsseln. Fortsetzung des vorherigen Beispiels verwenden wir Jose (kompatibel mit der Edge Runtime) und Reacts server-only
Paket, um sicherzustellen, dass Ihre Sitzungsverwaltungslogik nur auf dem Server ausgeführt wird.
Tipps:
- Die Nutzdaten sollten die minimalen, eindeutigen Benutzerdaten enthalten, die in nachfolgenden Anfragen verwendet werden, wie z.B. die Benutzer-ID, Rolle usw. Sie sollten keine personenbezogenen Informationen wie Telefonnummer, E-Mail-Adresse, Kreditkarteninformationen usw. oder sensible Daten wie Passwörter enthalten.
3. Cookies setzen (empfohlene Optionen)
Um die Sitzung in einem Cookie zu speichern, verwenden Sie die Next.js cookies
API. Der Cookie sollte auf dem Server gesetzt werden und die empfohlenen Optionen enthalten:
- HttpOnly: Verhindert den Zugriff auf den Cookie durch clientseitiges JavaScript.
- Secure: Verwendet https zum Senden des Cookies.
- SameSite: Gibt an, ob der Cookie mit cross-site-Anfragen gesendet werden kann.
- Max-Age oder Expires: Löscht den Cookie nach einem bestimmten Zeitraum.
- Path: Definiert den URL-Pfad für den Cookie.
Weitere Informationen zu diesen Optionen finden Sie unter MDN.
Zurück in Ihrer Server-Aktion können Sie die Funktion createSession()
aufrufen und die redirect()
API verwenden, um den Benutzer auf die entsprechende Seite weiterzuleiten:
Tipps:
- Cookies sollten auf dem Server gesetzt werden, um clientseitige Manipulationen zu verhindern.
- 🎥 Ansehen: Erfahren Sie mehr über zustandslose Sitzungen und Authentifizierung mit Next.js → YouTube (11 Minuten).
Aktualisieren (oder Erneuern) von Sitzungen
Sie können auch die Ablaufzeit der Sitzung verlängern. Dies ist nützlich, um den Benutzer angemeldet zu halten, nachdem er wieder auf die Anwendung zugreift. Zum Beispiel:
Tipp: Überprüfen Sie, ob Ihre Auth Library Refresh-Tokens unterstützt, die zur Verlängerung der Benutzersitzung verwendet werden können.
Löschen der Sitzung
Um die Sitzung zu löschen, können Sie das Cookie entfernen:
Anschließend können Sie die Funktion deleteSession()
in Ihrer Anwendung wiederverwenden, beispielsweise beim Abmelden:
Datenbank-Sitzungen
Um Datenbank-Sitzungen zu erstellen und zu verwalten, müssen Sie folgende Schritte durchführen:
- Erstellen Sie eine Tabelle in Ihrer Datenbank zur Speicherung von Sitzungen und Daten (oder prüfen Sie, ob Ihre Authentifizierungsbibliothek dies übernimmt).
- Implementieren Sie Funktionen zum Einfügen, Aktualisieren und Löschen von Sitzungen
- Verschlüsseln Sie die Sitzungs-ID, bevor Sie sie im Browser des Benutzers speichern, und stellen Sie sicher, dass Datenbank und Cookie synchron bleiben (dies ist optional, wird aber für optimistische Authentifizierungsprüfungen in Middleware empfohlen).
Beispiel:
Tipps:
- Für schnelleren Zugriff können Sie Server-Caching für die Lebensdauer der Sitzung in Betracht ziehen. Sie können die Sitzungsdaten auch in Ihrer primären Datenbank belassen und Datenanfragen kombinieren, um die Anzahl der Abfragen zu reduzieren.
- Sie können Datenbank-Sitzungen für erweiterte Anwendungsfälle verwenden, z.B. um den Zeitpunkt der letzten Anmeldung eines Benutzers zu verfolgen, die Anzahl aktiver Geräte oder um Benutzern die Möglichkeit zu geben, sich von allen Geräten abzumelden.
Nach der Implementierung der Sitzungsverwaltung müssen Sie Autorisierungslogik hinzufügen, um zu steuern, was Benutzer in Ihrer Anwendung aufrufen und tun können. Fahren Sie mit dem Abschnitt Autorisierung fort, um mehr zu erfahren.
Autorisierung
Sobald ein Benutzer authentifiziert ist und eine Sitzung erstellt wurde, können Sie die Autorisierung implementieren, um zu steuern, was der Benutzer in Ihrer Anwendung aufrufen und tun kann.
Es gibt zwei Haupttypen von Autorisierungsprüfungen:
- Optimistisch: Prüft, ob der Benutzer berechtigt ist, eine Route aufzurufen oder eine Aktion auszuführen, indem die im Cookie gespeicherten Sitzungsdaten verwendet werden. Diese Prüfungen sind nützlich für schnelle Operationen, wie das Anzeigen/Ausblenden von UI-Elementen oder das Umleiten von Benutzern basierend auf Berechtigungen oder Rollen.
- Sicher: Prüft, ob der Benutzer berechtigt ist, eine Route aufzurufen oder eine Aktion auszuführen, indem die in der Datenbank gespeicherten Sitzungsdaten verwendet werden. Diese Prüfungen sind sicherer und werden für Operationen verwendet, die Zugriff auf sensible Daten oder Aktionen erfordern.
Für beide Fälle empfehlen wir:
- Erstellen einer Datenzugriffsschicht (DAL), um Ihre Autorisierungslogik zu zentralisieren
- Verwenden von Data Transfer Objects (DTO), um nur die notwendigen Daten zurückzugeben
- Optional die Verwendung von Middleware für optimistische Prüfungen.
Optimistische Prüfungen mit Middleware (Optional)
Es gibt Fälle, in denen Sie Middleware verwenden und Benutzer basierend auf Berechtigungen umleiten möchten:
- Um optimistische Prüfungen durchzuführen. Da Middleware bei jeder Route ausgeführt wird, ist sie eine gute Möglichkeit, Umleitungslogik zu zentralisieren und nicht autorisierte Benutzer vorzufiltern.
- Um statische Routen zu schützen, die Daten zwischen Benutzern teilen (z.B. Inhalte hinter einer Paywall).
Da Middleware jedoch bei jeder Route ausgeführt wird, einschließlich vorab geladener Routen, ist es wichtig, die Sitzung nur aus dem Cookie zu lesen (optimistische Prüfungen) und Datenbankprüfungen zu vermeiden, um Leistungsprobleme zu verhindern.
Beispiel:
Während Middleware für erste Prüfungen nützlich sein kann, sollte sie nicht Ihre einzige Verteidigungslinie zum Schutz Ihrer Daten sein. Die meisten Sicherheitsprüfungen sollten so nah wie möglich an Ihrer Datenquelle durchgeführt werden, siehe Datenzugriffsschicht für weitere Informationen.
Tipps:
- In Middleware können Sie Cookies auch mit
req.cookies.get('session').value
lesen.- Middleware verwendet die Edge Runtime, prüfen Sie, ob Ihre Authentifizierungsbibliothek und Ihre Sitzungsverwaltungsbibliothek kompatibel sind.
- Sie können die Eigenschaft
matcher
in der Middleware verwenden, um festzulegen, auf welchen Routen Middleware ausgeführt werden soll. Für die Authentifizierung wird jedoch empfohlen, Middleware auf allen Routen auszuführen.
Erstellen einer Datenzugriffsschicht (DAL)
Wir empfehlen die Erstellung einer DAL, um Ihre Datenanfragen und Autorisierungslogik zu zentralisieren.
Die DAL sollte eine Funktion enthalten, die die Sitzung des Benutzers während der Interaktion mit Ihrer Anwendung überprüft. Mindestens sollte die Funktion prüfen, ob die Sitzung gültig ist, und dann den Benutzer umleiten oder die für weitere Anfragen benötigten Benutzerinformationen zurückgeben.
Erstellen Sie beispielsweise eine separate Datei für Ihre DAL, die eine Funktion verifySession()
enthält. Verwenden Sie dann die cache-API von React, um den Rückgabewert der Funktion während eines React-Renderdurchlaufs zwischenzuspeichern:
Sie können dann die Funktion verifySession()
in Ihren Datenanfragen, Server-Aktionen und Route Handlern aufrufen:
Tipp:
- Eine DAL kann zum Schutz von Daten verwendet werden, die zur Laufzeit abgerufen werden. Für statische Routen, die Daten zwischen Benutzern teilen, werden die Daten jedoch zum Build-Zeitpunkt und nicht zur Laufzeit abgerufen. Verwenden Sie Middleware, um statische Routen zu schützen.
- Für sichere Prüfungen können Sie überprüfen, ob die Sitzung gültig ist, indem Sie die Sitzungs-ID mit Ihrer Datenbank vergleichen. Verwenden Sie die cache-Funktion von React, um unnötige doppelte Anfragen an die Datenbank während eines Renderdurchlaufs zu vermeiden.
- Sie können verwandte Datenanfragen in einer JavaScript-Klasse konsolidieren, die
verifySession()
vor allen Methoden ausführt.
Verwendung von Data Transfer Objects (DTOs)
Beim Abrufen von Daten wird empfohlen, nur die notwendigen Daten zurückzugeben, die in Ihrer Anwendung verwendet werden, und nicht ganze Objekte. Wenn Sie beispielsweise Benutzerdaten abrufen, sollten Sie nur die Benutzer-ID und den Namen zurückgeben, anstatt das gesamte Benutzerobjekt, das Passwörter, Telefonnummern usw. enthalten könnte.
Falls Sie jedoch keine Kontrolle über die zurückgegebene Datenstruktur haben oder in einem Team arbeiten, in dem Sie vermeiden möchten, dass ganze Objekte an den Client übergeben werden, können Sie Strategien wie die Spezifizierung der Felder verwenden, die sicher für den Client freigegeben werden können.
Indem Sie Ihre Datenanfragen und Autorisierungslogik in einer DAL zentralisieren und DTOs verwenden, können Sie sicherstellen, dass alle Datenanfragen sicher und konsistent sind, was die Wartung, Überprüfung und Fehlerbehebung bei der Skalierung Ihrer Anwendung erleichtert.
Gut zu wissen:
- Es gibt verschiedene Möglichkeiten, ein DTO zu definieren, von der Verwendung von
toJSON()
über individuelle Funktionen wie im obigen Beispiel bis hin zu JS-Klassen. Da dies JavaScript-Muster und keine React- oder Next.js-Funktionen sind, empfehlen wir, einige Recherchen durchzuführen, um das beste Muster für Ihre Anwendung zu finden.- Erfahren Sie mehr über Sicherheitsbest Practices in unserem Artikel zur Sicherheit in Next.js.
Server-Komponenten
Authentifizierungsprüfungen in Server-Komponenten sind nützlich für rollenbasierte Zugriffe. Beispielsweise, um Komponenten basierend auf der Rolle des Benutzers bedingt zu rendern:
Im Beispiel verwenden wir die Funktion verifySession()
aus unserer DAL, um nach 'admin', 'user' und nicht autorisierten Rollen zu prüfen. Dieses Muster stellt sicher, dass jeder Benutzer nur mit den für seine Rolle geeigneten Komponenten interagiert.
Layouts und Authentifizierungsprüfungen
Aufgrund des Partiellen Renderings ist Vorsicht geboten, wenn Prüfungen in Layouts durchgeführt werden, da diese bei der Navigation nicht neu gerendert werden, was bedeutet, dass die Benutzersitzung nicht bei jedem Routenwechsel überprüft wird.
Stattdessen sollten Sie die Prüfungen in der Nähe Ihrer Datenquelle oder der Komponente durchführen, die bedingt gerendert wird.
Betrachten Sie beispielsweise ein gemeinsames Layout, das die Benutzerdaten abruft und das Benutzerbild in einer Navigation anzeigt. Anstatt die Authentifizierungsprüfung im Layout durchzuführen, sollten Sie die Benutzerdaten (getUser()
) im Layout abrufen und die Authentifizierungsprüfung in Ihrer DAL durchführen.
Dies stellt sicher, dass die Authentifizierungsprüfung überall in Ihrer Anwendung durchgeführt wird, wo getUser()
aufgerufen wird, und verhindert, dass Entwickler vergessen, zu überprüfen, ob der Benutzer berechtigt ist, auf die Daten zuzugreifen.
Gut zu wissen:
- Ein gängiges Muster in SPAs ist,
return null
in einem Layout oder einer Top-Level-Komponente zurückzugeben, wenn ein Benutzer nicht autorisiert ist. Dieses Muster wird nicht empfohlen, da Next.js-Anwendungen mehrere Einstiegspunkte haben, die nicht verhindern, dass verschachtelte Routensegmente und Server-Aktionen aufgerufen werden können.
Server-Aktionen
Behandeln Sie Server-Aktionen mit den gleichen Sicherheitsüberlegungen wie öffentlich zugängliche API-Endpunkte und überprüfen Sie, ob der Benutzer eine Mutation durchführen darf.
Im folgenden Beispiel überprüfen wir die Rolle des Benutzers, bevor die Aktion fortgesetzt wird:
Route-Handler
Behandeln Sie Route-Handler mit den gleichen Sicherheitsüberlegungen wie öffentlich zugängliche API-Endpunkte und überprüfen Sie, ob der Benutzer berechtigt ist, auf den Route-Handler zuzugreifen.
Beispiel:
Das obige Beispiel zeigt einen Route-Handler mit einer zweistufigen Sicherheitsprüfung. Zuerst wird auf eine aktive Sitzung geprüft, und dann wird überprüft, ob der angemeldete Benutzer ein 'admin' ist.
Kontext-Provider
Die Verwendung von Kontext-Providern für die Authentifizierung funktioniert aufgrund der Verschachtelung. Allerdings wird React context
in Server-Komponenten nicht unterstützt, was sie nur für Client-Komponenten anwendbar macht.
Dies funktioniert, aber alle untergeordneten Server-Komponenten werden zuerst auf dem Server gerendert und haben keinen Zugriff auf die Sitzungsdaten des Kontext-Providers:
Wenn Sitzungsdaten in Client-Komponenten benötigt werden (z.B. für clientseitiges Datenabrufen), verwenden Sie Reacts taintUniqueValue
API, um zu verhindern, dass sensible Sitzungsdaten dem Client ausgesetzt werden.
Ressourcen
Nachdem Sie nun etwas über Authentifizierung in Next.js gelernt haben, finden Sie hier Next.js-kompatible Bibliotheken und Ressourcen, die Ihnen bei der Implementierung einer sicheren Authentifizierung und Sitzungsverwaltung helfen:
Authentifizierungsbibliotheken
Sitzungsverwaltungsbibliotheken
Weiterführende Literatur
Um weiter über Authentifizierung und Sicherheit zu lernen, lesen Sie die folgenden Ressourcen: