Add agentic auth provider infrastructure#485
Conversation
|
This change is part of the following stack: Change managed by git-spice. |
c42fdca to
3d65157
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds “agentic auth provider” infrastructure across the SDK so API calls can obtain the correct token automatically (bot vs Agentic Identity), rather than requiring callers to always pre-wire an HTTP client token callback.
Changes:
- Introduces an
AgenticIdentitymodel and exposes it via the activityAccountmodel. - Adds an
AuthProviderprotocol plus an HTTP interceptor to injectAuthorizationwhen missing, and wires it throughApiClient/subclients; apps get anAppAuthProviderbacked byTokenManager. - Expands token-provider signatures to optionally accept
agentic_identity, and adds an inbound activity token validator that routes between Bot Framework and Entra token validation.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/common/tests/test_client.py | Adds tests ensuring interceptors are exposed read-only and cloned independently. |
| packages/common/src/microsoft_teams/common/http/client.py | Exposes interceptors and adjusts clone behavior around interceptor copying. |
| packages/apps/tests/test_token_validator.py | Adds tests for InboundActivityTokenValidator routing/caching and error cases. |
| packages/apps/tests/test_token_manager.py | Adds tests for agentic identity propagation into token providers and AppAuthProvider behavior. |
| packages/apps/src/microsoft_teams/apps/token_manager.py | Adds app-token API, agentic identity token-provider support, and signature-aware token-provider invocation. |
| packages/apps/src/microsoft_teams/apps/options.py | Switches app options token typing to shared TokenProvider. |
| packages/apps/src/microsoft_teams/apps/http/http_server.py | Switches inbound auth validation to InboundActivityTokenValidator. |
| packages/apps/src/microsoft_teams/apps/auth/token_validator.py | Adds InboundActivityTokenValidator, Entra v1 issuer constant, and bounded validator caching. |
| packages/apps/src/microsoft_teams/apps/auth/init.py | Exports InboundActivityTokenValidator. |
| packages/apps/src/microsoft_teams/apps/auth_provider.py | Adds AppAuthProvider that uses TokenManager for app vs agentic tokens. |
| packages/apps/src/microsoft_teams/apps/app.py | Wires ApiClient to use auth_provider rather than an HTTP-client token override. |
| packages/apps/pyproject.toml | Bumps cryptography minimum version. |
| packages/api/tests/unit/test_user_client.py | Verifies user client uses auth provider to mint bot tokens. |
| packages/api/tests/unit/test_bot_client.py | Adds token-provider signature compatibility tests and auth-provider sign-in test. |
| packages/api/tests/unit/test_base_client.py | Adds tests for interceptor precedence and agentic identity scope selection. |
| packages/api/src/microsoft_teams/api/models/agentic_identity.py | Introduces AgenticIdentity model (API layer). |
| packages/api/src/microsoft_teams/api/models/account.py | Adds agentic identity fields and helper property to build AgenticIdentity. |
| packages/api/src/microsoft_teams/api/models/init.py | Exports AgenticIdentity. |
| packages/api/src/microsoft_teams/api/clients/user/token_client.py | Threads auth_provider/cloud into user token client via BaseClient. |
| packages/api/src/microsoft_teams/api/clients/user/client.py | Threads auth_provider/cloud into UserClient and its subclient. |
| packages/api/src/microsoft_teams/api/clients/bot/token_client.py | Updates deprecated bot token client to support token-provider signatures with optional agentic arg. |
| packages/api/src/microsoft_teams/api/clients/bot/sign_in_client.py | Threads auth_provider/cloud into sign-in client via BaseClient. |
| packages/api/src/microsoft_teams/api/clients/bot/client.py | Threads auth_provider into BotClient subclient construction. |
| packages/api/src/microsoft_teams/api/clients/base_client.py | Adds AuthProvider protocol, attaches auth-provider interceptor, and provides agentic token factory helper. |
| packages/api/src/microsoft_teams/api/clients/api_client.py | Adds auth_provider plumbing into ApiClient and relevant subclients. |
| packages/api/src/microsoft_teams/api/clients/_auth_provider_interceptor.py | Adds request interceptor that injects Authorization via the auth provider when absent. |
| packages/api/src/microsoft_teams/api/auth/credentials.py | Defines TokenProvider typing to allow optional agentic_identity (positional or keyword). |
| packages/api/src/microsoft_teams/api/auth/cloud_environment.py | Adds agentic_bot_scope to cloud environments. |
| packages/api/src/microsoft_teams/api/auth/init.py | Exports new token-provider typing aliases. |
2958451 to
0addde5
Compare
5090e99 to
70506df
Compare
70506df to
e2b8163
Compare
|
Q: Can the "agentic vs bot" decision live in one place (the TokenManager) rather than three? Right now the choice of agentic token vs app/bot token - which is purely agentic_identity is None? - seems to be made in three spots that have to stay in sync: BaseClient._get_auth_token picks agentic_bot_scope + passes the identity when one exists Could the upstream layers just pass the identity (or None) and let TokenManager own the decision - i.e. a single get_token(scope_resource, identity) that internally chooses the bot vs agentic scope/tenant/mint path? The interceptor would then just be the identity=None case rather than a separate hardcoded branch. |
e2b8163 to
cfdbefa
Compare
|
Update: @MehakBindra - check the latest update. Here we're doing something similar as .net. Methods with agentic identity would stamp the request using |
| assert client.interceptors == (interceptor1,) | ||
| assert clone.interceptors == (interceptor1, interceptor2) | ||
| assert client.interceptors is not clone.interceptors |
cfdbefa to
e102800
Compare
e102800 to
5f44f4a
Compare
Adds agentic auth provider plumbing to the API layer. `ApiClient` is powered by `HttpClient` to make requests. Normally, `HttpClient` can take a token directly, but Agent ID calls need the SDK to choose between a regular bot token and an agentic identity token per request. So this PR does the following: 1. Introduces the `AgenticIdentity` model. 2. Introduces an `AuthProvider` concept at the `ApiClient` layer. If provided, auth can happen through `ApiClient` if HttpClient does not have a token revolver. 3. Installs an HTTP interceptor from `ApiClient`. The interceptor skips requests that already have `Authorization`, otherwise it uses the `AuthProvider`. 4. Uses `httpx` request extensions to mark per-request `AgenticIdentity` metadata. This is local-only metadata, not a header, so it does not leak to Teams endpoints. With this, we are basically stamping a request that requires agentic identity. 5. The interceptor reads that extension, picks the bot vs Agent ID scope, and passes the scope + identity to the `AuthProvider`. 6. Updates token-provider typing so custom token providers can receive `AgenticIdentity` when needed. 7. Sovereign cloud Agent ID scopes are TODO-marked until platform values are confirmed. No sneaky magic there.
This PR adds `AgenticIdentity` as a new auth context across the Teams API surface. Why: Agent ID calls need a user-shaped Agent ID token instead of the normal bot token. The API methods now accept `agentic_identity` where needed, and the shared auth interceptor uses local request metadata to pick the right auth path. Interesting bits: - Adds optional `agentic_identity` to conversation create, activity operations, conversation members, reactions, teams, and meetings. - Adds optional `service_url` overrides across the service-url based APIs touched here. - Agentic identity is passed through `httpx` request extensions, not headers. So it stays inside the client pipeline and does not leak to Teams endpoints. - The auth interceptor reads that extension and asks the auth provider for the right token. Reviewer tips: Start with the API method signatures, then the changed call sites in `ConversationActivityClient`, `ConversationMemberClient`, `ReactionClient`, `TeamClient`, and `MeetingClient`. The auth plumbing itself lives one PR down in #485. Testing: - Focused API unit tests for conversation, reaction, bot, user, team, and meeting clients. - Full test suite passed locally. Live smoke tested with Agent ID token: - conversation activity create/update/reply/get_members - conversation members get_all/get/get_paged - reactions add/delete - teams get_by_id/get_conversations - conversations.create - meetings get_by_id/get_participant Known limitation: - targeted activity create/update reached the service but returned 500. Leaving that as not proven until platform behavior is confirmed.

Adds agentic auth provider plumbing to the API layer.
ApiClientis powered byHttpClientto make requests. Normally,HttpClientcan take a token directly, but Agent ID calls need the SDK to choose between a regular bot token and an agentic identity token per request.So this PR does the following:
AgenticIdentitymodel.AuthProviderconcept at theApiClientlayer. If provided, auth can happen throughApiClientif HttpClient does not have a token revolver.ApiClient. The interceptor skips requests that already haveAuthorization, otherwise it uses theAuthProvider.httpxrequest extensions to mark per-requestAgenticIdentitymetadata. This is local-only metadata, not a header, so it does not leak to Teams endpoints. With this, we are basically stamping a request that requires agentic identity.AuthProvider.AgenticIdentitywhen needed.