agentic-community / agentic-community/mcp-gateway-registry
Egress OBO: Keycloak RFC 8693 token-exchange path (Phase 4 follow-up to #1269)
- Dominant language
- Python
- Stars
- 912
- Forks
- 234
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 62
Description
Follow-up to #1269 (which shipped the `token-exchange` / `obo_exchange` egress mode with the **Microsoft Entra `jwt-bearer`** provider path). This issue tracks the remaining provider path.
## Problem
The OBO egress mode (`egress_auth_mode = "obo_exchange"`) is implemented and working for Entra, but the **Keycloak RFC 8693 token-exchange** path is a deliberate Phase-4 stub: `auth_server/egress_obo.py` `_keycloak_exchange_body()` raises `OboUnsupportedIdpError("Keycloak OBO token-exchange (RFC 8693) is not yet implemented; Entra (jwt-bearer) ships first. Tracked as Phase 4.")`.
## Proposed solution
Implement the Keycloak branch of `obo_exchange`:
- RFC 8693 token exchange: `grant_type=urn:ietf:params:oauth:grant-type:token-exchange`, the user's ingress token as `subject_token` (with `subject_token_type=...:access_token`), and the backend as the `audience` (bare target client id, not Entra's `scope=api://.../.default`).
- Reuse the auth-server's configured Keycloak token endpoint and client credentials.
- Same fail-closed contract as the Entra path: strip the ingress token, exchange, inject; on failure return an error with no relay and no client-credentials fallback.
- Reject a backend audience the realm does not own (no federation guessing).
## Acceptance criteria
- [ ] Keycloak branch of `_keycloak_exchange_body` / `obo_exchange` implemented (no longer raises).
- [ ] Against a same-realm Keycloak backend, the exchanged token preserves the user identity (delegated, not client-only).
- [ ] Exchange failure returns an error with no relay and no client-credentials fallback.
- [ ] The egress path logs no token material.
## Out of scope
Public SaaS backends (served by `vault-oauth`); the `vault-pat` and custom-header modes (#1268).
Contributor guide
Research direction
Start in `auth_server/egress_obo.py`, focusing on `_keycloak_exchange_body()` and `obo_exchange`, and mirror the existing Entra flow for request structure and fail-closed behavior. Implement the Keycloak RFC 8693 token-exchange body with `grant_type`, `subject_token`, `subject_token_type`, and `audience` using the configured Keycloak token endpoint and client credentials. Then verify the path handles rejected realms/audiences, exchange failures, and no relay/no fallback behavior, with no token material appearing in logs; done when the current `OboUnsupportedIdpError` stub is removed and expectations around successful/failed delegated exchange are covered in auth-server egress OBO tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authentication
- Issue type
- Feature
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100