DIY: Auth in Next.js – weniger Magie, mehr Kontrolle

Ein Schweizer Taschenmesser, ein Schloss und ein lächelndes Emoji erscheinen über "DIY: AUTH NEXT.JS" auf schwarzem Hintergrund.

In meiner Zeit als Java-Entwickler (ja, ich hab's getan – Java! 🙈), insbesondere mit Spring Boot, war die Welt der Authentifizierung einfach. Zwei Zeilen im application.yaml – und zagg-💥, ein sicherer Login stand.

Die Libs waren ausgereift und sicher und so vorkonfiguriert, dass man eigentlich nichts falsch machen konnte. Ein ungeschriebenes Gesetz von mir lautetet damals:

«Auth baut man nicht selbst.»

Good old Java Developer

Punkt.

Doch die Realität moderner Webanwendungen, insbesondere im Next.js-Kosmos mit der ganzen Palette von Server-Side Rendering über Streaming von Komponenten bis zu API Endpunkten, ist eine andere. Hier geht es um komplexe Frontends, massgeschneiderte User Experience und spezifische Anforderungen, die oft über das hinausgehen, was All-in-One-Lösungen standardmässig bieten. Und genau hier bin ich an einen Punkt gekommen, wo sich meine Perspektive geändert hat.

Nicht, weil Security plötzlich einfach wäre. Sondern weil in modernen Next.js-Projekten Customizing wichtiger ist als ein starrer "One-size-fits-all"-Ansatz. Wenn du Auth wirklich verstehen und steuern willst, führt heute kein Weg mehr an einem eigenen Setup vorbei.

🤔 Wer sich jetzt fragt: "Wow cool, dann darf ich jetzt also alles selbst bauen – inklusive Benutzername/Passwort Verwaltung etc?"

Ein Mann im Anzug steht in einem Büro und wirkt schockiert oder überrascht, mit leicht geöffnetem Mund und großen Augen.

Auf keinen Fall! Eigene Passwort-Logins zu bauen ist immer noch absolut Tabu!!!iii!! 🙅 Dafür gibt’s ausgereifte Lösungen wie Zitadel oder diverse Social-Login-Provider. Mir geht’s hier nur um die OIDC-Integration.

Wenn dein Auth-Flow nicht Standard ist

Moderne Web-Apps haben oft komplexe Anforderungen an Auth:

  • Individuelle User-/Session-Modelle
  • Externe Anbieter mit leicht abweichendem Verhalten
  • Serverseitige Kontrolle über Sessions
  • UX ohne „Login-Flicker“ bei Refresh
  • Unterstützung von Backchannel Logout

Tools wie NextAuth (oder neu mit v5 Auth.js, welches schon seeeehr lange Beta ist) waren dafür nie gemacht. Sie sind super für den schnellen Einstieg (#prototyping) – aber wenn du 80 % deines Auth-Flows danach patchen musst, kannst du es auch gleich richtig machen.

Genau da setzte die Auth-Library Lucia an – eine sehr simple Auth-Library, die ich sogar in einem Blogpost vorgestellt habe. Leider ist Lucia inzwischen deprecated. ⚰️🥲

Aber der spannende Punkt ist: Das kleine bisschen, das Lucia abgenommen hat – im Wesentlichen das Zusammenstöpseln der unteren Bausteine – lässt sich auch problemlos selbst umsetzen. Und zwar so, dass man noch flexibler ist und die sicherheitskritischen Teile trotzdem ausgereiften Libraries überlässt.

Und so bin ich heute an einem Punkt, wo ich sage: Ja, man kann OIDC auch selbst machen – und das sogar richtig gut

Was ein stabiler, sicherer OIDC-Flow in Next.js wirklich braucht

🧊 1. Arctic – OIDC wie es sein sollte

Arctic kümmert sich um das, was OIDC am komplexesten macht:

  • PKCE und State-Handling
  • Login-URLs generieren
  • Code austauschen gegen Token
  • Multi-Provider-Unterstützung

Und das alles ohne dir vorzuschreiben, wie du deine Session speicherst oder wie dein User-Modell aussehen soll.

🧪 2. Oslo – JWTs & Hashes ohne Bloat

Oslo liefert genau das, was man für Security auf Node-Seite braucht:

  • JWT verifizieren (z. B. ID-Tokens vom Provider)
  • Hashes für Secrets, Passwörter, Refresh-Token-Keys etc.
  • CSRF-Tokens generieren

Dabei bleibt Oslo bewusst klein und unaufgeregt. Perfekt für eigene Auth-Backends.

🧠 3. Redis – Sessions, wie sie sein sollten

Session Handling ist oft der wackeligste Teil in Web-Apps. Viele setzen auf verschlüsselte JWTs als Session-Token – aber das hat Tücken:

  • Kein serverseitiges Invalidieren
  • Kein einfaches TTL-Handling
  • Kein Logout ohne Token-Blacklisting
  • Probleme mit Refresh Tokens (Cookie Update in Next.js nicht immer möglich)

Mit Redis kannst du Sessions richtig abbilden:

  • Token referenziert Session-ID
  • Session ist serverseitig gespeichert und steuerbar
  • Nutzer- und Sessiondaten klar getrennt
  • Am besten noch serverseitig verschlüsselt

👉 Redis ist hier mein Favorit, aber letztlich kann man jede schnelle, zuverlässige Datenbank verwenden. Wichtig ist nur, dass Sessions serverseitig gespeichert und zentral steuerbar bleiben.

🔁 4. Refresh Tokens – für sanfte UX ohne Security-Kompromisse

Statt das Access Token ewig gültig zu halten, ist es ein Muss auf kurzlebige Tokens plus Refresh Flow zu setzen. Das bringt:

  • Sicherheit (Token Diebstahl wird schnell irrelevant)
  • UX (kein Login-Flicker, keine harten Redirects)
  • Kontrolle (Refresh nur serverseitig erlaubt)

Der Refresh Flow läuft voll backendseitig.

🚪 5. Backchannel Logout – wenn’s dein Provider hergibt

Backchannel Logout ist die sauberste Methode, Sessions zentral zu beenden. Wird z. B. ein Nutzer im zentralen SSO-System ausgeloggt, kann der OIDC-Provider einen Logout-Hook an dein Backend schicken – und du killst die Session direkt in Redis.

Kein Polling. Kein clientseitiger Check mehr nötig.

🔒 6. Backend-for-Frontend (BFF) – für maximale Kontrolle

Ein dediziertes Backend-for-Frontend (BFF) sorgt dafür, dass Access Tokens nie im Client landen – kein localStorage, kein Risiko durch XSS. Wenn die Session auf dem Server ausläuft oder aktiv beendet wird, kann der Client nichts mehr tun – kein Flicker, kein Pseudo-Cleanup.

Das BFF wird damit zur zentralen Instanz für Login, Refresh, Logout und User-Daten – und macht deinen Auth-Flow sicher, robust und übersichtlich. Und falls du bis hier gelesen hast: Respekt! 🎉

Fazit: Auth ist kein Hexenwerk – wenn man weiss, was man tut

Ich dachte lange, Auth sei ein Mienenfeld, das man besser nicht selbst betritt. Heute sehe ich es anders: Wenn du verstehst, was du brauchst – und weisst, was du tust – kannst und solltest du dir mit Arctic, Oslo & Redis einen Auth-Flow bauen, der sicherer, flexibler und langfristig wartbarer ist als viele All-in-One-Lösungen.

Und das Beste: Du hast die volle Kontrolle.

Keine „magischen Defaults“. Keine Library-Blackbox. Sondern Auth, wie sie zu deiner App passt.

PS: Die Dokumentation von Arctic und Oslo ist super, schau dort unbedingt auch mal rein.

Geschrieben von
Lorenz Bösch

Next.js|August 2025

Weitere Artikel