Token Exchange Grant
Der OAuth 2.0 Token Exchange (RFC 8693) ist ein offen spezifizierter Flow, mit dem ein Client ein bestehendes Token (das subject_token) gegen ein neues Token mit anderem Issuer, anderer Audience oder anderem Scope eintauschen lässt. Optional kann ein zweites Token (das actor_token) mitgeliefert werden, um eine Delegierungskette mit kryptographisch nachgewiesenem Akteur zu belegen.
Im CMI STS deckt der Token-Exchange-Grant Anwendungsfälle ab, die mit dem On-Behalf-Of-Grant nicht oder nur eingeschränkt abbildbar sind:
- Cross-Tenant: Ein Subject-Token, das ein anderer CMI-STS-Mandant ausgestellt hat, wird im Ziel-Mandanten gegen ein dort gültiges Access-Token getauscht. Die externe Identität (
external_idpundexternal_sub) wird im Ziel-Mandanten gegen die dortige CMI-Server-Konfiguration aufgelöst. - Partner-STS: Ein Subject-Token, das ein föderierter Partner-STS (kein Identity Provider, sondern ein vorgelagerter Security Token Service) ausgestellt hat, wird gegen ein Access-Token für den CMI Server getauscht.
- Delegation mit Akteur-Nachweis: Eine Web-API ruft den CMI Server stellvertretend für den Benutzer auf und weist sich gleichzeitig per
actor_tokenselbst aus. Das ausgestellte Token erhält einenact-Claim gemäss RFC 8693 §4.1; Mehrhop-Delegierung bleibt strukturell nachvollziehbar (act.act-Verschachtelung).
Hinweis: Der OBO-Grant (
urn:ietf:params:oauth:grant-type:jwt-bearer) bleibt für reine OIDC-IDP-Tausch-Fälle (z. B. Azure AD App-Registrierung → CMI-Access-Token) bestehen und wird durch den Token-Exchange-Grant nicht ersetzt. Wer einen Akteur belegen, einen Partner-STS einbinden oder Cross-Tenant arbeiten muss, verwendet den Token-Exchange-Grant.
Ein vollständiges End-to-End-Beispiel mit zwei STS-Installationen und drei Mandanten ist im Cross-Domain-Token-Chaining-Walkthrough dokumentiert.
Anforderungen
Damit der CMI STS einen Token-Exchange-Request akzeptiert, müssen folgende Bedingungen erfüllt sein:
- Es muss eine Trust-Quelle für das subject_token konfiguriert sein:
- OIDC-IDP (
OpenIdConnectIdPs) — gleiche Konfiguration wie für den OBO-Grant, siehe Externe Identity Provider (IDP). - Partner-STS (
TrustedPartnerStsIssuers) — siehe Kapitel Konfiguration: Partner-STS. - Eigener CMI STS (Cross-Tenant) — der Quell-Mandant muss im Ziel-Mandanten unter
TrustedSourceTenantseingetragen sein, siehe Kapitel Konfiguration: Cross-Tenant. - Es werden ausschliesslich JWT-formatierte Subject- und Actor-Tokens unterstützt:
urn:ietf:params:oauth:token-type:jwtundurn:ietf:params:oauth:token-type:access_token. SAML-Assertions und opake Tokens werden abgelehnt. - Der Parameter
resourcewird nicht unterstützt; das Ziel des Tokens muss zwingend überaudiencebenannt werden. - Der ausgestellte Token-Typ ist immer
urn:ietf:params:oauth:token-type:access_token(Bearer). ID-Tokens, Refresh-Tokens und SAML-Assertions werden nicht ausgestellt. - Subject- und Actor-Tokens sind auf 16 KB begrenzt; grössere Tokens werden abgelehnt, bevor die Signatur geprüft wird.
Wichtig: Der CMI STS validiert Subject- und Actor-Token gegen die konfigurierte Trust-Quelle. Pflicht-Prüfungen sind Signatur,
iss,sub(Tokens ohne nicht-leerensub-Claim werden abgelehnt),expundiat. Für Subject-/Actor-Token gilt kein maximaler Lebensdauer-Cap und kein Vergangenheitsfenster (es sind reguläre Access-Tokens, z. B. mit 60 Minuten Laufzeit):expbegrenzt die Gültigkeit, einiatin der Zukunft (jenseits der Uhrendrift) wird abgelehnt, und das ausgestellte Token überlebt die Quell-Tokens ohnehin nie (siehe unten). Deraud-Claim wird nur geprüft, wenn die Trust-Quelle eine Audience vorgibt: bei Partner-STS immer (TrustedPartnerStsIssuers.Audience), bei OIDC-IDP- und Cross-Tenant-Quellen greifen stattdessenAllowedSubjectAudiencesbzw.AllowedSourceTenants. Es erfolgt keine Online-Introspection beim ausstellenden System.
Konfiguration: CMI STS
Ein regulärer Duende-Client wird angelegt; siehe auch Clients. Die folgende Konfiguration dient als Referenzkonfiguration. Alle Schlüssel unter TokenExchange sind CMI-spezifische Erweiterungen.
{
// ...
"tenants": {
"mandant": {
"Clients": [
{
"ClientId": "<CLIENT_ID>",
"AllowedGrantTypes": ["urn:ietf:params:oauth:grant-type:token-exchange"],
"AllowedScopes": ["metatool"],
"ClientSecrets": [{ "value": "..." }],
"TokenExchange": {
// Erlaubte Ziel-Audiences des Requests:
"AllowedAudiences": ["https://cmi-server.example.com"],
// Eine oder mehrere Subject-Token-Quellen freischalten:
"AllowedSourceIssuers": ["azuread-tenant1", "https://login.microsoftonline.com/<TENANT_ID>/v2.0"],
"AllowedSourceTenants": ["mandant-partner"],
// Bei OIDC-IDP-Quellen erforderlich: erlaubte aud-Werte des Subject-Tokens:
"AllowedSubjectAudiences": ["api://cmi-metatool"],
// Delegation (actor_token) — standardmässig deaktiviert:
"AllowDelegation": true,
"AllowedActorIssuers": ["azuread-tenant1"],
"AllowedActorAudiences": ["api://cmi-metatool"],
"ValidationClockSkewSeconds": 60
}
}
]
}
}
}
ClientId(erforderlich): Eine beliebige Client ID.AllowedGrantTypes(erforderlich): Der Grant Typeurn:ietf:params:oauth:grant-type:token-exchangeaktiviert den Token-Exchange-Grant.AllowedScopes(erforderlich): Scopes, die im ausgestellten Access-Token enthalten sein dürfen. Der CMI Server erwartet den Scopemetatool.ClientSecrets(erforderlich): Ein oder mehrere Client Secrets als SHA-512-Hash, siehe Clients.TokenExchange(erforderlich): CMI-spezifische Optionen des Token-Exchange-Grants. Alle Allow-Listen sind JSON-String-Arrays. Leere oder fehlende Listen bedeuten Deny: Ohne explizite Einträge wird keine Quelle, keine Audience und kein Akteur akzeptiert. Wildcards werden nicht unterstützt.AllowedAudiences(erforderlich): Erlaubte Werte für den Request-Parameteraudience. Alle angefragten Audiences müssen in der Liste enthalten sein (Schutz gegen Audience-Smuggling).AllowedSourceIssuers(bedingt erforderlich): Erlaubte Subject-Token-Aussteller, geprüft gegen den internen Schlüssel (ausOpenIdConnectIdPsoderTrustedPartnerStsIssuers) oder den Roh-iss-Wert (Discovery-Issuer-URI). Ein Treffer auf einem der beiden genügt.AllowedSourceTenants(bedingt erforderlich): Erlaubte fremde CMI-STS-Mandanten (Cross-Tenant) als Quelle des Subject-Tokens.AllowedSubjectAudiences(erforderlich bei OIDC-IDP-Quellen): Erlaubteaud-Werte des Subject-Tokens, wenn dessen Aussteller ein OIDC-IDP ist. Ein OIDC-Issuer stellt Tokens für viele Anwendungen aus; ohne diese Audience-Bindung könnte ein Token, das der IDP für eine fremde Anwendung ausgestellt hat, eingetauscht werden (Confused-Deputy). Leer ⇒ kein OIDC-Subject-Token wird akzeptiert. Trägt das Token einaud-Array, genügt ein Treffer. Nicht zu verwechseln mitAllowedAudiences(Ziel-Audience des Requests). Bei Partner-STS-Quellen wird die Audience am Issuer-Eintrag (Audience) gepinnt, bei Cross-Tenant überAllowedSourceTenants— dort ist diese Liste wirkungslos.AllowDelegation(optional, Standardwert:false): Aktiviert die Annahme einesactor_token. Ohne diese Freischaltung wird ein mitgesendetesactor_tokenmitunauthorized_clientabgelehnt — noch bevor es kryptographisch geprüft wird. ErstAllowDelegation=trueund mindestens ein Eintrag inAllowedActorIssuersschalten Delegation frei.AllowedActorIssuers(erforderlich bei Delegation): Erlaubte Aussteller desactor_token(Issuer-Key oder Roh-iss-URI). Leere Liste ⇒ strikter Deny — Delegation kann nicht versehentlich nur durch Setzen vonAllowDelegationaktiviert werden. Jedersubeines erlaubten Actor-Issuers wird akzeptiert; ein bestimmter Akteur kann zusätzlich über denmay_act-Claim im Subject-Token gepinnt werden (siehe Beispiel mit Actor-Token).AllowedActorAudiences(erforderlich bei OIDC-IDP-Actor-Quellen): Erlaubteaud-Werte des Actor-Tokens, wenn dessen Aussteller ein OIDC-IDP ist. Actor-Pendant zuAllowedSubjectAudiences. Leer ⇒ kein OIDC-Actor-Token wird akzeptiert. Bei Partner-STS- oder Cross-Tenant-Actor-Quellen wirkungslos.ValidationClockSkewSeconds(optional, Standardwert:60): Akzeptierte Uhrendrift in Sekunden für dieexp/nbf/iat-Validierung der Subject- und Actor-Tokens. Der Wert ist ein Operator-Entscheid und wird nach oben nicht begrenzt; negative Werte werden als0behandelt.
Wichtig: Pro Subject-Token-Quelle muss mindestens eine der beiden Allow-Listen (
AllowedSourceIssuers,AllowedSourceTenants) gefüllt sein. Ohne Eintrag wird der Tausch unabhängig vom Token-Inhalt verweigert.Hinweis: Scopes werden nicht separat am
TokenExchange-Block konfiguriert. Ausgestellt wird die Schnittmenge aus angefragten Scopes,AllowedScopesdes Clients und den Scopes des Subject-Tokens; eine leere Schnittmenge führt zur Ablehnung.
Konfiguration: Partner-STS
Ein Partner-STS (z. B. ein Token-Service eines Drittsystems) wird pro Mandant unter TrustedPartnerStsIssuers eingetragen. Pro Eintrag werden Authority, erwartete Audience und optional Pflicht-Claims hinterlegt.
{
"tenants": {
"mandant": {
"TrustedPartnerStsIssuers": {
"partner-sts-1": {
"Authority": "https://partner-sts.example.com",
"Audience": "https://mandant.cmi.example.com",
"RequiredClaimRequirements": {
"ver": "1.0",
"auth_method": "mfa"
}
}
}
}
}
}
Authority(erforderlich): URL des Partner-STS. Wird verwendet, um das OpenID-Discovery-Dokument (JWKS-Endpoint,iss-Wert) zu laden. JWKS wird automatisch aktualisiert; bei Ausfällen greift ein Last-Known-Good-Fallback.Audience(erforderlich): Erwarteteraud-Claim der Tokens des Partner-STS. Tokens mit abweichender Audience werden abgelehnt.RequiredClaimRequirements(optional): Pflicht-Claims, die im Subject-/Actor-Token vorhanden sein und exakt mit dem angegebenen Wert übereinstimmen müssen.
Der Schlüssel der Map (im Beispiel partner-sts-1) ist der Issuer-Key, der in TokenExchange.AllowedSourceIssuers und TokenExchange.AllowedActorIssuers verwendet wird.
Konfiguration: Cross-Tenant
Soll ein anderer CMI-STS-Mandant als Quelle akzeptiert werden, muss der Ziel-Mandant den Quell-Mandanten unter TrustedSourceTenants deklarieren. Pro Quelle wird ein Mapping der externen IDP-Schlüssel hinterlegt, falls Quell- und Ziel-Mandant unterschiedliche IDP-Schlüssel für denselben föderierten IDP verwenden.
{
"tenants": {
"mandant-ziel": {
"TrustedSourceTenants": {
"mandant-quelle": {
"ProviderKeyMapping": {
"azuread-source": "azuread-target"
}
}
},
"OpenIdConnectIdPs": {
"azuread-target": { /* ... übliche OIDC-IDP-Konfiguration ... */ }
},
"Clients": [
{
"ClientId": "cross-tenant-bridge",
"AllowedGrantTypes": ["urn:ietf:params:oauth:grant-type:token-exchange"],
"AllowedScopes": ["metatool"],
"ClientSecrets": [{ "value": "..." }],
"TokenExchange": {
"AllowedAudiences": ["https://cmi-server-ziel.example.com"],
"AllowedSourceTenants": ["mandant-quelle"]
}
}
]
}
}
}
- Das Subject-Token des Quell-Mandanten muss die Pflicht-Claims
external_idp(Provider-Key in der Quell-Mandanten-Konfiguration) undexternal_sub(Subject des Benutzers beim föderierten IDP) tragen. ProviderKeyMappingarbeitet als Default-Deny: Jederexternal_idp-Wert, der getauscht werden soll, braucht einen expliziten Eintrag — so wird die Cross-Tenant-Identität nie versehentlich gegen einen unbeabsichtigten lokalen Provider aufgelöst. Verwenden Quell- und Ziel-Mandant denselben Provider-Key-Namensraum, wird der Key als identisches Paar eingetragen (z. B."aad-mandantA": "aad-mandantA").- Zusätzlich muss der Quell-Mandant im Client unter
TokenExchange.AllowedSourceTenantsaufgeführt sein. Ein Mandant, der dort nicht aufgeführt ist, darf den Tausch nicht auslösen — auch dann nicht, wenn er inTrustedSourceTenantsfür einen anderen Client eingetragen wäre.
Der Ablauf eines Cross-Tenant-Tauschs in fünf Schritten:
- Der CMI STS erkennt anhand des
iss-Werts, dass das Subject-Token von einem eigenen Mandanten stammt. - Der Quell-Mandant wird gegen
TokenExchange.AllowedSourceTenantsdes Clients geprüft. external_idpundexternal_subwerden aus dem Subject-Token gelesen.ProviderKeyMappingbildet denexternal_idp-Wert auf den Provider-Key des Ziel-Mandanten ab; der CMI Server des Ziel-Mandanten wird mit diesem Key undexternal_subaufgerufen.- Der CMI Server löst den Benutzer auf. Subject und Claims des ausgestellten Tokens stammen ausschliesslich vom CMI Server des Ziel-Mandanten — Claims aus dem Request werden ignoriert.
Ein vollständiges Cross-Tenant- und Partner-STS-Szenario inklusive Verifikation ist im Cross-Domain-Token-Chaining-Walkthrough beschrieben.
Backend-Aufruf: CMI Server Identity Resolution
Die Identitätsauflösung gegen den CMI Server erfolgt über die private STS-Schnittstelle POST {CmiPrivateUri}api/core/sts/AuthenticateExternal. Der CMI Server liefert Subject und Claims, die unverändert in das ausgestellte Access-Token übernommen werden. Fehler des Backends werden auf Token-Exchange-Fehlercodes gemappt, siehe Fehlercodes.
Grant Request
Der Token-Exchange-Grant wird über den Token-Endpunkt ausgeführt, der im Discovery-Dokument des CMI STS publiziert ist ({tenant id}/identity/.well-known/openid-configuration, grant_types_supported enthält urn:ietf:params:oauth:grant-type:token-exchange).
Der Request muss wie folgt erfolgen:
(Zeilenumbrüche und fehlende URL-Codierung dienen nur der besseren Lesbarkeit)
POST /{tenant id}/identity/connect/token HTTP/1.1
Host: {CMI STS host}
Content-Type: application/x-www-form-urlencoded
Content-Length: ...
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&client_id=<CLIENT_ID>
&client_secret=<CLIENT_SECRET>
&subject_token=<SUBJECT_TOKEN>
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&audience=https://cmi-server.example.com
&scope=metatool
Pflicht-Parameter:
grant_type— festurn:ietf:params:oauth:grant-type:token-exchange.subject_token— das vorhandene Token, das getauscht werden soll. OhneBearer-Preamble übermitteln.subject_token_type—urn:ietf:params:oauth:token-type:jwtoderurn:ietf:params:oauth:token-type:access_token. Andere Werte (z. B. SAML) werden abgelehnt.audience— angefragte Ziel-Audience. Dient der Autorisierung: jeder Wert muss inTokenExchange.AllowedAudiencesenthalten sein, sonst wird der Request abgelehnt (STS930). Mehrfach-Werte werden unterstützt. Der Wert wird nicht in denaud-Claim des ausgestellten Tokens übernommen (siehe Hinweis unter Grant Response).client_idundclient_secret— Client-Authentisierung.
Optionale Parameter:
scope— Space-separierter Scope-Request. Leer ⇒ es werden die im Client erlaubten Scopes ausgegeben, soweit sie auch im Subject-Token enthalten sind.actor_tokenundactor_token_type— Akteur-Nachweis für Delegation, siehe Beispiel mit Actor-Token.requested_token_type— wenn gesetzt, muss der Werturn:ietf:params:oauth:token-type:access_tokensein.
Der Parameter resource wird nicht unterstützt; das Ziel ist immer über audience zu benennen.
Grant Response
Die Antwort entspricht RFC 8693 §2.2. Erfolg ⇒ HTTP 2XX, Fehler ⇒ HTTP 4XX mit error/error_description und CMI-spezifischen error_codes. Alle Token-Exchange-Fehlercodes (Bereich STS92x bis STS951) sind in ErrorCodes.md dokumentiert und werden hier nicht dupliziert.
Erfolgsantwort
{
"access_token": "ey...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "metatool",
"error_codes": ["STS920"],
"trace_id": "0HMV...",
"timestamp": "2026-05-20T08:42:17Z"
}
access_token(erforderlich): Das ausgestellte Bearer-Access-Token.issued_token_type(erforderlich): Der Typ des ausgestellten Tokens, immerurn:ietf:params:oauth:token-type:access_token.token_type(erforderlich): FestBearer.expires_in(optional): Lebensdauer in Sekunden. Berechnet als Minimum über die Restlaufzeit des Subject-Tokens, die Restlaufzeit des Actor-Tokens (falls vorhanden) undInternalTokenLifetimeSeconds(falls gesetzt), mit einer Untergrenze von 60 Sekunden. Das ausgestellte Token kann die Quell-Tokens damit nie überleben. Lässt sich keine Obergrenze ableiten, gilt ein konservativer Fallback von 300 Sekunden.scope(optional): Wird nur ausgegeben, wenn die Scope-Schnittmenge vom Request abweicht (Scope-Downgrade).error_codes(optional): Enthält bei Erfolg den ErfolgscodeSTS920(analogSTS900beim OBO-Grant).trace_id(optional): Trace-ID für die Korrelation mit den STS-Logs.timestamp(optional): UTC-Zeitstempel der Antwort.
Ein Refresh-Token wird nicht ausgestellt: der Scope offline_access wird beim Token-Exchange immer aus der ausgestellten Scope-Menge entfernt, auch wenn Client und Subject-Token ihn autorisieren. Andernfalls würde der Refresh-Pfad den auf die Quell-Token-Restlaufzeit berechneten Lifetime-Cap umgehen.
Hinweis zur Audience: Das ausgestellte Token trägt die statische Audience des CMI STS (
{issuer}/resources), nicht die im Request angefragteaudience.TokenExchange.AllowedAudiencesist ein Autorisierungs-Gate (welche Audiences ein Client anfragen darf), keine kryptographische Bindung des Tokens an ein Ziel. Resource Server validieren das ausgestellte Token daher über den Issuer (iss) und die STS-Audience, nicht über einen zielspezifischenaud-Wert.
Fehlerantwort
{
"error": "invalid_request",
"error_description": "subject_token validation failed",
"error_codes": ["STS925"],
"trace_id": "0HMV...",
"timestamp": "2026-05-20T08:42:17Z"
}
error(erforderlich):invalid_request,invalid_target,invalid_scopeoderunauthorized_client(RFC 8693 §2.2.2).error_description(optional): Kurze, lesbare Begründung ohne sensible Daten.error_codes(optional): CMI-spezifische Fehlercodes, dokumentiert in ErrorCodes.md.
Beispiel mit Actor-Token
Eine Web-API ruft den CMI Server stellvertretend für den eingeloggten Benutzer auf und weist sich gleichzeitig per actor_token aus. Der Client muss TokenExchange.AllowDelegation=true und mindestens einen Eintrag in TokenExchange.AllowedActorIssuers haben.
(Zeilenumbrüche und fehlende URL-Codierung dienen nur der besseren Lesbarkeit)
POST /{tenant id}/identity/connect/token HTTP/1.1
Host: {CMI STS host}
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&client_id=<CLIENT_ID>
&client_secret=<CLIENT_SECRET>
&subject_token=<SUBJECT_TOKEN>
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&actor_token=<ACTOR_TOKEN>
&actor_token_type=urn:ietf:params:oauth:token-type:access_token
&audience=https://cmi-server.example.com
&scope=metatool
Das ausgestellte Token enthält gemäss RFC 8693 §4.1 einen act-Claim als JSON-Objekt. Hat das Subject-Token bereits einen act-Claim aus einer früheren Delegationsstufe, wird die bestehende Kette unter dem neuen Akteur verschachtelt (act.act):
// JWT-Payload-Auszug (illustrativ)
{
"iss": "https://sts.example.com/mandant",
"sub": "user-1234",
"aud": "https://sts.example.com/mandant/resources", // statische STS-Audience, nicht die angefragte audience
"exp": 1747746000,
"act": {
"sub": "app-web-api",
"iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"act": {
"sub": "app-gateway", // ursprünglicher Akteur einer früheren Delegationsstufe
"iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0"
}
}
}
may_act-Pre-Authorization (optional): Trägt das Subject-Token einen may_act-Claim (RFC 8693 §4.4), gilt er als Vorab-Autorisierung des Subject-Token-Ausstellers für einen bestimmten Akteur. Der CMI STS erzwingt strikte Übereinstimmung: may_act.sub (und may_act.iss, falls vorhanden) müssen mit dem actor_token übereinstimmen, und ein Subject-Token mit may_act verlangt zwingend ein actor_token. Verstösse werden abgelehnt, siehe ErrorCodes.md.
Fehlercodes
Alle Fehlercodes des Token-Exchange-Grants (Bereich STS92x bis STS951) sind zentral in ErrorCodes.md dokumentiert. STS920 ist der Erfolgscode.
Sicherheitsmodell
Der Token-Exchange-Grant folgt durchgängig dem Default-Deny-Prinzip: Vor dem Einbau einer neuen Quelle, eines neuen Akteurs oder einer neuen Audience müssen die jeweiligen Allow-Listen explizit ergänzt werden; das Entfernen eines Eintrags sperrt die Quelle sofort. Die wichtigsten Hardening-Massnahmen:
- Trust-Chain: Nur Issuer aus
TrustedPartnerStsIssuers,OpenIdConnectIdPsoderTrustedSourceTenantswerden akzeptiert; pro Issuer JWKS-Discovery mit Last-Known-Good-Fallback. - Audience-Smuggling: All-or-Nothing-Check gegen
AllowedAudiences; bei OIDC-Quellen zusätzlich Audience-Bindung der Subject-/Actor-Tokens überAllowedSubjectAudiences/AllowedActorAudiences. - Subject-Spoofing: Die Identität stammt ausschliesslich aus dem validierten Subject-Token bzw. der CMI-Server-Antwort; Identitäts-Claims im Request-Body werden ignoriert.
- Delegation-Chain-Splicing:
AllowDelegationundAllowedActorIssuersmüssen beide gesetzt sein;may_act-Strict-Match; dieact-Kette ist auf eine maximale Tiefe von 10 begrenzt. - Scope-Elevation: Ausgestellt wird nur die Schnittmenge aus angefragten Scopes, Client-Scopes und Subject-Token-Scopes.
- Token-Lifetime-Extension: Das ausgestellte Token ist nie länger gültig als Subject- und Actor-Token (kryptographisch durchgesetzter Output-Lifetime-Cap). Für die eingereichten Tokens gibt es keinen zusätzlichen Lebensdauer-Cap; ein
iatin der Zukunft wird abgelehnt. - JWT-Profil: Signatur-Algorithmen-Allow-Liste (
RS256/PS256/ES256), Pflicht-Claimsiss/sub/exp/iat, Token-Grössen-Limit 16 KB. - Replay: Kein
jti-Replay-Cache — innerhalb der Token-Lebensdauer ist ein Mehrfach-Tausch desselbensubject_tokenmöglich; die Eingrenzung erfolgt über die kurzen Lebensdauern und die Audience-Bindung. - Audit-Datenlecks: Subject und Actor werden im Audit-Log nur als SHA-256-Prefix gespeichert, nie im Klartext.
Diagnose und Metriken
Der CMI STS emittiert zu jedem Token-Exchange-Request genau ein strukturiertes Audit-Event (TokenExchangeAuditEvent mit Client, Quelle, gehashten Subject-/Actor-Werten, Outcome, Fehlercode, Jti und TraceId) sowie Metriken:
CMI_STS3_tokenexchange_counter— zählt alle Token-Exchange-Requests. Labels: Tenant,CMI_STS3_tokenexchange_outcome(successoder der STS-Fehlercode, z. B.STS925) undCMI_STS3_tokenexchange_source_kind(InternalSts,OidcIdP,PartnerStsodernonebei frühen Ablehnungen ohne Subject-Token-Inspektion).CMI_STS3_tokenexchange_delegation_counter— zählt Requests, die einactor_tokenmitgeliefert haben, unabhängig vom Ergebnis.
Alerting-Hinweise: Häufungen des Outcomes STS930 deuten auf falsch konfigurierte Clients oder auf das Durchprobieren von Audiences hin; wiederkehrende STS925/STS946 auf einer source_kind deuten auf eine Drift zwischen Partner-STS-Konfiguration und dessen tatsächlichem Token-Inhalt hin. Jede Fehlerantwort trägt eine trace_id, mit der sich STS-Logs, Audit-Events und die HTTP-Antwort des Clients verknüpfen lassen.