99import fastapi .responses
1010from a2a .server .apps import A2AFastAPIApplication
1111from a2a .server .apps .rest .rest_adapter import RESTAdapter
12- from a2a .types import AgentCard , AgentInterface , TransportProtocol
12+ from a2a .types import AgentCard , AgentInterface , HTTPAuthSecurityScheme , SecurityScheme , TransportProtocol
1313from a2a .utils import AGENT_CARD_WELL_KNOWN_PATH
1414from fastapi import Depends , HTTPException , Request
1515
1616from agentstack_server .api .dependencies import (
1717 A2AProxyServiceDependency ,
18+ ConfigurationDependency ,
1819 ProviderServiceDependency ,
1920 RequiresPermissions ,
2021)
22+ from agentstack_server .configuration import Configuration
2123from agentstack_server .domain .models .permissions import AuthorizedUser
2224from agentstack_server .service_layer .services .a2a import A2AServerResponse
2325
2426router = fastapi .APIRouter ()
2527
2628
27- def create_proxy_agent_card (agent_card : AgentCard , * , provider_id : UUID , request : Request ) -> AgentCard :
29+ def create_proxy_agent_card (
30+ agent_card : AgentCard , * , provider_id : UUID , request : Request , configuration : Configuration
31+ ) -> AgentCard :
2832 proxy_base = str (request .url_for (a2a_proxy_jsonrpc_transport .__name__ , provider_id = provider_id ))
33+
34+ proxy_security = []
35+ proxy_security_schemes = {}
36+ if not configuration .auth .disable_auth :
37+ # Note that we're purposefully not using oAuth but a more generic http scheme.
38+ # This is because we don't want to declare the auth metadata but prefer discovery through related RFCs
39+ # The http scheme also covers internal jwt tokens
40+ proxy_security .append ({"bearer" : []})
41+ proxy_security_schemes ["bearer" ] = SecurityScheme (HTTPAuthSecurityScheme (scheme = "bearer" ))
42+ if configuration .auth .basic .enabled :
43+ proxy_security .append ({"basic" : []})
44+ proxy_security_schemes ["basic" ] = SecurityScheme (HTTPAuthSecurityScheme (scheme = "basic" ))
45+
2946 return agent_card .model_copy (
3047 update = {
3148 "preferred_transport" : TransportProtocol .jsonrpc ,
@@ -34,6 +51,8 @@ def create_proxy_agent_card(agent_card: AgentCard, *, provider_id: UUID, request
3451 AgentInterface (transport = TransportProtocol .http_json , url = urljoin (proxy_base , "http" )),
3552 AgentInterface (transport = TransportProtocol .jsonrpc , url = proxy_base ),
3653 ],
54+ "security" : proxy_security ,
55+ "security_schemes" : proxy_security_schemes ,
3756 }
3857 )
3958
@@ -51,10 +70,13 @@ async def get_agent_card(
5170 provider_id : UUID ,
5271 request : Request ,
5372 provider_service : ProviderServiceDependency ,
73+ configuration : ConfigurationDependency ,
5474 _ : Annotated [AuthorizedUser , Depends (RequiresPermissions (providers = {"read" }))],
5575) -> AgentCard :
5676 provider = await provider_service .get_provider (provider_id = provider_id )
57- return create_proxy_agent_card (provider .agent_card , provider_id = provider .id , request = request )
77+ return create_proxy_agent_card (
78+ provider .agent_card , provider_id = provider .id , request = request , configuration = configuration
79+ )
5880
5981
6082@router .post ("/{provider_id}" )
@@ -64,10 +86,13 @@ async def a2a_proxy_jsonrpc_transport(
6486 request : fastapi .requests .Request ,
6587 a2a_proxy : A2AProxyServiceDependency ,
6688 provider_service : ProviderServiceDependency ,
89+ configuration : ConfigurationDependency ,
6790 user : Annotated [AuthorizedUser , Depends (RequiresPermissions (a2a_proxy = {"*" }))],
6891):
6992 provider = await provider_service .get_provider (provider_id = provider_id )
70- agent_card = create_proxy_agent_card (provider .agent_card , provider_id = provider .id , request = request )
93+ agent_card = create_proxy_agent_card (
94+ provider .agent_card , provider_id = provider .id , request = request , configuration = configuration
95+ )
7196
7297 handler = await a2a_proxy .get_request_handler (provider = provider , user = user .user )
7398 app = A2AFastAPIApplication (agent_card = agent_card , http_handler = handler )
@@ -83,11 +108,14 @@ async def a2a_proxy_http_transport(
83108 request : fastapi .requests .Request ,
84109 a2a_proxy : A2AProxyServiceDependency ,
85110 provider_service : ProviderServiceDependency ,
111+ configuration : ConfigurationDependency ,
86112 user : Annotated [AuthorizedUser , Depends (RequiresPermissions (a2a_proxy = {"*" }))],
87113 path : str = "" ,
88114):
89115 provider = await provider_service .get_provider (provider_id = provider_id )
90- agent_card = create_proxy_agent_card (provider .agent_card , provider_id = provider .id , request = request )
116+ agent_card = create_proxy_agent_card (
117+ provider .agent_card , provider_id = provider .id , request = request , configuration = configuration
118+ )
91119
92120 handler = await a2a_proxy .get_request_handler (provider = provider , user = user .user )
93121 adapter = RESTAdapter (agent_card = agent_card , http_handler = handler )
0 commit comments