Skip to content

Feat: RFC 7523 cross-IdP federated token exchange (Keycloak JWT → Entra/Okta) #525

Description

@akram

Summary

Add support for RFC 7523 (JWT Bearer Client Assertion) as a cross-IdP federation mechanism, enabling agents with Keycloak-issued tokens to obtain tokens from external IdPs (Entra ID, Okta) without credential duplication.

Problem

Today, AuthBridge's token exchange operates within a single IdP: agents authenticate to Keycloak and exchange tokens for Keycloak-protected services. When an agent needs to call APIs protected by a different IdP (Microsoft Graph via Entra, Salesforce via Okta), there is no mechanism to exchange a Keycloak token for an external IdP token.

The RFC 7523 Flow

Agent (has Keycloak JWT)
  → AuthBridge intercepts outbound call to graph.microsoft.com
  → Route matches: provider=entra, credential=federated
  → POST to login.microsoftonline.com/{tenant}/oauth2/v2.0/token
      grant_type=client_credentials
      client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
      client_assertion=<keycloak-jwt>
      scope=https://graph.microsoft.com/.default
  → Entra validates Keycloak JWT against Federated Identity Credential config
  → Returns Entra access token
  → AuthBridge attaches Entra token to outbound request

The agent code never knows Entra/Okta exists. AuthBridge handles the cross-IdP exchange transparently.

Prerequisites on the external IdP side

Entra ID (config-only, no code)

  • Create a Federated Identity Credential on the Agent Identity pointing to Keycloak's OIDC issuer
  • Subject claim matches the agent's Keycloak client ID (namespace/workload)

Okta (config-only, no code)

  • Configure a Custom Authorization Server with a Token Exchange policy
  • Add Keycloak as a trusted token issuer

What this enables

The "three-IdP enterprise" routing table:

routes:
  # Microsoft APIs → Entra (federated from Keycloak)
  - match: "graph.microsoft.com/*"
    token_exchange: { provider: entra, credential: federated }
  # SaaS APIs → Okta (federated from Keycloak)
  - match: "*.salesforce.com/*"
    token_exchange: { provider: okta, credential: federated }
  # Internal APIs → Keycloak (direct, works today)
  - match: "*.internal.company.com/*"
    token_exchange: { provider: keycloak }

Implementation notes

  • The RFC 7523 flow is the same for both Entra and Okta — a standard client_credentials grant with client_assertion_type=jwt-bearer and the Keycloak JWT as the assertion.
  • A generic RFC 7523 implementation covers both IdPs (and Auth0, Ping, ForgeRock, etc.) rather than building separate plugins per IdP.
  • This may require extending the IdPProvider interface (feat(authbridge): make token-exchange plugin interface IDP-agnostic #481) with a credential: federated concept, or it may be a new credential type alongside client-secret and spiffe.
  • Per-route provider selection (different IdP per destination) is a prerequisite — today the provider is global per plugin config.

Relationship to existing issues

References

Assisted-By: Claude (Anthropic AI) noreply@anthropic.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions