Fast jede Anwendung hat die Anforderung, sich in das System einzuloggen. Dieses Feature hat oft die gleichen Anforderungen und wird trotzdem häufig unterschiedlich gebaut. Username und Passwort eingeben, mit dem Wert in der Datenbank vergleichen – fertig.
Doch wie wird das Passwort verschlüsselt, wie werden die Daten übertragen? Was ist mit besseren Anbindungen, wie Social login oder Multifactor Authentifizierung.
Mit Tools, wie Keycloak Auth0, werden diese Anforderungen optimal umgesetzt. Aber auch diese Tools bieten unterschiedliche Implementierungen. In diesem Blog soll beleuchtet werden, welche Varianten es gibt und was unsere präferierte Variante ist.
JWT vs. Cookiebased
Viele Tutorials implementieren die Cookiebasedvariante ohne auf diese beiden Varianten hinzuweisen. Der Grund hierfür ist, dass in dieser Variante wenig implementiert werden muss. Spring Security kann mit wenigen Konfigurationen so konfiguriert werden, dass die Cookiebasedvariante genutzt wird. Dies funktioniert gut, bis Probleme auftreten.
Die meisten Anwendungen, die wir aktuell entwickeln, haben eine Single Page Application im Frontend und ein Backend in C#, Java, JavaScript oder Ähnliches. Da hier zwei unterschiedliche Anwendungen miteinander kommunizieren müssen, sind wir der Meinung, dass die Variante mit einem JWT die bessere Alternative ist.
Implementierung / Erstellung des JWT
Der Ort der JWT Generierung ist die Single Page Application. Die Identity Provider stellen ein Framework bereit, welches via npm installiert wird. Dieses Framework hat eine Login-Methode oder Ähnliches, welche nur aufgerufen werden muss. Die Anwendung wird daraufhin mit einer Weiterleitung auf den Identity Provider weitergeleitet und nach erfolgreichem Login mit dem Token auf die Single Page Application zurück geroutet.
Immer wenn das Login nicht erfolgreich durchgeführt wurde, müssen alle schützenswerten Seiten geblockt werden.
Der JWT kann als Bearer im Authorizationheader versendet werden, sodass das Backend diesen JWT überreicht bekommt.
Validierung des JWT
Alle schützenswerten Endpunkte müssen mit einem Filter geschützt werden. Diese Filter werden von allen relevanten Frameworks bereitgestellt. In diesem Filter müssen folgende Punkte geprüft werden.
- Ist der Token noch valide?
- Ist der Token richtig signiert?
- Sind weitere Claims korrekt?
Asymmetrisch oder Symmetrisch
Ein JWT muss in der Regel nicht verschlüsselt werden und der Inhalt kann auf jwt.io immer eingesehen werden. Dies ist auch kein Problem, da die Schlüssel signiert werden und diese Tokens daher nicht manipuliert werden können. Hierbei gibt es zwei Varianten. Bei der symmetrischen Signierung wird der Schlüssel mit einem geheimen Schlüssel abgeglichen. Bei der asymmetrischen Signierung wird eine “well known” Adresse aufgerufen, damit geprüft wird, ob dieser Token korrekt ist. Diese Variante wird von den meisten Identity Providern standardmäßig implementiert und diese Implementierung ist aus unserer Sicht die richtige.
Fazit
Mit diesen wenigen einfachen Regeln kann man sich in dem Dokumentationsjungle der unterschiedlichen Identity Provider hoffentlich zurecht finden. Das gleiche gilt auch, sofern Azure AD, google etc. angebunden wird. Wir hoffen, dass diese Regeln helfen und wir freuen uns über Success Storys von erfolgreichen Anwendungen.