CodamAIDocs
Themafertig

Der Weg des Tokens

Wo das Token entsteht, wo es liegt, wer es tauscht und wer es liest, bis es als RequestContext bei CDMS ankommt.

Ausprägungen
Benutzer über ein PortalDownload mit Token in der AdresseDienst-Token für die LookupsLeser-Token für die Deklaration

Worum es geht

Ein Token ist ein kleines, signiertes JSON-Dokument. Es sagt, wer jemand ist und was für ihn gilt. Auf dem Weg einer Anfrage wechselt es mehrfach den Besitzer, wird einmal getauscht und am Ende gar nicht mehr gebraucht.

Diese Seite verfolgt es von der Anmeldung bis zu der Stelle, an der CDMS Daten liest. Wie derselbe Weg fachlich aussieht, steht unter Von der Anmeldung bis zu den Daten.

Zwei Wörter vorweg:

  • Ein BFF („Backend for Frontend“) ist der kleine Server, der zu einem Portal gehört. Der Browser redet mit ihm, er redet mit der API.
  • Die Filterkette ist Code aus cias-authentication, der vor jedem Endpunkt läuft. Sie steckt in beiden Betriebsarten im CDMS-Prozess, auch wenn CIAS ein eigener Dienst ist.

Die Stationen

Der Weg eines Benutzer-Tokens
  1. Keycloak
    Ausstellen
    Stimmen die Anmeldedaten? Dann gibt es Access-, Refresh- und ID-Token
    ↳ nein kein Token – die Anmeldung scheitert
  2. BFF
    Aufbewahren
    Die drei Tokens wandern in ein verschlüsseltes Sitzungs-Cookie. Der Browser bekommt nur dieses Cookie
  3. Client
    Mitschicken
    Der BFF entschlüsselt das Cookie und hängt das Access-Token als Authorization: Bearer … an den API-Aufruf
    ↳ nein 403 – auf jedem geschützten Pfad ohne Token
  4. Filterkette
    Prüfen
    Signatur gegen einen öffentlichen Schlüssel des Realms, dazu Beginn und Ablauf. Keycloak wird dafür nicht gefragt
    ↳ nein 401 mit WWW-Authenticate: Bearer error="invalid_token"
  5. Filterkette
    Tauschen
    Keycloak tauscht das Token gegen eines für den eigenen Client von CIAS
    ↳ nein die Anfrage läuft ohne Identität weiter, jede Rollenprüfung lehnt danach ab
  6. Filterkette
    Lesen
    Aus dem getauschten Token: Benutzer, Name, Realm-Rollen, Fachrollen, Gruppen, Organisationen, Attribute
  7. CIAS
    Ergänzen
    Mandant auflösen, Mandanten-Tor fragen, Rollen und Attribute für genau diesen Mandanten bilden
    ↳ nein 403 mit einem Schlüssel cias.authentication.…
  8. Filterkette
    Ablegen
    Alles zusammen kommt in den RequestContext dieser einen Anfrage
  9. CDMS arbeitet – und liest nur noch den RequestContext

Jede einzelne Station hat eine eigene Seite. Diese hier zeigt nur, dass es eine Kette ist: Token prüfen, Token tauschen, Claims lesen, Mandant auflösen, Mandant zulassen, Effektive Rollen bilden.

Wo welches Token liegt

Auf einem Anfrageweg sind mehrere Tokens unterwegs, und sie gehören verschiedenen Beteiligten.

