[Feat]: Improve client auth handling
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 45/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- python
- Lĩnh vực
- api, authentication, backend
Hướng nghiên cứu
Bắt đầu bằng cách đọc lớp AuthInterceptor hiện có trong src/a2a/client/auth/interceptor.py và ClientFactory trong src/a2a/client/client_factory.py. Tìm hiểu cách các lược đồ bảo mật của AgentCard được định nghĩa trong src/a2a/types.py. Mục tiêu là thiết kế một ClientCredentialManager có thể đối sánh các lược đồ bảo mật và tự động đính kèm thông tin xác thực. Kiểm tra cách các transport khác nhau (HTTP, gRPC) xử lý việc xác thực. Một proof of concept sẽ bao gồm việc mở rộng ClientConfig để chấp nhận một credential manager và sửa đổi luồng tạo client để inject các interceptor phù hợp.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Is your feature request related to a problem? Please describe.
Agents declare their authentication requirements via the security_schemes and security fields in the AgentCard. Skills can also declare required security.
Clients are responsible for understanding how to fulfill these authentication requirements. As of now, this is effectively left to the developer to roll this code themselves. However, in some cases, the SecuritySchemes object contains enough information to programmatically determine how to fulfill the auth requirements. We should provide a base implementation for this that handles common use cases (such as OAuth).
The AuthInterceptor class class is a start, but we're missing pieces for easily using it. AuthInterceptor handles the work of placing the credential in the right HTTP header (if known). It's still up to the developer to set up a CredentialService and pass the AuthInterceptor in the right spots. We can do better.
Describe the solution you'd like
Many auth schemes require, at minimum, some configuration in order to fulfill. For OAuth, if you want to generate access tokens on demand, you need a Client ID and Secret. For API Key authentication, you need the key to be sent. For mTLS, you need a client certificate to use. Once you have this, however, it's generally possible to handle the authentication with common code.
My idea for the interface is essentially:
- Load up an object with a bunch of authentication configurations.
- Provide this object to the
ClientFactory, perhaps via ClientConfig. - When a client is constructed, analyze the SecuritySchemes + security in the AgentCard to determine whether we have sufficient information to meet the authentication requirements for the agent.
- If so, compose a credential handling object that wraps the logic needed to fulfill the authentication requirements and provide this to the client.
- If not, we could raise a warning that we don't know how to fulfill the authentication for the agent. You can ignore this warning and continue, or treat this as an error and be unable to use the client.
- When interacting with the client, authentication is handled as transparently as possible. There are cases where the code using the client needs to provide additional information, such as for OAuth Authorization Code access tokens.
I have not fully investigated how feasible this is or what the pieces I'm missing are. Authentication code is generally pretty complex, so for complicated cases I expect we'll need a lot of thought for creating an appropriate interface.
Here's a rough sketch of how the code could look:
client_credential_manager = ClientCredentialManager()
# Methods for configuring well-known authentication types.
client_credential_manager.add_oauth_client(
id="google",
token_url="https://oauth2.googleapis.com/token",
authorization_url="https://accounts.google.com/o/oauth2/v2/auth",
client_config=(MY_CLIENT_ID, MY_CLIENT_SECRET),
use_authorization_code_flow=True,
)
client_credential_manager.add_mtls(
id="example-com-mtls",
certificate=MY_CLIENT_CERTIFICATE,
)
client_credential_manager.add_api_key(
id="cool-api-key",
host_domain="example.com",
api_key=MY_API_KEY,
)
# But generalized underpinnings to be extensible.
# Something like AuthScheme.matches(SecurityScheme) and AuthScheme.get_handler(AgentCard, SecurityScheme)
custom_auth_scheme = MyAuthScheme()
client_credential_manager.add_handler(
id="my-custom-auth",
scheme=custom_auth_scheme
)
client_config = ClientConfig(
# ... Normal config stuff,
credential_manager=client_credential_manager
)
client_factory = ClientFactory(client_config)
And using the client should be as transparent as possible:
some_agent_card = AgentCard(
url="https://agents.example.com/magic",
# ...
security_schemes = {
"google_oauth": OAuth2SecurityScheme(
flows=OAuthFlows(
authorization_code=AuthorizationCodeOAuthFlow(
authorization_url="https://accounts.google.com/o/oauth2/v2/auth",
# ...
)
)
),
},
security=[{"google_oauth": []}, {}],
)
# Credential manager helps match and fulfill auth schemes.
client = client_factory.create(some_agent_card)
# Yay, it just works!
client.send_message(new_text_message("Hello!"))
Some additional thoughts:
- We should handle both patterns of statically configured credentials and dynamically sourced credentials. Users may want to use request-level context to choose what credentials are provided on a request.
- However, we should be able to know whether we have any chance at all of fulfilling auth requirements at client construction time.
- OAuth is a really big use case, so we should build out as much support for this as we can. This should include being able to retrieve access tokens stored in a secret manager or performing an authorization flow on demand.
- Our underlying abstractions should be pretty flexible -- be able to match an auth scheme against a SecurityScheme, and some kind of handler that alters outgoing requests to attach credentials. This gets a little complicated with our various transports -- JSON-RPC and REST use HTTP headers, gRPC uses Metadata. Something more esoteric might not have an equivalent side-channel, so there might be some interaction with
ClientTransportimplementations.
Describe alternatives you've considered
We currently have some initial support for ClientCallInterceptors. This was built with auth in mind, but hasn't been integrated as smoothly as we'd like and it isn't clear how it works with all transports. We may use ClientCallInterceptors and ClientCallContext under the hood, but it should be largely transparent to users.
There's some initial auth support in src/a2a/client/auth, but it's not as extensive as what I'm proposing. It's the right start, but needs to be cleaned up and better structured.
Additional context
No response
Code of Conduct
- I agree to follow this project's Code of Conduct
- Ngôn ngữ chính
- Python
- Star
- 2.2k
- Fork
- 499
- Merge trung bình
- 3 ngày 20 giờ
- Pull request đã merge (30 ngày)
- 32
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của a2aproject/a2a-python
-
maintainers-only
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
a2aproject/a2a-python#805 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
v0.3 gRPC and REST SendMessage return no history when history_length is not setCó thể đã có người làm @rohityan đã nhận 1 ngày trước. Đang mở
a2aproject/a2a-python#1305 · 2 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug]: DefaultRequestHandlerV2 keeps the ActiveTask (producer, consumer, 2 dispatchers) alive forever after a direct Message or input-required responseCó thể đã có người làm @rohityan đã nhận 1 ngày trước. Đang mở
a2aproject/a2a-python#1296 · 2 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Feat]: Change Httpx to Httpx2Có thể đã có người làm @rohityan đã nhận 2 ngày trước. Đang mởcomponent: client status: needs review
a2aproject/a2a-python#1288 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug]: Streaming follow-up on an existing task does not begin with a Task; enqueuing the current task drops the follow-up message from historyCó thể đã có người làm @rohityan đã nhận 3 ngày trước. Đang mởcomponent: server status:awaiting response
a2aproject/a2a-python#1285 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của a2aproject/a2a-python
Issue tương tự
-
P4: low tooling
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
jeffknupp/association#318 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
petercorke/robotics-toolbox-python#709 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
MakerYuichi/Aegis-pro#114 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
mpfaffenberger/code_puppy#985 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày