Worum es geht
Ein Access-Token gilt nur kurz, bei Keycloak standardmäßig 5 Minuten. Damit niemand alle paar Minuten neu anmelden muss, holt der BFF rechtzeitig ein neues. Dafür schickt er das Refresh-Token an Keycloak. Das nennt man Refresh.
Warum sind Access-Tokens so kurz? Ein Access-Token wird bei jeder Anfrage nur lokal geprüft, niemand fragt dabei Keycloak. Ein entzogenes Recht verschwindet deshalb erst, wenn ein neues Token ausgestellt wird. Kurze Tokens halten diese Lücke klein. Siehe Warum ein Rechteentzug verzögert wirkt.
Der Zeitstrahl
gantt
title Ein Access-Token (Standard 5 Minuten)
dateFormat mm:ss
axisFormat %M:%S
section Token 1
gültig :t1, 00:00, 5m
Puffer, Refresh fällig :crit, r1, 03:30, 90s
section Token 2
gültig nach dem Refresh :t2, 03:30, 5m
Ab 90 Sekunden vor Ablauf gilt das Token als „bald abgelaufen“. Die nächste Abfrage der Sitzung löst dann den Refresh aus. Die Oberfläche fragt die Sitzung jede Minute ab und jedes Mal, wenn der Tab wieder in den Vordergrund kommt. So findet der Refresh fast immer im Puffer statt.
Wie der Refresh abläuft
-
1Browser→BFFfragt
/api/auth/sessionab (jede Minute und beim Fokus) -
2BFFLäuft das Access-Token in weniger als 90 Sekunden ab?nein: Sitzung unverändert zurück
-
3BFF→Keycloak
POST /tokenmitgrant_type=refresh_token, Client-ID und Client-Geheimnis -
4Keycloak→BFFneues Access-Token, meist auch ein neues Refresh-Token und ID-Token
-
5BFFschreibt die neuen Tokens ins Sitzungs-CookieErgebnis: Sitzung läuft weiter, niemand merkt etwas
Keycloak gibt bei jedem Refresh ein neues Refresh-Token aus. Ist der Realm so eingestellt, dass ein Refresh-Token nur einmal gilt, wird das alte damit ungültig. Das heißt Rotation.
Die Ausgänge
Wann: Keycloak antwortet mit neuen Tokens.
Der BFF übernimmt Access-, Refresh- und ID-Token und löscht ein eventuelles Fehlerfeld in der Sitzung. Kommt kein neues Refresh-Token mit, behält er das alte.
Ergebnis: Sitzung läuft weiter.
Wann: Keycloak lehnt ab, meist mit invalid_grant: Das Refresh-Token ist abgelaufen, die Keycloak-Sitzung wurde beendet oder das Konto gesperrt.
-
1BFFsetzt in der Sitzung den Fehler
RefreshAccessTokenError -
2BFF→BrowserAPI-Aufrufe des BFF antworten jetzt mit 401
-
3Frontendsieht den Fehler und leitet auf
/login -
4Browser→Keycloakneuer Login. Besteht bei Keycloak keine Sitzung mehr, fragt Keycloak nach dem Passwort
Ergebnis: Die alte Sitzung ist zu Ende. Der neue Login überschreibt das Cookie.
Wann: Keycloak antwortet mit 5xx oder gar nicht.
Der BFF behält das bisherige Token und setzt keinen Fehler. Die nächste Abfrage der Sitzung versucht es erneut. Der Puffer von 90 Sekunden lässt dafür Zeit, bevor das Token wirklich abläuft.
Ergebnis: Kurze Ausfälle von Keycloak bleiben unbemerkt. Dauert der Ausfall länger als das Token, antworten die APIs mit 401.
Wann: Keycloak antwortet mit 5xx oder gar nicht.
Der Hub behandelt jeden gescheiterten Refresh wie eine Ablehnung: Er entfernt das Access-Token und setzt RefreshAccessTokenError.
Ergebnis: Die Oberfläche startet einen neuen Login. Solange Keycloak nicht erreichbar ist, gelingt der nicht.
Besonderheiten im Hub
Der Hub erneuert zusätzlich vor jedem API-Aufruf: Ist das Access-Token (mit 30 Sekunden Sicherheitsabstand) schon abgelaufen, holt der BFF erst ein neues. Das neue Token gilt nur für diesen Aufruf, ins Cookie kommt es bei der nächsten Sitzungsabfrage.
Rotiert Keycloak das Refresh-Token, dürfen zwei gleichzeitige Aufrufe nicht zweimal mit demselben Refresh-Token erneuern: Der zweite bekäme invalid_grant. Der Hub merkt sich deshalb für 60 Sekunden, welche Erneuerungen gerade laufen oder gerade gelaufen sind, und lässt parallele Aufrufe auf dasselbe Ergebnis warten.
Und API-Clients ohne Oberfläche?
Ein eigener Client, der CDMS direkt aufruft, macht es genauso: vor Ablauf mit dem Refresh-Token erneuern. Bekommt er von der API 401 mit invalid_token, ist das Token abgelaufen: erneuern und die Anfrage wiederholen. Siehe Zugriff ohne Token.