Commit f8128de7 authored by Sergio Gimenez's avatar Sergio Gimenez Committed by Dimitrios Gogos
Browse files

docs(fm): align EWBI flows with OPG.04

Replace stale mTLS and custom-route assumptions with the OAuth2 trust model and canonical GSMA contract. Record upstream OpenAPI defects as an explicit profile instead of silent deviations.
parent 23a9e4e4
Loading
Loading
Loading
Loading
+6 −7
Changes for decisions/0016-fm-python-fastapi-stack.md: 6 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -27,15 +27,14 @@ exception; (b) FM follows the platform stack — a single Python/FastAPI service

Option (b). FM is one Python/FastAPI service like every other OOP component, following the same
hexagonal `python-template` layout and importing oop-commons. Nginx (already in front of every
service) terminates TLS/mTLS and forwards the client certificate to FM in a header; FM middleware
validates the certificate thumbprint. Outbound EWBI mTLS uses `httpx` with per-partner client
certificates. There is no Envoy sidecar and no Go control plane.
service) terminates HTTPS and routes the canonical EWBI path to FM. OAuth2 Client-Credentials is
the current EWBI authorization mechanism (ADR-0038); `httpx` handles outbound token acquisition
and Bearer-authenticated partner calls. There is no Envoy sidecar and no Go control plane.

## Consequences

Single-language stack: shared Pydantic models, shared auth/logging/health middleware, shared
developer knowledge; one deployable, one scaling model (stateless horizontal pods). Cost: FM does
not get Envoy's battle-tested mTLS/filter machinery — certificate handling and header stripping
are FM application code and must be covered by the topology-leakage and certificate-validation
test suites. Revisit trigger: EWBI traffic or mTLS policy complexity (revocation, SPIFFE-style
rotation) outgrowing what Nginx + FastAPI middleware can express.
not get Envoy's policy/filter machinery, so Bearer-token validation and header stripping are FM
application code and require security tests. If mTLS sender-binding is added later (ADR-0038),
revisit whether its revocation and rotation policy still fits Nginx + FastAPI.
+7 −7
Changes for decisions/0042-ewbi-oauth2-client-credentials-mtls-deferred.md: 7 added lines, 7 removed lines.
Original line number Diff line number Diff line
---
type: Decision Record
title: "ADR-0042: EWBI authorization is OAuth2 Client-Credentials via centralized Keycloak; mTLS is deferred defense-in-depth"
description: "FM authorizes E/WBI requests with OAuth2 Client-Credentials + signed JWT (OPG.04 Sec. 9), issued by the platform's centralized Keycloak in a dedicated federation realm; mTLS is not built yet and is reclassified as a future layer, not the primary mechanism"
title: "ADR-0042: EWBI authorization is OAuth2 Client-Credentials; mTLS is deferred defense-in-depth"
description: "FM authorizes E/WBI requests with OAuth2 Client-Credentials + signed JWT (OPG.04 Sec. 9); our Keycloak issues inbound tokens, each partner's Authorization Server issues outbound tokens, and mTLS is deferred"
tags: [adr, fm, federation, security]
timestamp: 2026-08-06T00:00:00Z
status: "accepted"
---

# ADR-0042: EWBI authorization is OAuth2 Client-Credentials via centralized Keycloak; mTLS is deferred defense-in-depth
# ADR-0042: EWBI authorization is OAuth2 Client-Credentials; mTLS is deferred defense-in-depth

**Status:** accepted
**Date:** 2026-08-06
@@ -35,14 +35,14 @@ The platform already runs a centralized Keycloak as core shared infrastructure (

## Decision

1. **E/WBI authorization is OAuth2 Client-Credentials + signed JWT (OPG.04 Sec. 9), issued and validated via the platform's centralized Keycloak, in a dedicated `federation` realm** — separate from the `oop` realm used for internal admin and (via OEG) app-provider auth. Rationale for a separate realm: partner OPs are an external, adversarial-by-default trust domain; isolating it from internal/admin identity is standard practice and cheap given Keycloak already supports multiple realms on one deployment. Each partner relationship gets its own Keycloak client with the `fed-mgmt` scope (`fed-mgmt-notif` for callbacks); FM is both a Client (outbound calls to a partner's realm) and an Authorization+Resource Server (inbound calls, via its own realm) per OPG.04 Sec. 9.2.
2. **mTLS is not deleted, it is reclassified as deferred defense-in-depth.** `partner_ops.cert_thumbprint` stays in the schema as a future hook (e.g. RFC 8705 sender-constrained tokens once real Nginx mTLS termination exists); it is removed from today's authorization decision path. Today's cert-thumbprint-header check is not real authentication and must not be described as satisfying REQ-FED-01 on its own.
1. **E/WBI authorization is OAuth2 Client-Credentials + signed JWT (OPG.04 Sec. 9).** For inbound calls, the partner is a client of our platform's centralized Keycloak, using the dedicated `federation` realm; FM validates the resulting token. For outbound calls, FM is a client of the partner OP's Authorization Server and obtains the token from that partner's token endpoint. The local `federation` realm stays separate from the `oop` realm used for internal admin and app-provider authentication. Each partner gets its own local Keycloak client with the `fed-mgmt` scope (`fed-mgmt-notif` for callbacks).
2. **mTLS is not built and is reclassified as deferred defense-in-depth.** No certificate thumbprint or client-certificate path is retained in today's `partner_ops` schema. When sender-constrained tokens are designed (for example RFC 8705), the required trust and certificate fields will be introduced with that design. Today's caller-supplied thumbprint header proves no identity and is removed completely.
3. Signing is JWS (RFC 7515), matching Keycloak's default and OPG.04 Sec. 9.3's primary recommendation — not the Sec. 9.3 pre-shared-symmetric-key (MAC) alternative, which only earns its keep when there is no real Authorization Server to lean on. There is one.

