Context
Split from #262. The A2A HTTP gateway currently supports X-Api-Key authentication (added in #261). This issue adds JWT/Bearer token authentication as a second scheme and wires end-to-end claims propagation so the agent can independently verify caller identity.
JWT/Bearer token authentication
The gateway's auth infrastructure was designed to support multiple schemes via ASP.NET Core's AddAuthentication().AddScheme() pattern.
Open questions
- Identity provider: Should JWT validation be generic OIDC (validate against a configurable
Authority/Audience via jwks_uri), or targeted at a specific provider (Azure AD, Auth0, Keycloak)? Generic OIDC with configurable Authority/Audience seems most flexible.
End-to-end token/claims propagation to the agent
Currently the gateway validates the API key and passes only the caller's string identity as the Source field on the RabbitMQ envelope. The agent trusts this at face value (NameBasedAgentIdentityVerifier, IsSelfAsserted: true). For production hardening, the agent should be able to independently verify the caller.
Notes
- The existing
ApiKeyAuthenticationHandler produces claims (NameIdentifier, Name, custom issuer) that can serve as the pattern for the JWT handler
- The
WellKnownHeaders class can be extended with rb-auth-token / rb-auth-claims constants
IAgentIdentityVerifier and VerifiedAgentIdentity are already in RockBot.A2A.Abstractions
Context
Split from #262. The A2A HTTP gateway currently supports X-Api-Key authentication (added in #261). This issue adds JWT/Bearer token authentication as a second scheme and wires end-to-end claims propagation so the agent can independently verify caller identity.
JWT/Bearer token authentication
The gateway's auth infrastructure was designed to support multiple schemes via ASP.NET Core's
AddAuthentication().AddScheme()pattern.subclaim extraction for caller identityAgentCard.SecuritySchemesto advertise both API key and Bearer schemesOpen questions
Authority/Audienceviajwks_uri), or targeted at a specific provider (Azure AD, Auth0, Keycloak)? Generic OIDC with configurable Authority/Audience seems most flexible.End-to-end token/claims propagation to the agent
Currently the gateway validates the API key and passes only the caller's string identity as the
Sourcefield on the RabbitMQ envelope. The agent trusts this at face value (NameBasedAgentIdentityVerifier,IsSelfAsserted: true). For production hardening, the agent should be able to independently verify the caller.MessageEnvelopecustom headers (e.g.,rb-auth-tokenorrb-auth-claims) — the envelope already supports aheadersdictionaryIAgentIdentityVerifierthat validates the forwarded token/claims instead of trusting theSourcestringIsSelfAsserted: falseand populateVerifiedAgentIdentity.Issuerwith the IdP issuer andClaimswith the verified claimsVerifiedAgentIdentityalready hasClaims,Issuer, andIsSelfAssertedfields designed for thisNotes
ApiKeyAuthenticationHandlerproduces claims (NameIdentifier,Name, customissuer) that can serve as the pattern for the JWT handlerWellKnownHeadersclass can be extended withrb-auth-token/rb-auth-claimsconstantsIAgentIdentityVerifierandVerifiedAgentIdentityare already inRockBot.A2A.Abstractions