microsoft-agents-hosting-core 0.7.0.dev10__tar.gz → 0.7.0.dev16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/PKG-INFO +2 -2
- microsoft_agents_hosting_core-0.7.0.dev16/VERSION.txt +1 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/__init__.py +0 -1
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/agent_application.py +12 -24
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/__init__.py +2 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/_handlers/__init__.py +2 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/_handlers/agentic_user_authorization.py +5 -2
- microsoft_agents_hosting_core-0.7.0.dev16/microsoft_agents/hosting/core/app/oauth/_handlers/connector_user_authorization.py +240 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/authorization.py +18 -8
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/access_token_provider_base.py +7 -3
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/agent_auth_configuration.py +29 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/anonymous_token_provider.py +7 -3
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/claims_identity.py +16 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/jwt_token_validator.py +2 -2
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/channel_service_adapter.py +1 -3
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/__init__.py +4 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/client/connector_client.py +0 -1
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/client/user_token_client.py +0 -1
- microsoft_agents_hosting_core-0.7.0.dev16/microsoft_agents/hosting/core/connector/mcs/__init__.py +3 -0
- microsoft_agents_hosting_core-0.7.0.dev16/microsoft_agents/hosting/core/connector/mcs/mcs_connector_client.py +249 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/errors/error_resources.py +15 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/http/_http_adapter_base.py +3 -6
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/rest_channel_service_client_factory.py +17 -3
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/memory_storage.py +0 -1
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/storage.py +0 -1
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/transcript_logger.py +0 -1
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents_hosting_core.egg-info/PKG-INFO +2 -2
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents_hosting_core.egg-info/SOURCES.txt +3 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents_hosting_core.egg-info/requires.txt +1 -1
- microsoft_agents_hosting_core-0.7.0.dev10/VERSION.txt +0 -1
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/LICENSE +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/MANIFEST.in +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/_oauth/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/_oauth/_flow_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/_oauth/_flow_storage_client.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/_oauth/_oauth_flow.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/activity_handler.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/agent.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/_routes/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/_routes/_route.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/_routes/_route_list.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/_routes/route_rank.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/_type_defs.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/app_error.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/app_options.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/input_file.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/_handlers/_authorization_handler.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/_handlers/_user_authorization.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/_sign_in_response.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/_sign_in_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/oauth/auth_handler.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/query.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/state/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/state/conversation_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/state/state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/state/temp_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/state/turn_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/streaming/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/streaming/citation.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/streaming/citation_util.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/streaming/streaming_response.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/app/typing_indicator.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/auth_types.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/authentication_constants.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/authorization/connections.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/card_factory.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/channel_adapter.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/channel_api_handler_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/channel_service_client_factory_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/agent_conversation_reference.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/channel_factory_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/channel_host_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/channel_info_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/channel_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/channels_configuration.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/configuration_channel_host.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/conversation_constants.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/conversation_id_factory.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/conversation_id_factory_options.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/conversation_id_factory_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/http_agent_channel.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/client/http_agent_channel_factory.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/agent_sign_in_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/attachments_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/client/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/connector_client_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/conversations_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/get_product_info.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/teams/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/teams/teams_connector_client.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/user_token_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/connector/user_token_client_base.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/errors/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/http/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/http/_channel_service_routes.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/http/_http_request_protocol.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/http/_http_response.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/message_factory.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/middleware_set.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/state/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/state/agent_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/state/state_property_accessor.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/state/user_state.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/__init__.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/_type_aliases.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/error_handling.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/store_item.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/transcript_file_store.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/transcript_info.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/transcript_memory_store.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/storage/transcript_store.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents/hosting/core/turn_context.py +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents_hosting_core.egg-info/dependency_links.txt +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/microsoft_agents_hosting_core.egg-info/top_level.txt +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/pyproject.toml +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/readme.md +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/setup.cfg +0 -0
- {microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/setup.py +0 -0
{microsoft_agents_hosting_core-0.7.0.dev10 → microsoft_agents_hosting_core-0.7.0.dev16}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: microsoft-agents-hosting-core
|
|
3
|
-
Version: 0.7.0.
|
|
3
|
+
Version: 0.7.0.dev16
|
|
4
4
|
Summary: Core library for Microsoft Agents
|
|
5
5
|
Author: Microsoft Corporation
|
|
6
6
|
License-Expression: MIT
|
|
@@ -15,7 +15,7 @@ Classifier: Operating System :: OS Independent
|
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: microsoft-agents-activity==0.7.0.
|
|
18
|
+
Requires-Dist: microsoft-agents-activity==0.7.0.dev16
|
|
19
19
|
Requires-Dist: pyjwt>=2.10.1
|
|
20
20
|
Requires-Dist: isodate>=0.6.1
|
|
21
21
|
Requires-Dist: azure-core>=1.30.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.7.0.dev16
|
|
@@ -120,11 +120,9 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
120
120
|
"ApplicationOptions.storage is required and was not configured.",
|
|
121
121
|
stack_info=True,
|
|
122
122
|
)
|
|
123
|
-
raise ApplicationError(
|
|
124
|
-
"""
|
|
123
|
+
raise ApplicationError("""
|
|
125
124
|
The `ApplicationOptions.storage` property is required and was not configured.
|
|
126
|
-
"""
|
|
127
|
-
)
|
|
125
|
+
""")
|
|
128
126
|
|
|
129
127
|
if options.long_running_messages and (
|
|
130
128
|
not options.adapter or not options.bot_app_id
|
|
@@ -133,12 +131,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
133
131
|
"ApplicationOptions.long_running_messages requires an adapter and bot_app_id.",
|
|
134
132
|
stack_info=True,
|
|
135
133
|
)
|
|
136
|
-
raise ApplicationError(
|
|
137
|
-
"""
|
|
134
|
+
raise ApplicationError("""
|
|
138
135
|
The `ApplicationOptions.long_running_messages` property is unavailable because
|
|
139
136
|
no adapter or `bot_app_id` was configured.
|
|
140
|
-
"""
|
|
141
|
-
)
|
|
137
|
+
""")
|
|
142
138
|
|
|
143
139
|
if options.adapter:
|
|
144
140
|
self._adapter = options.adapter
|
|
@@ -180,12 +176,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
180
176
|
"AgentApplication.adapter(): self._adapter is not configured.",
|
|
181
177
|
stack_info=True,
|
|
182
178
|
)
|
|
183
|
-
raise ApplicationError(
|
|
184
|
-
"""
|
|
179
|
+
raise ApplicationError("""
|
|
185
180
|
The AgentApplication.adapter property is unavailable because it was
|
|
186
181
|
not configured when creating the AgentApplication.
|
|
187
|
-
"""
|
|
188
|
-
)
|
|
182
|
+
""")
|
|
189
183
|
|
|
190
184
|
return self._adapter
|
|
191
185
|
|
|
@@ -203,12 +197,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
203
197
|
"AgentApplication.auth(): self._auth is not configured.",
|
|
204
198
|
stack_info=True,
|
|
205
199
|
)
|
|
206
|
-
raise ApplicationError(
|
|
207
|
-
"""
|
|
200
|
+
raise ApplicationError("""
|
|
208
201
|
The `AgentApplication.auth` property is unavailable because
|
|
209
202
|
no Auth options were configured.
|
|
210
|
-
"""
|
|
211
|
-
)
|
|
203
|
+
""")
|
|
212
204
|
|
|
213
205
|
return self._auth
|
|
214
206
|
|
|
@@ -592,12 +584,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
592
584
|
f"Failed to register sign-in success handler for route handler {func.__name__}",
|
|
593
585
|
stack_info=True,
|
|
594
586
|
)
|
|
595
|
-
raise ApplicationError(
|
|
596
|
-
"""
|
|
587
|
+
raise ApplicationError("""
|
|
597
588
|
The `AgentApplication.on_sign_in_success` method is unavailable because
|
|
598
589
|
no Auth options were configured.
|
|
599
|
-
"""
|
|
600
|
-
)
|
|
590
|
+
""")
|
|
601
591
|
return func
|
|
602
592
|
|
|
603
593
|
def on_sign_in_failure(
|
|
@@ -628,12 +618,10 @@ class AgentApplication(Agent, Generic[StateT]):
|
|
|
628
618
|
f"Failed to register sign-in failure handler for route handler {func.__name__}",
|
|
629
619
|
stack_info=True,
|
|
630
620
|
)
|
|
631
|
-
raise ApplicationError(
|
|
632
|
-
"""
|
|
621
|
+
raise ApplicationError("""
|
|
633
622
|
The `AgentApplication.on_sign_in_failure` method is unavailable because
|
|
634
623
|
no Auth options were configured.
|
|
635
|
-
"""
|
|
636
|
-
)
|
|
624
|
+
""")
|
|
637
625
|
return func
|
|
638
626
|
|
|
639
627
|
def error(
|
|
@@ -9,6 +9,7 @@ from ._sign_in_response import _SignInResponse
|
|
|
9
9
|
from ._handlers import (
|
|
10
10
|
_UserAuthorization,
|
|
11
11
|
AgenticUserAuthorization,
|
|
12
|
+
ConnectorUserAuthorization,
|
|
12
13
|
_AuthorizationHandler,
|
|
13
14
|
)
|
|
14
15
|
|
|
@@ -20,4 +21,5 @@ __all__ = [
|
|
|
20
21
|
"_SignInResponse",
|
|
21
22
|
"_UserAuthorization",
|
|
22
23
|
"AgenticUserAuthorization",
|
|
24
|
+
"ConnectorUserAuthorization",
|
|
23
25
|
]
|
|
@@ -4,11 +4,13 @@ Licensed under the MIT License.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from .agentic_user_authorization import AgenticUserAuthorization
|
|
7
|
+
from .connector_user_authorization import ConnectorUserAuthorization
|
|
7
8
|
from ._user_authorization import _UserAuthorization
|
|
8
9
|
from ._authorization_handler import _AuthorizationHandler
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"AgenticUserAuthorization",
|
|
13
|
+
"ConnectorUserAuthorization",
|
|
12
14
|
"_UserAuthorization",
|
|
13
15
|
"_AuthorizationHandler",
|
|
14
16
|
]
|
|
@@ -75,7 +75,7 @@ class AgenticUserAuthorization(_AuthorizationHandler):
|
|
|
75
75
|
agentic_instance_id = context.activity.get_agentic_instance_id()
|
|
76
76
|
assert agentic_instance_id
|
|
77
77
|
instance_token, _ = await connection.get_agentic_instance_token(
|
|
78
|
-
agentic_instance_id
|
|
78
|
+
context.activity.get_agentic_tenant_id(), agentic_instance_id
|
|
79
79
|
)
|
|
80
80
|
return (
|
|
81
81
|
TokenResponse(token=instance_token) if instance_token else TokenResponse()
|
|
@@ -131,7 +131,10 @@ class AgenticUserAuthorization(_AuthorizationHandler):
|
|
|
131
131
|
)
|
|
132
132
|
|
|
133
133
|
token = await connection.get_agentic_user_token(
|
|
134
|
-
|
|
134
|
+
context.activity.get_agentic_tenant_id(),
|
|
135
|
+
agentic_instance_id,
|
|
136
|
+
agentic_user_id,
|
|
137
|
+
scopes,
|
|
135
138
|
)
|
|
136
139
|
return TokenResponse(token=token) if token else TokenResponse()
|
|
137
140
|
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
Licensed under the MIT License.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import jwt
|
|
8
|
+
from datetime import datetime, timezone
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
from microsoft_agents.activity import TokenResponse
|
|
12
|
+
from microsoft_agents.hosting.core.errors import ErrorResources
|
|
13
|
+
|
|
14
|
+
from ...._oauth._flow_state import _FlowStateTag
|
|
15
|
+
from ....turn_context import TurnContext
|
|
16
|
+
from ....storage import Storage
|
|
17
|
+
from ....authorization import Connections
|
|
18
|
+
from ..auth_handler import AuthHandler
|
|
19
|
+
from ._authorization_handler import _AuthorizationHandler
|
|
20
|
+
from .._sign_in_response import _SignInResponse
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ConnectorUserAuthorization(_AuthorizationHandler):
|
|
26
|
+
"""
|
|
27
|
+
User Authorization handling for Copilot Studio Connector requests.
|
|
28
|
+
Extracts token from the identity and performs OBO token exchange.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
storage: Storage,
|
|
34
|
+
connection_manager: Connections,
|
|
35
|
+
auth_handler: Optional[AuthHandler] = None,
|
|
36
|
+
*,
|
|
37
|
+
auth_handler_id: Optional[str] = None,
|
|
38
|
+
auth_handler_settings: Optional[dict] = None,
|
|
39
|
+
**kwargs,
|
|
40
|
+
) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Creates a new instance of ConnectorUserAuthorization.
|
|
43
|
+
|
|
44
|
+
:param storage: The storage system to use for state management.
|
|
45
|
+
:type storage: Storage
|
|
46
|
+
:param connection_manager: The connection manager for OAuth providers.
|
|
47
|
+
:type connection_manager: Connections
|
|
48
|
+
:param auth_handler: Configuration for OAuth provider.
|
|
49
|
+
:type auth_handler: AuthHandler, Optional
|
|
50
|
+
:param auth_handler_id: Optional ID of the auth handler.
|
|
51
|
+
:type auth_handler_id: str, Optional
|
|
52
|
+
:param auth_handler_settings: Optional settings dict for the auth handler.
|
|
53
|
+
:type auth_handler_settings: dict, Optional
|
|
54
|
+
"""
|
|
55
|
+
super().__init__(
|
|
56
|
+
storage,
|
|
57
|
+
connection_manager,
|
|
58
|
+
auth_handler,
|
|
59
|
+
auth_handler_id=auth_handler_id,
|
|
60
|
+
auth_handler_settings=auth_handler_settings,
|
|
61
|
+
**kwargs,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
async def _sign_in(
|
|
65
|
+
self,
|
|
66
|
+
context: TurnContext,
|
|
67
|
+
exchange_connection: Optional[str] = None,
|
|
68
|
+
exchange_scopes: Optional[list[str]] = None,
|
|
69
|
+
) -> _SignInResponse:
|
|
70
|
+
"""
|
|
71
|
+
For connector requests, there is no separate sign-in flow.
|
|
72
|
+
The token is extracted from the identity.
|
|
73
|
+
|
|
74
|
+
:param context: The turn context for the current turn of conversation.
|
|
75
|
+
:type context: TurnContext
|
|
76
|
+
:param exchange_connection: Optional connection name for token exchange.
|
|
77
|
+
:type exchange_connection: Optional[str]
|
|
78
|
+
:param exchange_scopes: Optional list of scopes (unused for connector auth).
|
|
79
|
+
:type exchange_scopes: Optional[list[str]]
|
|
80
|
+
:return: A SignInResponse with the extracted token.
|
|
81
|
+
:rtype: _SignInResponse
|
|
82
|
+
"""
|
|
83
|
+
# Connector auth uses the token from the request, not a separate sign-in flow
|
|
84
|
+
token_response = await self.get_refreshed_token(context)
|
|
85
|
+
return _SignInResponse(
|
|
86
|
+
token_response=token_response, tag=_FlowStateTag.COMPLETE
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
async def get_refreshed_token(
|
|
90
|
+
self,
|
|
91
|
+
context: TurnContext,
|
|
92
|
+
exchange_connection: Optional[str] = None,
|
|
93
|
+
exchange_scopes: Optional[list[str]] = None,
|
|
94
|
+
) -> TokenResponse:
|
|
95
|
+
"""
|
|
96
|
+
Gets the connector user token and optionally exchanges it via OBO.
|
|
97
|
+
|
|
98
|
+
:param context: The turn context for the current turn of conversation.
|
|
99
|
+
:type context: TurnContext
|
|
100
|
+
:param exchange_connection: Optional name of the connection to use for token exchange.
|
|
101
|
+
:type exchange_connection: Optional[str], Optional
|
|
102
|
+
:param exchange_scopes: Optional list of scopes to request during token exchange.
|
|
103
|
+
:type exchange_scopes: Optional[list[str]], Optional
|
|
104
|
+
:return: The token response, potentially after OBO exchange.
|
|
105
|
+
:rtype: TokenResponse
|
|
106
|
+
"""
|
|
107
|
+
token_response = self._create_token_response(context)
|
|
108
|
+
|
|
109
|
+
# Check if token is expired
|
|
110
|
+
if token_response.expiration:
|
|
111
|
+
try:
|
|
112
|
+
# Parse ISO 8601 format
|
|
113
|
+
expiration = datetime.fromisoformat(
|
|
114
|
+
token_response.expiration.replace("Z", "+00:00")
|
|
115
|
+
)
|
|
116
|
+
if expiration <= datetime.now(timezone.utc):
|
|
117
|
+
raise ValueError(
|
|
118
|
+
f"Unexpected connector token expiration for handler: {self._id}"
|
|
119
|
+
)
|
|
120
|
+
except (ValueError, AttributeError) as ex:
|
|
121
|
+
logger.error(
|
|
122
|
+
f"Error checking token expiration for handler {self._id}: {ex}"
|
|
123
|
+
)
|
|
124
|
+
raise
|
|
125
|
+
|
|
126
|
+
# Perform OBO exchange if configured
|
|
127
|
+
try:
|
|
128
|
+
return await self._handle_obo(
|
|
129
|
+
context, token_response, exchange_connection, exchange_scopes
|
|
130
|
+
)
|
|
131
|
+
except Exception:
|
|
132
|
+
await self._sign_out(context)
|
|
133
|
+
raise
|
|
134
|
+
|
|
135
|
+
async def _sign_out(self, context: TurnContext) -> None:
|
|
136
|
+
"""
|
|
137
|
+
Sign-out is a no-op for connector authorization.
|
|
138
|
+
|
|
139
|
+
:param context: The turn context for the current turn of conversation.
|
|
140
|
+
:type context: TurnContext
|
|
141
|
+
"""
|
|
142
|
+
# No concept of sign-out with ConnectorAuth
|
|
143
|
+
logger.debug("Sign-out called for ConnectorUserAuthorization (no-op)")
|
|
144
|
+
|
|
145
|
+
async def _handle_obo(
|
|
146
|
+
self,
|
|
147
|
+
context: TurnContext,
|
|
148
|
+
input_token_response: TokenResponse,
|
|
149
|
+
exchange_connection: Optional[str] = None,
|
|
150
|
+
exchange_scopes: Optional[list[str]] = None,
|
|
151
|
+
) -> TokenResponse:
|
|
152
|
+
"""
|
|
153
|
+
Exchanges a token for another token with different scopes via OBO flow.
|
|
154
|
+
|
|
155
|
+
:param context: The context object for the current turn.
|
|
156
|
+
:type context: TurnContext
|
|
157
|
+
:param input_token_response: The input token to exchange.
|
|
158
|
+
:type input_token_response: TokenResponse
|
|
159
|
+
:param exchange_connection: Optional connection name for exchange.
|
|
160
|
+
:type exchange_connection: Optional[str]
|
|
161
|
+
:param exchange_scopes: Optional scopes for the exchanged token.
|
|
162
|
+
:type exchange_scopes: Optional[list[str]]
|
|
163
|
+
:return: The token response after exchange, or the original if exchange not configured.
|
|
164
|
+
:rtype: TokenResponse
|
|
165
|
+
"""
|
|
166
|
+
if not input_token_response:
|
|
167
|
+
return input_token_response
|
|
168
|
+
|
|
169
|
+
connection_name = exchange_connection or self._handler.obo_connection_name
|
|
170
|
+
scopes = exchange_scopes or self._handler.scopes
|
|
171
|
+
|
|
172
|
+
# If OBO is not configured, return token as-is
|
|
173
|
+
if not connection_name or not scopes:
|
|
174
|
+
return input_token_response
|
|
175
|
+
|
|
176
|
+
# Check if token is exchangeable
|
|
177
|
+
if not input_token_response.is_exchangeable():
|
|
178
|
+
raise ValueError(
|
|
179
|
+
str(ErrorResources.OboNotExchangeableToken.format(self._id))
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Get the connection that supports OBO
|
|
183
|
+
token_provider = self._connection_manager.get_connection(connection_name)
|
|
184
|
+
if not token_provider:
|
|
185
|
+
raise ValueError(
|
|
186
|
+
str(
|
|
187
|
+
ErrorResources.ResourceNotFound.format(
|
|
188
|
+
f"Connection '{connection_name}'"
|
|
189
|
+
)
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Perform the OBO exchange
|
|
194
|
+
# Note: In Python, the acquire_token_on_behalf_of method is on the AccessTokenProviderBase
|
|
195
|
+
token = await token_provider.acquire_token_on_behalf_of(
|
|
196
|
+
scopes=scopes,
|
|
197
|
+
user_assertion=input_token_response.token,
|
|
198
|
+
)
|
|
199
|
+
return TokenResponse(token=token) if token else None
|
|
200
|
+
|
|
201
|
+
def _create_token_response(self, context: TurnContext) -> TokenResponse:
|
|
202
|
+
"""
|
|
203
|
+
Creates a TokenResponse from the security token in the turn context identity.
|
|
204
|
+
|
|
205
|
+
:param context: The turn context for the current turn of conversation.
|
|
206
|
+
:type context: TurnContext
|
|
207
|
+
:return: A TokenResponse containing the extracted token.
|
|
208
|
+
:rtype: TokenResponse
|
|
209
|
+
:raises ValueError: If the identity doesn't have a security token.
|
|
210
|
+
"""
|
|
211
|
+
if not context.identity or not hasattr(context.identity, "security_token"):
|
|
212
|
+
raise ValueError(
|
|
213
|
+
f"Unexpected connector request - no security token found for handler: {self._id}"
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
security_token = context.identity.security_token
|
|
217
|
+
if not security_token:
|
|
218
|
+
raise ValueError(
|
|
219
|
+
f"Unexpected connector request - security token is None for handler: {self._id}"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
token_response = TokenResponse(token=security_token)
|
|
223
|
+
|
|
224
|
+
# Try to extract expiration and check if exchangeable
|
|
225
|
+
try:
|
|
226
|
+
# TODO: (connector) validate this decoding
|
|
227
|
+
jwt_token = jwt.decode(security_token, options={"verify_signature": False})
|
|
228
|
+
|
|
229
|
+
# Set expiration if present
|
|
230
|
+
if "exp" in jwt_token:
|
|
231
|
+
# JWT exp is in Unix timestamp (seconds since epoch)
|
|
232
|
+
expiration = datetime.fromtimestamp(jwt_token["exp"], tz=timezone.utc)
|
|
233
|
+
# Convert to ISO 8601 format
|
|
234
|
+
token_response.expiration = expiration.isoformat()
|
|
235
|
+
|
|
236
|
+
except Exception as ex:
|
|
237
|
+
logger.warning(f"Failed to parse JWT token for handler {self._id}: {ex}")
|
|
238
|
+
raise ex
|
|
239
|
+
|
|
240
|
+
return token_response
|
|
@@ -20,6 +20,7 @@ from ._sign_in_state import _SignInState
|
|
|
20
20
|
from ._sign_in_response import _SignInResponse
|
|
21
21
|
from ._handlers import (
|
|
22
22
|
AgenticUserAuthorization,
|
|
23
|
+
ConnectorUserAuthorization,
|
|
23
24
|
_UserAuthorization,
|
|
24
25
|
_AuthorizationHandler,
|
|
25
26
|
)
|
|
@@ -29,6 +30,7 @@ logger = logging.getLogger(__name__)
|
|
|
29
30
|
AUTHORIZATION_TYPE_MAP = {
|
|
30
31
|
"userauthorization": _UserAuthorization,
|
|
31
32
|
"agenticuserauthorization": AgenticUserAuthorization,
|
|
33
|
+
"connectoruserauthorization": ConnectorUserAuthorization,
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
|
|
@@ -44,7 +46,7 @@ class Authorization:
|
|
|
44
46
|
storage: Storage,
|
|
45
47
|
connection_manager: Connections,
|
|
46
48
|
auth_handlers: Optional[dict[str, AuthHandler]] = None,
|
|
47
|
-
|
|
49
|
+
auto_sign_in: bool = False,
|
|
48
50
|
use_cache: bool = False,
|
|
49
51
|
**kwargs,
|
|
50
52
|
):
|
|
@@ -77,21 +79,26 @@ class Authorization:
|
|
|
77
79
|
|
|
78
80
|
self._handlers = {}
|
|
79
81
|
|
|
82
|
+
auth_configuration: dict = kwargs.get("AGENTAPPLICATION", {}).get(
|
|
83
|
+
"USERAUTHORIZATION", {}
|
|
84
|
+
)
|
|
80
85
|
if not auth_handlers:
|
|
81
86
|
# get from config
|
|
82
|
-
auth_configuration: dict = kwargs.get("AGENTAPPLICATION", {}).get(
|
|
83
|
-
"USERAUTHORIZATION", {}
|
|
84
|
-
)
|
|
85
87
|
handlers_config: dict[str, dict] = auth_configuration.get("HANDLERS")
|
|
86
88
|
if not auth_handlers and handlers_config:
|
|
87
89
|
auth_handlers = {
|
|
88
90
|
handler_name: AuthHandler(
|
|
89
|
-
name=handler_name,
|
|
91
|
+
name=handler_name,
|
|
92
|
+
auth_type=config.get("TYPE", None),
|
|
93
|
+
**config.get("SETTINGS", {}),
|
|
90
94
|
)
|
|
91
95
|
for handler_name, config in handlers_config.items()
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
self._handler_settings = auth_handlers
|
|
99
|
+
self._auto_sign_in = auto_sign_in or bool(
|
|
100
|
+
auth_configuration.get("AUTO_SIGN_IN", False)
|
|
101
|
+
)
|
|
95
102
|
|
|
96
103
|
# operations default to the first handler if none specified
|
|
97
104
|
if self._handler_settings:
|
|
@@ -296,13 +303,16 @@ class Authorization:
|
|
|
296
303
|
"""
|
|
297
304
|
sign_in_state = await self._load_sign_in_state(context)
|
|
298
305
|
|
|
299
|
-
if sign_in_state:
|
|
300
|
-
auth_handler_id = sign_in_state.active_handler_id
|
|
301
|
-
if auth_handler_id:
|
|
306
|
+
if sign_in_state or self._auto_sign_in:
|
|
307
|
+
auth_handler_id = sign_in_state.active_handler_id if sign_in_state else None
|
|
308
|
+
if auth_handler_id or self._auto_sign_in:
|
|
302
309
|
sign_in_response = await self._start_or_continue_sign_in(
|
|
303
310
|
context, state, auth_handler_id
|
|
304
311
|
)
|
|
305
312
|
if sign_in_response.tag == _FlowStateTag.COMPLETE:
|
|
313
|
+
if not sign_in_state:
|
|
314
|
+
# flow just completed, no continuation activity
|
|
315
|
+
return False, None
|
|
306
316
|
assert sign_in_state.continuation_activity is not None
|
|
307
317
|
continuation_activity = (
|
|
308
318
|
sign_in_state.continuation_activity.model_copy()
|
|
@@ -33,16 +33,20 @@ class AccessTokenProviderBase(Protocol):
|
|
|
33
33
|
raise NotImplementedError()
|
|
34
34
|
|
|
35
35
|
async def get_agentic_application_token(
|
|
36
|
-
self, agent_app_instance_id: str
|
|
36
|
+
self, tenant_id: str, agent_app_instance_id: str
|
|
37
37
|
) -> Optional[str]:
|
|
38
38
|
raise NotImplementedError()
|
|
39
39
|
|
|
40
40
|
async def get_agentic_instance_token(
|
|
41
|
-
self, agent_app_instance_id: str
|
|
41
|
+
self, tenant_id: str, agent_app_instance_id: str
|
|
42
42
|
) -> tuple[str, str]:
|
|
43
43
|
raise NotImplementedError()
|
|
44
44
|
|
|
45
45
|
async def get_agentic_user_token(
|
|
46
|
-
self,
|
|
46
|
+
self,
|
|
47
|
+
tenant_id: str,
|
|
48
|
+
agent_app_instance_id: str,
|
|
49
|
+
agentic_user_id: str,
|
|
50
|
+
scopes: list[str],
|
|
47
51
|
) -> Optional[str]:
|
|
48
52
|
raise NotImplementedError()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
2
|
# Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
+
from __future__ import annotations
|
|
4
5
|
from typing import Optional
|
|
5
6
|
|
|
6
7
|
from microsoft_agents.hosting.core.authorization.auth_types import AuthTypes
|
|
@@ -32,6 +33,16 @@ class AgentAuthConfiguration:
|
|
|
32
33
|
SCOPES: Optional[list[str]]
|
|
33
34
|
AUTHORITY: Optional[str]
|
|
34
35
|
ALT_BLUEPRINT_ID: Optional[str]
|
|
36
|
+
ANONYMOUS_ALLOWED: bool = False
|
|
37
|
+
|
|
38
|
+
# Multi-connection support: Maintains a map of all configured connections
|
|
39
|
+
# to enable JWT validation across connections. This allows tokens issued
|
|
40
|
+
# for any configured connection to be validated, supporting multi-tenant
|
|
41
|
+
# scenarios where connections share a security boundary.
|
|
42
|
+
#
|
|
43
|
+
# Note: This is an internal implementation detail. External code should
|
|
44
|
+
# not directly access _connections.
|
|
45
|
+
_connections: dict[str, AgentAuthConfiguration]
|
|
35
46
|
|
|
36
47
|
def __init__(
|
|
37
48
|
self,
|
|
@@ -44,6 +55,7 @@ class AgentAuthConfiguration:
|
|
|
44
55
|
connection_name: Optional[str] = None,
|
|
45
56
|
authority: Optional[str] = None,
|
|
46
57
|
scopes: Optional[list[str]] = None,
|
|
58
|
+
anonymous_allowed: bool = False,
|
|
47
59
|
**kwargs: Optional[dict[str, str]],
|
|
48
60
|
):
|
|
49
61
|
|
|
@@ -57,6 +69,12 @@ class AgentAuthConfiguration:
|
|
|
57
69
|
self.CONNECTION_NAME = connection_name or kwargs.get("CONNECTIONNAME", None)
|
|
58
70
|
self.SCOPES = scopes or kwargs.get("SCOPES", None)
|
|
59
71
|
self.ALT_BLUEPRINT_ID = kwargs.get("ALT_BLUEPRINT_NAME", None)
|
|
72
|
+
self.ANONYMOUS_ALLOWED = anonymous_allowed or kwargs.get(
|
|
73
|
+
"ANONYMOUS_ALLOWED", False
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# JWT-patch: always at least include self for backward compat
|
|
77
|
+
self._connections = {str(self.CONNECTION_NAME): self}
|
|
60
78
|
|
|
61
79
|
@property
|
|
62
80
|
def ISSUERS(self) -> list[str]:
|
|
@@ -68,3 +86,14 @@ class AgentAuthConfiguration:
|
|
|
68
86
|
f"https://sts.windows.net/{self.TENANT_ID}/",
|
|
69
87
|
f"https://login.microsoftonline.com/{self.TENANT_ID}/v2.0",
|
|
70
88
|
]
|
|
89
|
+
|
|
90
|
+
def _jwt_patch_is_valid_aud(self, aud: str) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
JWT-patch: Checks if the given audience is valid for any of the connections.
|
|
93
|
+
"""
|
|
94
|
+
for conn in self._connections.values():
|
|
95
|
+
if not conn.CLIENT_ID:
|
|
96
|
+
continue
|
|
97
|
+
if aud.lower() == conn.CLIENT_ID.lower():
|
|
98
|
+
return True
|
|
99
|
+
return False
|
|
@@ -23,16 +23,20 @@ class AnonymousTokenProvider(AccessTokenProviderBase):
|
|
|
23
23
|
return ""
|
|
24
24
|
|
|
25
25
|
async def get_agentic_application_token(
|
|
26
|
-
self, agent_app_instance_id: str
|
|
26
|
+
self, tenant_id: str, agent_app_instance_id: str
|
|
27
27
|
) -> Optional[str]:
|
|
28
28
|
return ""
|
|
29
29
|
|
|
30
30
|
async def get_agentic_instance_token(
|
|
31
|
-
self, agent_app_instance_id: str
|
|
31
|
+
self, tenant_id: str, agent_app_instance_id: str
|
|
32
32
|
) -> tuple[str, str]:
|
|
33
33
|
return "", ""
|
|
34
34
|
|
|
35
35
|
async def get_agentic_user_token(
|
|
36
|
-
self,
|
|
36
|
+
self,
|
|
37
|
+
tenant_id: str,
|
|
38
|
+
agent_app_instance_id: str,
|
|
39
|
+
agentic_user_id: str,
|
|
40
|
+
scopes: list[str],
|
|
37
41
|
) -> Optional[str]:
|
|
38
42
|
return ""
|
|
@@ -11,10 +11,12 @@ class ClaimsIdentity:
|
|
|
11
11
|
claims: dict[str, str],
|
|
12
12
|
is_authenticated: bool,
|
|
13
13
|
authentication_type: Optional[str] = None,
|
|
14
|
+
security_token: Optional[str] = None,
|
|
14
15
|
):
|
|
15
16
|
self.claims = claims
|
|
16
17
|
self.is_authenticated = is_authenticated
|
|
17
18
|
self.authentication_type = authentication_type
|
|
19
|
+
self.security_token = security_token
|
|
18
20
|
|
|
19
21
|
def get_claim_value(self, claim_type: str) -> Optional[str]:
|
|
20
22
|
return self.claims.get(claim_type)
|
|
@@ -83,3 +85,17 @@ class ClaimsIdentity:
|
|
|
83
85
|
if self.is_agent_claim()
|
|
84
86
|
else AuthenticationConstants.AGENTS_SDK_SCOPE
|
|
85
87
|
)
|
|
88
|
+
|
|
89
|
+
def get_token_scope(self) -> list[str]:
|
|
90
|
+
"""
|
|
91
|
+
Gets the token scope from current claims.
|
|
92
|
+
|
|
93
|
+
:return: The token scope.
|
|
94
|
+
"""
|
|
95
|
+
return [
|
|
96
|
+
(
|
|
97
|
+
f"{self.get_outgoing_app_id()}/.default"
|
|
98
|
+
if self.is_agent_claim()
|
|
99
|
+
else AuthenticationConstants.AGENTS_SDK_SCOPE + "/.default"
|
|
100
|
+
)
|
|
101
|
+
]
|
|
@@ -28,13 +28,13 @@ class JwtTokenValidator:
|
|
|
28
28
|
leeway=300.0,
|
|
29
29
|
options={"verify_aud": False},
|
|
30
30
|
)
|
|
31
|
-
if decoded_token["aud"]
|
|
31
|
+
if not self.configuration._jwt_patch_is_valid_aud(decoded_token["aud"]):
|
|
32
32
|
logger.error(f"Invalid audience: {decoded_token['aud']}", stack_info=True)
|
|
33
33
|
raise ValueError("Invalid audience.")
|
|
34
34
|
|
|
35
35
|
# This probably should return a ClaimsIdentity
|
|
36
36
|
logger.debug("JWT token validated successfully.")
|
|
37
|
-
return ClaimsIdentity(decoded_token, True)
|
|
37
|
+
return ClaimsIdentity(decoded_token, True, security_token=token)
|
|
38
38
|
|
|
39
39
|
def get_anonymous_claims(self) -> ClaimsIdentity:
|
|
40
40
|
logger.debug("Returning anonymous claims identity.")
|
|
@@ -381,16 +381,14 @@ class ChannelServiceAdapter(ChannelAdapter, ABC):
|
|
|
381
381
|
If the task completes successfully, then an :class:`microsoft_agents.activity.InvokeResponse` is returned;
|
|
382
382
|
otherwise, `None` is returned.
|
|
383
383
|
"""
|
|
384
|
-
scopes: list[str] =
|
|
384
|
+
scopes: list[str] = claims_identity.get_token_scope()
|
|
385
385
|
outgoing_audience: str = None
|
|
386
386
|
|
|
387
387
|
if claims_identity.is_agent_claim():
|
|
388
388
|
outgoing_audience = claims_identity.get_token_audience()
|
|
389
|
-
scopes = [f"{claims_identity.get_outgoing_app_id()}/.default"]
|
|
390
389
|
activity.caller_id = f"{CallerIdConstants.agent_to_agent_prefix}{claims_identity.get_outgoing_app_id()}"
|
|
391
390
|
else:
|
|
392
391
|
outgoing_audience = AuthenticationConstants.AGENTS_SDK_SCOPE
|
|
393
|
-
scopes = [f"{AuthenticationConstants.AGENTS_SDK_SCOPE}/.default"]
|
|
394
392
|
|
|
395
393
|
use_anonymous_auth_callback = False
|
|
396
394
|
if (
|
|
@@ -9,11 +9,15 @@ from .client.user_token_client import UserTokenClient
|
|
|
9
9
|
# Teams API
|
|
10
10
|
from .teams.teams_connector_client import TeamsConnectorClient
|
|
11
11
|
|
|
12
|
+
# MCS API
|
|
13
|
+
from .mcs.mcs_connector_client import MCSConnectorClient
|
|
14
|
+
|
|
12
15
|
__all__ = [
|
|
13
16
|
"ConnectorClient",
|
|
14
17
|
"UserTokenClient",
|
|
15
18
|
"UserTokenClientBase",
|
|
16
19
|
"TeamsConnectorClient",
|
|
20
|
+
"MCSConnectorClient",
|
|
17
21
|
"ConnectorClientBase",
|
|
18
22
|
"get_product_info",
|
|
19
23
|
]
|