TokenWer stellt es ausWo liegt esWer benutzt es
Access-Token des BenutzersKeycloakim Sitzungs-Cookie des BFFder BFF, bei jedem API-Aufruf
Refresh-TokenKeycloaknur im Sitzungs-Cookieder BFF, um ein neues Access-Token zu holen
ID-TokenKeycloaknur im Sitzungs-Cookieder BFF beim Abmelden
getauschtes TokenKeycloak, auf Bitte von CIASim Speicher des CDMS-Prozesses, höchstens 5 Minutendie Filterkette, um Rollen und Attribute zu lesen
Dienst-Token für die LookupsKeycloak, für den eigenen Client des CDMS-Dienstes (Client Credentials)im Speicher des CDMS-Dienstes, erneuert nach drei Vierteln der Laufzeitcias-tenancy-client, um CIAS über HTTP zu fragen
Leser-Token für die DeklarationKeycloak, für den Leser-Client von CIAS (Client Credentials)im Speicher des CIAS-Dienstes, erneuert nach drei Vierteln der LaufzeitCIAS, um GET /cias/fetch bei CDMS zu lesen

Der Browser hält kein Token, sondern nur das verschlüsselte Cookie. Warum das so ist, steht unter Sitzung im BFF und Cookies.

Die vier Wege im Einzelnen

Wer wem wann ein Token schickt

Wann: Der Normalfall – jemand klickt in Hub, CDMS-Portal oder CIAS-Portal.

  1. 1
    Browser→BFF
    Klick, das Sitzungs-Cookie geht automatisch mit
  2. 2
    BFF
    entschlüsselt das Cookie und nimmt das Access-Token heraus
    Fehlt es oder steht ein Fehler in der Sitzung, antwortet der BFF selbst mit 401 und das Portal startet einen neuen Login
  3. 3
    BFF→CDMS
    POST /api/rest/crm/customer/query mit Authorization: Bearer …
  4. 4
    CDMS→BFF
    Antwort
    Ergebnis: Der BFF reicht die Daten an den Browser weiter

Wann: Ein Browser folgt einem Link, ein <img src> lädt ein Bild, ein PDF-Betrachter holt eine Datei.

Keiner dieser Fälle kann einen eigenen Header setzen. Deshalb nehmen die Download-Endpunkte das Token als ?access_token= in der Adresse. Geprüft wird es genauso: Signatur und Ablauf. Die Identität liest aber nicht die Filterkette, sondern der Endpunkt selbst – mit denselben Schritten ab „Tauschen“.

Ergebnis: Lehnt CIAS dabei ab, endet der Download mit derselben Ablehnung wie jede andere Anfrage. Siehe Zugriff ohne Token.

Wann: CIAS läuft als eigener Dienst, und der CDMS-Dienst muss etwas wissen.

  1. 1
    CDMS
    nimmt sein Dienst-Token – geholt bei Keycloak mit Client-ID und Secret des Dienstes (Client Credentials), rechtzeitig vor dem Ablauf erneuert
  2. 2
    CDMS→CIAS
    GET /cias/lookup/tenants/{key} und GET /cias/lookup/users/{id}/attributes?tenantKey=…
  3. 3
    CIAS
    prüft die Rolle des Aufrufers – je Endpunkt eine eigene, ohne Standardwert
  4. 4
    CIAS→CDMS
    Antwort
    Ergebnis: Der CDMS-Dienst merkt sie sich für die eingestellte Zeit

Wann: CIAS holt sich die Liste der Rollen und Attribute eines Moduls.

Die Richtung ist umgekehrt: CIAS ruft CDMS auf, GET /cias/fetch, mit einem eigenen Leser-Token, das CIAS genauso bei Keycloak holt. Die Antwort ist die komplette Rechtekarte der Anwendung, also nichts, was öffentlich sein dürfte. CDMS prüft dafür eine eigene Realm-Rolle.

Ergebnis: Dieser Aufruf liegt nicht auf dem Anfrageweg. Er läuft beim Start und wenn jemand den Abgleich anstößt. Siehe Module melden ihre Rollen an.

Was am Ende im RequestContext steht

Der RequestContext ist der einzige Ort, an dem CDMS nachliest. Er enthält unter anderem:

