CodamAIDocs
Topicdone

The path of the token

Where the token is created, where it is stored, who exchanges it and who reads it, until it arrives at CDMS as a RequestContext.

Variants
user through a portaldownload with the token in the URLservice token for the lookupsreader token for the declaration

What this is about

A token is a small, signed JSON document. It says who somebody is and what applies to them. On the path of a request it changes hands several times, gets exchanged once, and in the end is no longer needed at all.

This page follows it from the login to the point where CDMS reads data. The same path told in business terms is under From login to the data.

Two words up front:

  • A BFF (“backend for frontend”) is the small server that belongs to a portal. The browser talks to it, and it talks to the API.
  • The filter chain is code from cias-authentication that runs before every endpoint. It sits in the CDMS process in both operating modes, even when CIAS is a separate service.

The stations

The path of a user token
  1. Keycloak
    Issue
    Are the credentials correct? Then Keycloak issues an access, a refresh and an ID token
    ↳ no no token – the login fails
  2. BFF
    Store
    The three tokens go into an encrypted session cookie. The browser only gets that cookie
  3. Client
    Send
    The BFF decrypts the cookie and attaches the access token as Authorization: Bearer … to the API call
    ↳ no 403 – on every protected path without a token
  4. Filter chain
    Verify
    The signature against a public key of the realm, plus start and expiry. Keycloak is not asked for this
    ↳ no 401 with WWW-Authenticate: Bearer error="invalid_token"
  5. Filter chain
    Exchange
    Keycloak exchanges the token for one for CIAS's own client
    ↳ no the request continues without an identity, and every role check refuses afterwards
  6. Filter chain
    Read
    From the exchanged token: user, name, realm roles, business roles, groups, organizations, attributes
  7. CIAS
    Complete
    Resolve the tenant, ask the tenant gate, build roles and attributes for exactly this tenant
    ↳ no 403 with a key cias.authentication.…
  8. Filter chain
    Store in context
    All of it goes into the RequestContext of this one request
  9. CDMS works – and only reads the RequestContext

Every single station has a page of its own. This one only shows that it is one chain: verify the token, exchange the token, read the claims, resolve the tenant, admit the tenant, build the effective roles.

Where each token is stored

Several tokens travel along one request path, and they belong to different parties.

TokenWho issues itWhere it is storedWho uses it
the user’s access tokenKeycloakin the BFF’s session cookiethe BFF, on every API call
refresh tokenKeycloakonly in the session cookiethe BFF, to get a new access token
ID tokenKeycloakonly in the session cookiethe BFF when logging out
exchanged tokenKeycloak, on CIAS’s requestin the memory of the CDMS process, at most 5 minutesthe filter chain, to read roles and attributes
service token for the lookupsKeycloak, for the CDMS service’s own client (client credentials)in the memory of the CDMS service, renewed after three quarters of its lifetimecias-tenancy-client, to ask CIAS over HTTP
reader token for the declarationKeycloak, for CIAS’s reader client (client credentials)in the memory of the CIAS service, renewed after three quarters of its lifetimeCIAS, to read GET /cias/fetch from CDMS

The browser holds no token, only the encrypted cookie. Why that is so is under Session in the BFF and cookies.

The four paths in detail

Who sends whom a token, and when

When: The normal case – somebody clicks in the hub, the CDMS portal or the CIAS portal.

  1. 1
    Browser→BFF
    a click, the session cookie goes along automatically
  2. 2
    BFF
    decrypts the cookie and takes the access token out of it
    If it is missing, or the session carries an error, the BFF answers 401 itself and the portal starts a new login
  3. 3
    BFF→CDMS
    POST /api/rest/crm/customer/query with Authorization: Bearer …
  4. 4
    CDMS→BFF
    response
    Result: The BFF passes the data on to the browser

When: A browser follows a link, an <img src> loads a picture, a PDF viewer fetches a file.

None of these can set a header of their own. That is why the download endpoints take the token as ?access_token= in the URL. It is verified just the same: signature and expiry. The identity, however, is not read by the filter chain but by the endpoint itself – with the same steps from "exchange" onwards.

Result: If CIAS refuses along the way, the download ends with the same refusal as any other request. See Access without a token.

When: CIAS runs as a separate service and the CDMS service needs to know something.

  1. 1
    CDMS
    takes its service token – fetched from Keycloak with the service's client ID and secret (client credentials), renewed in good time before it expires
  2. 2
    CDMS→CIAS
    GET /cias/lookup/tenants/{key} and GET /cias/lookup/users/{id}/attributes?tenantKey=…
  3. 3
    CIAS
    checks the caller's role – one of its own per endpoint, with no default
  4. 4
    CIAS→CDMS
    the answer
    Result: The CDMS service remembers it for the configured time

When: CIAS fetches the list of roles and attributes a module defines.

The direction is reversed: CIAS calls CDMS, GET /cias/fetch, with a reader token of its own, which CIAS fetches from Keycloak the same way. The answer is the complete permission map of the application, so it is nothing that should be public. CDMS checks a realm role of its own for it.

Result: This call is not on the request path. It runs at startup and when somebody triggers the reconciliation. See Modules register their roles.

What ends up in the RequestContext

The RequestContext is the only place CDMS reads from. Among other things it holds:

FieldFromUsed for
userIdsub of the exchanged tokenowner of new objects, history, owner filter
userNamename, else preferred_usernamedisplay and logging
userTenantthe resolved and admitted tenantwhich database, which rows
allowedTenantsown tenant, organizations, attributewhat a tenant switch may reach
effectiveUserRealmRolesrealm_access.rolesplatform roles, switch permissions
effectiveUserRolesbusiness roles for the active tenantmodel and field roles in CDMS
effectiveUserGroupsgroupsfor information
effectiveUserAttributesthe token plus the values per tenantattribute filters on rows

Which claim goes exactly where is under What is read from the token.

Who reads the RequestContext

The readers, in the order of the request
  1. 1
    CDMS
    The role check compares the business roles with the roles the model requires
  2. 2
    CDMS
    The attribute filter takes an attribute value of the person and restricts the rows with it
  3. 3
    CDMS
    The owner filter compares the row's _userId with the userId of the request
  4. 4
    CDMS
    On a write, the system layer records the userId as the owner, and the history records it too
  5. 5
    CDMS
    The file storage stores files under the tenant of the request
  6. 6
    CIAS
    CIAS's own endpoints read the same context as the caller: authenticated, tenant, roles, person
    Result: A tenant administrator therefore always administers their own tenant, never one taken from the request body

After the response, everything is gone

The filter chain clears the RequestContext at the end of every request — including a request that was refused. That is necessary because the context is attached to the thread, and threads are reused. If it stayed, the next piece of work on that thread could read the identity, tenant and roles of the previous request.

Watch out

Next

Sources in the code and the knowledge base
  • CIAS/cias-authentication – SessionConfig (public paths, Http403ForbiddenEntryPoint, DefaultBearerTokenResolver with allowUriQueryParameter), JwtSessionFilter (creating the RequestContext, switch headers, 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
Search