CodamAIDocs
Themafertig

Sitzung im BFF und Cookies

Warum das Token im Server des Frontends liegt und nicht im Browser, wie das Sitzungs-Cookie aussieht und warum jedes Portal ein eigenes Cookie-Präfix hat.

Ausprägungen
Cookie httpOnly, sameSite=laxeigenes Präfix je PortalLaufzeit 1 h

Worum es geht

Nach dem Login hat der BFF drei Tokens von Keycloak. Die Frage ist: Wo werden sie aufbewahrt? Die Antwort bei CodamAI: in einem verschlüsselten Cookie, das nur der BFF öffnen kann. Aufrufe an CDMS und CIAS macht der BFF, nicht der Browser.

Wo welches Token liegt

flowchart LR
    B["Browser<br/>Sitzungs-Cookie (verschlüsselt)"] -- "Cookie bei jeder Anfrage" --> F["BFF<br/>entschlüsselt:<br/>Access-, Refresh-, ID-Token"]
    F -- "Authorization: Bearer <Access-Token>" --> A["CDMS / CIAS"]
    F -- "Refresh-Token, ID-Token" --> K["Keycloak"]
TokenWoWer benutzt es
Access-Tokenim Sitzungs-Cookie. Die Seite kann es über /api/auth/session abfragender BFF bei jedem API-Aufruf
Refresh-Tokennur im Sitzungs-Cookieder BFF, um ein neues Access-Token zu holen
ID-Tokennur im Sitzungs-Cookieder BFF beim Abmelden

Warum nicht einfach im Browser speichern, etwa im localStorage? Weil jedes Skript auf der Seite dort lesen kann. Ein einziges eingeschleustes Skript könnte dann das Refresh-Token stehlen und sich damit stundenlang neue Tokens holen. Ein httpOnly-Cookie ist für Skripte unsichtbar.

EigenschaftWertBedeutung
httpOnlyjakein JavaScript kann das Cookie lesen
sameSitelaxder Browser schickt es nicht bei Formularen oder Skript-Anfragen von fremden Seiten mit
secureja unter httpsnur über verschlüsselte Verbindungen. Der Name bekommt dann das Präfix __Secure-
path/gilt für die ganze Anwendung
Inhaltverschlüsselt (JWE)Tokens, Ablaufzeit, ein Fehlerfeld. Schlüssel ist das Geheimnis des Portals (NUXT_AUTH_SECRET)
Größewird bei mehr als etwa 4 KB aufgeteiltTeile heißen …session-token.0, .1 usw.

Daneben setzt der BFF während der Anmeldung kurzlebige Cookies für state, PKCE und das Rücksprungziel. Sie gelten höchstens 15 Minuten.

JWE steht für JSON Web Encryption: Der Inhalt ist nicht nur signiert, sondern verschlüsselt.

Laufzeit: eine Stunde, gleitend

Die Sitzung gilt eine Stunde. Die Stunde wird verlängert, solange die Seite offen ist: Die Oberfläche fragt jede Minute und beim Zurückkehren in den Tab /api/auth/session ab, und jede Abfrage schiebt das Ende nach hinten. Dabei erneuert der BFF auch das Access-Token, wenn es bald abläuft, siehe Token erneuern.

Ist die Sitzung noch gültig?
Tab offen, Seite fragt regelmäßigletzte Abfrage älter als 1 hRefresh bei Keycloak möglichWas passiert
janeinjaSitzung läuft weiter, Tokens werden erneuert
–ja–Cookie abgelaufen, beim nächsten Seitenaufruf neuer Login
janeinneinSitzung bekommt einen Fehler, die Oberfläche startet einen neuen Login

Eigenes Präfix je Portal

Cookies gehören zu einem Rechnernamen, nicht zu einem Port. Laufen mehrere Portale auf demselben Rechner, etwa lokal auf localhost:3000 und localhost:3001, sehen sie gegenseitig ihre Cookies. Hätten alle denselben Cookie-Namen, würde jedes Portal das Cookie des anderen überschreiben, und jedes hat einen anderen Schlüssel:

Was bei gleichem Cookie-Namen passiert
  1. 1
    Browser→Frontend
    Login im Hub setzt next-auth.session-token, verschlüsselt mit dem Schlüssel des Hubs
  2. 2
    Browser→Frontend
    Login im CDMS-Portal überschreibt dasselbe Cookie mit dem eigenen Schlüssel
  3. 3
    Frontend
    Der Hub kann das Cookie nicht mehr entschlüsseln
    Sitzungsfehler, neuer Login, der wiederum das andere Portal abmeldet

Deshalb verwendet das CIAS-Portal das eigene Präfix cias-auth: Seine Cookies heißen cias-auth.session-token, cias-auth.csrf-token usw. Der Hub und das CDMS-Portal verwenden die Standardnamen next-auth.*.

Wie der BFF die API aufruft

Ein Klick in der Oberfläche
  1. 1
    Browser→BFF
    GET /api/kunden, das Sitzungs-Cookie geht automatisch mit
  2. 2
    BFF
    entschlüsselt das Cookie. Fehlt das Access-Token oder steht ein Fehler in der Sitzung?
    dann 401 an den Browser, die Oberfläche startet einen neuen Login
  3. 3
    BFF→CDMS
    POST /api/rest/crm/customer/query mit Authorization: Bearer <Access-Token>
  4. 4
    CDMS→BFF
    Antwort
  5. 5
    BFF→Browser
    gibt die Daten weiter

Die Header tenant und user für einen Mandanten- oder Benutzerwechsel schicken die Portale nicht. Siehe Mandantenwechsel per Header.

Weiter

Quellen im Code und in der Wissensdatenbank
  • hub-frontend, CIAS/cias-frontend, CDMS/frontend – server/api/auth/[...].ts (session strategy jwt, maxAge, updateAge, Callbacks), nuxt.config.ts (sessionRefresh)
  • CIAS/cias-frontend – server/utils/authCookies.ts, server/middleware/dropForeignAuthCookies.ts
  • hub-frontend – server/utils/backendFetch.ts, ciasFetch.ts, useCmsApi.ts
  • next-auth 4 – jwt/index.js (JWE dir/A256GCM), core/lib/cookie.js (Namen, Flags, Aufteilung)
Suchen