FeldWoherWofür
userIdsub aus dem getauschten TokenEigentümer neuer Objekte, Historie, Owner-Filter
userNamename, sonst preferred_usernameAnzeige und Protokoll
userTenantaufgelöster und zugelassener MandantWelche Datenbank, welche Zeilen
allowedTenantseigener Mandant, Organisationen, AttributWas ein Mandantenwechsel erreichen darf
effectiveUserRealmRolesrealm_access.rolesPlattformrollen, Wechselrechte
effectiveUserRolesFachrollen für den aktiven MandantenModell- und Feldrollen in CDMS
effectiveUserGroupsgroupszur Information
effectiveUserAttributesToken plus Werte pro MandantAttributfilter auf Zeilen

Welcher Claim genau wohin geht, steht unter Was aus dem Token gelesen wird.

Wer den RequestContext liest

Die Leser, in der Reihenfolge der Anfrage
  1. 1
    CDMS
    Die Rechteprüfung vergleicht die Fachrollen mit den Rollen, die das Modell verlangt
  2. 2
    CDMS
    Der Attributfilter nimmt einen Attributwert der Person und schränkt damit die Zeilen ein
  3. 3
    CDMS
    Der Owner-Filter vergleicht _userId der Zeile mit der userId der Anfrage
  4. 4
    CDMS
    Beim Schreiben trägt der System-Layer die userId als Eigentümer ein, die Historie schreibt sie mit
  5. 5
    CDMS
    Die Dateiablage legt Dateien unter dem Mandanten der Anfrage ab
  6. 6
    CIAS
    Die eigenen Endpunkte von CIAS lesen denselben Kontext als Aufrufer: authentifiziert, Mandant, Rollen, Person
    Ergebnis: Ein Mandantenadministrator verwaltet damit immer seinen eigenen Mandanten, nie einen aus dem Anfragekörper

Nach der Antwort ist alles weg

Die Filterkette räumt den RequestContext am Ende jeder Anfrage wieder ab – auch dann, wenn die Anfrage abgelehnt wurde. Das ist nötig, weil der Kontext am Thread hängt und Threads wiederverwendet werden. Bliebe er stehen, könnte die nächste Arbeit auf demselben Thread Identität, Mandant und Rollen der vorigen Anfrage lesen.

Fallen

Weiter

Quellen im Code und in der Wissensdatenbank
  • CIAS/cias-authentication – SessionConfig (offene Pfade, Http403ForbiddenEntryPoint, DefaultBearerTokenResolver mit allowUriQueryParameter), JwtSessionFilter (RequestContext anlegen, Wechsel-Header, refuse, finally), TokenParser (tokenParser, admit, extractIdentity, PROTOCOL_CLAIMS), TokenExchangeService, TokenExchangeProperties, JwtDecoderUtil, EffectiveRoles, EffectiveAttributes, AttributeLookup, TenantGate, ContextSwitch, CurrentTenantProviderImpl, ResolvedTenantHolder
  • CIAS/cias-kernel – AuthenticatedIdentity, CallerContext, CallerContextProvider, TenantContext
  • commons – RequestContext, RequestContextHolder
  • CDMS/cdms-rest-api – QueryTokenAuthentication, AbstractRestApi, AbstractRestSingletonApi
  • CDMS/cdms-authorization – AbstractAuthorizationLayer, AbstractAttributeFilter, CiasApi, CiasReaderRoles
  • CDMS/cdms-system-layer – AbstractLayer (_userId), AbstractSystemLayer
  • CDMS/cdms-localfs-storage – LocalFSFileController
  • CIAS/cias-tenancy-client – ClientCredentialsTenantLookupCredentials, CiasTenancyClientCredentialsProperties, StaticTenantLookupCredentials, CiasTenancyClientProperties, RemoteTenantLookupAdapter, RemoteTenantBoundAttributeAdapter
  • CIAS/cias-spring-boot-starter – RequestContextCallerContextProvider
  • hub-frontend – server/utils/backendFetch.ts, sessionToken.ts, ciasFetch.ts
Suchen