fix(fm): refuse partner tokens not issued for us
sequenceDiagram
participant P as Partner FM
participant KC as our Keycloak (realm federation)
participant FM as our FM (EWBI)
P->>KC: client_credentials, scope fed-mgmt
KC-->>P: access token, aud "federation-manager" (audience mapper from the chart)
P->>FM: EWBI call, Bearer token
Note over FM: checks signature, issuer, expiry, fed-mgmt scope<br/>and now aud contains FM_KEYCLOAK_AUDIENCE
FM-->>P: 2xx, or 401 authentication-failed when aud is missing or names someone elseFM validated inbound EWBI tokens for signature, issuer, expiry and the fed-mgmt scope, but never looked at aud. Any token our Keycloak minted for another client in the federation realm would have passed. The Helm chart already puts an audience mapper (aud: federation-manager) on every partner client and its docs say FM checks it; until now FM didn't.
FM_KEYCLOAK_AUDIENCE sets the expected audience and defaults to federation-manager, the value the chart's mapper writes, so existing deployments need no new setting. A token without that audience gets the same 401 authentication-failed as a bad scope. The CI realm (keycloak/realm-import.json) and the test fixture realm get the mapper too, so the integration tests run against tokens shaped like a deployment's.
One extra test pins that a refused InstallApp leaves no install record. Deleting a refused attempt depends on FM answering 404 to SRM's instance read.
| Result | |
|---|---|
| full suite, Postgres + NATS + Keycloak as in CI | 437 passed, 1 skipped (432 on develop + 5 new) |
| mypy, ruff | clean |
testbed probe, ns oop: client in the federation realm without the mapper |
token has no aud; EWBI GET /{ctx}/health → 401 authentication-failed |
| same client after adding the mapper | aud: federation-manager; FM gets past the token and answers 401 partner-unknown (the probe isn't a registered partner) |
testbed, OP-1 portal → app on OP-2's Paris zone, all three operators running develop + this MR + feat/one-agreement-per-partner |
partner calls in both directions accepted; instance ready |
The unknown row is an older partner instance, deleted on OP-2 earlier. OEG !43 drops those rows from the list.