## Consequences

FM gains a real dependency on the centralized Keycloak (already a platform dependency for OEG and FM's own admin routes, so no new infrastructure). FM must implement: inbound Bearer-JWT validation (signature via Keycloak's JWKS, issuer, expiry, `fed-mgmt` scope) replacing today's cert-thumbprint gate; outbound Client-Credentials token acquisition and caching before calling a partner. `partner_ops` needs OAuth2 client-credential fields per partner (client_id, and a reference to where the secret is stored) alongside the retained `cert_thumbprint` column.
FM gains a real dependency on the centralized Keycloak for inbound EWBI authorization (already a platform dependency for OEG and FM's own admin routes, so no new infrastructure). FM must implement inbound Bearer-JWT validation (signature via Keycloak's JWKS, issuer, expiry, `fed-mgmt` scope) and outbound Client-Credentials token acquisition and caching before calling a partner. `partner_ops` stores the partner's inbound client identity plus our outbound client ID, token endpoint, and a reference to the mounted secret; it stores no OAuth client secret inline.

Cost: FM does not get to skip Authorization Server work by leaning on Nginx alone — Nginx's role here stays limited to HTTPS termination and routing, not the authorization decision. Revisit trigger: real Nginx mTLS termination is deployed (ADR-0016's original assumption) — at that point, sender-constrained tokens (RFC 8705) can layer mTLS back in as defense-in-depth, per the E/WBI security model both GSMA documents (OPG.02 Sec. 4.2.3/3.3.4.5, OPG.04 Sec. 9) actually describe: connection-level mutual authentication *and* request-level OAuth2 authorization, stacked, not substituted.
Cost: FM does not get to skip Authorization Server work by leaning on Nginx alone — Nginx's role here stays limited to HTTPS termination and routing, not the authorization decision. OPG.04 Sec. 9 requires TLS and OAuth2 but defines no mTLS OpenAPI security scheme. If the project later adds RFC 8705 sender-binding, that is a separate project decision grounded in OPG.02 Sec. 4.2.3/3.3.4.5, not a claim that OPG.04 currently mandates mTLS.

This ADR does not change FM's stack choice (ADR-0016 stands); it corrects only the E/WBI authorization mechanism ADR-0016 assumed in passing.
+1 −1
Changes for decisions/index.md: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -44,4 +44,4 @@ the reasoning lives here. Never renumber; supersede instead (see the record-deci
* [ADR-0039](0039-source-spec-stated-by-publisher.md) - source_spec is stated by the publishing component (OEG from CAMARA, FM from OPG.04) on network capability commands; SRM never derives it from the envelope source and never synthesizes a family, API, or version
* [ADR-0040](0040-target-serveability-is-a-tri-state.md) - can_serve_target answers can_serve | unknown_subscriber | unsupported_identifier; a boolean cannot carry the 404/422 split §E.2 requires, and 404 needs positive evidence (supersedes ADR-0038's boolean)
* [ADR-0041](0041-tfsdk-owns-adapter-construction.md) - TF-SDK builds adapters behind a factory keyed by adapter kind; SRM resolves control_path_ref to an instance but never enumerates adapter kinds
* [ADR-0042](0042-ewbi-oauth2-client-credentials-mtls-deferred.md) - E/WBI authorization is OAuth2 Client-Credentials via centralized Keycloak (dedicated federation realm), per OPG.04 Sec. 9; mTLS deferred to future defense-in-depth once real Nginx termination exists
* [ADR-0042](0042-ewbi-oauth2-client-credentials-mtls-deferred.md) - E/WBI authorization is OAuth2 Client-Credentials: local Keycloak for inbound, partner Authorization Server for outbound; mTLS deferred
+136 −96

File changed.

Preview size limit exceeded, changes collapsed.

+96 −38

File changed.

Preview size limit exceeded, changes collapsed.

Loading