10000 Auth flow and ENV pattern for all samples (#21) · microsoft/Agents-for-python@017b14f · GitHub
[go: up one dir, main page]

Skip to content

Commit 017b14f

Browse files
authored
Auth flow and ENV pattern for all samples (#21)
* Auth flow and ENV pattern for all samples * Auth flow and ENV pattern for all samples - Formatting
1 parent 74825e8 commit 017b14f

File tree

12 files changed

+73
-28
lines changed

12 files changed

+73
-28
lines changed

libraries/Builder/microsoft-agents-builder/microsoft/agents/builder/channel_service_adapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ async def process_activity(
333333
use_anonymous_auth_callback = False
334334
if (
335335
not claims_identity.is_authenticated
336-
and activity.channel_id == Channels.emulator
336+
and claims_identity.authentication_type == "Anonymous"
337337
):
338338
use_anonymous_auth_callback = True
339339

libraries/Builder/microsoft-agents-builder/microsoft/agents/builder/rest_channel_service_client_factory.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from microsoft.agents.authorization import (
44
AuthenticationConstants,
5+
AnonymousTokenProvider,
56
ClaimsIdentity,
67
Connections,
78
)
@@ -15,6 +16,8 @@
1516

1617

1718
class RestChannelServiceClientFactory(ChannelServiceClientFactoryBase):
19+
_ANONYMOUS_TOKEN_PROVIDER = AnonymousTokenProvider()
20+
1821
def __init__(
1922
self,
2023
configuration: Any,
@@ -43,22 +46,31 @@ async def create_connector_client(
4346
"RestChannelServiceClientFactory.create_connector_client: audience can't be None or Empty"
4447
)
4548

49+
token_provider = (
50+
self._connections.get_token_provider(claims_identity, service_url)
51+
if not use_anonymous
52+
else self._ANONYMOUS_TOKEN_PROVIDER
53+
)
54+
4655
return ConnectorClient(
4756
endpoint=service_url,
48-
credential_token_provider=self._connections.get_token_provider(
49-
claims_identity, service_url
50-
),
57+
credential_token_provider=token_provider,
5158
credential_resource_url=audience,
5259
credential_scopes=scopes,
5360
)
5461

5562
async def create_user_token_client(
5663
self, claims_identity: ClaimsIdentity, use_anonymous: bool = False
5764
) -> UserTokenClient:
58-
return UserTokenClient(
59-
credential_token_provider=self._connections.get_token_provider(
65+
token_provider = (
66+
self._connections.get_token_provider(
6067
claims_identity, self._token_service_endpoint
61-
),
68+
)
69+
if not use_anonymous
70+
else self._ANONYMOUS_TOKEN_PROVIDER
71+
)
72+
return UserTokenClient(
73+
credential_token_provider=token_provider,
6274
credential_resource_url=self._token_service_audience,
6375
credential_scopes=[f"{self._token_service_audience}/.default"],
6476
endpoint=self._token_service_endpoint,

libraries/Core/microsoft-agents-authorization/microsoft/agents/authorization/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .access_token_provider_base import AccessTokenProviderBase
22
from .authentication_constants import AuthenticationConstants
3+
from .anonymous_token_provider import AnonymousTokenProvider
34
from .connections import Connections
45
from .agent_auth_configuration import AgentAuthConfiguration
56
from .claims_identity import ClaimsIdentity
@@ -8,6 +9,7 @@
89
__all__ = [
910
"AccessTokenProviderBase",
1011
"AuthenticationConstants",
12+
"AnonymousTokenProvider",
1113
"Connections",
1214
"AgentAuthConfiguration",
1315
"ClaimsIdentity",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from .access_token_provider_base import AccessTokenProviderBase
2+
3+
4+
class AnonymousTokenProvider(AccessTokenProviderBase):
5+
"""
6+
A class that provides an anonymous token for authentication.
7+
This is used when no authentication is required.
8+
"""
9+
10+
async def get_access_token(
11+
self, resource_url: str, scopes: list[str], force_refresh: bool = False
12+
) -> str:
13+
return ""

libraries/Core/microsoft-agents-authorization/microsoft/agents/authorization/jwt_token_validator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ def validate_token(self, token: str) -> ClaimsIdentity:
2525
# This probably should return a ClaimsIdentity
2626
return ClaimsIdentity(decoded_token, True)
2727

28+
def get_anonymous_claims(self) -> ClaimsIdentity:
29+
return ClaimsIdentity({}, False, authentication_type="Anonymous")
30+
2831
def _get_public_key_or_secret(self, token: str) -> PyJWK:
2932
header = get_unverified_header(token)
3033
unverified_payload: dict = decode(token, options={"verify_signature": False})

libraries/Hosting/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/jwt_authorization_middleware.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ async def jwt_authorization_middleware(request: Request, handler):
1717
except ValueError as e:
1818
return json_response({"error": str(e)}, status=401)
1919
else:
20-
if (not auth_config.CLIENT_ID) and (request.app["env"] == "DEV"):
21-
# TODO: Define anonymous strategy
22-
request["user"] = {"name": "anonymous"}
20+
if not auth_config.CLIENT_ID:
21+
# TODO: Refine anonymous strategy
22+
request["claims_identity"] = token_validator.get_anonymous_claims()
2323
else:
2424
return json_response(
2525
{"error": "Authorization header not found"}, status=401

test_samples/agent_to_agent/agent_1/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Licensed under the MIT License.
33

44
from aiohttp.web import Application, Request, Response, run_app
5+
from dotenv import load_dotenv
56

67
from microsoft.agents.builder import RestChannelServiceClientFactory
78
from microsoft.agents.hosting.aiohttp import (
@@ -25,6 +26,8 @@
2526
from agent1 import Agent1
2627
from config import DefaultConfig
2728

29+
load_dotenv()
30+
2831
AUTH_PROVIDER = MsalAuth(DefaultConfig())
2932

3033

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from os import environ
12
from microsoft.agents.authentication.msal import AuthTypes, MsalAuthConfiguration
23
from microsoft.agents.client import (
34
ChannelHostConfiguration,
@@ -9,12 +10,13 @@
910
class DefaultConfig(MsalAuthConfiguration, ChannelsConfiguration):
1011
"""Agent Configuration"""
1112

12-
AUTH_TYPE = AuthTypes.client_secret
13-
TENANT_ID = ""
14-
CLIENT_ID = ""
15-
CLIENT_SECRET = ""
16-
PORT = 3978
17-
SCOPES = ["https://api.botframework.com/.default"]
13+
def __init__(self) -> None:
14+
self.AUTH_TYPE = AuthTypes.client_secret
15+
self.TENANT_ID = "" or environ.get("TENANT_ID")
16+
self.CLIENT_ID = "" or environ.get("CLIENT_ID")
17+
self.CLIENT_SECRET = "" or environ.get("CLIENT_SECRET")
18+< F438 div class="diff-text-inner"> self.PORT = 3978
19+
self.SCOPES = ["https://api.botframework.com/.default"]
1820

1921
# ChannelHost configuration
2022
@staticmethod
@@ -23,13 +25,13 @@ def CHANNEL_HOST_CONFIGURATION():
2325
CHANNELS=[
2426
ChannelInfo(
2527
id="EchoAgent",
26-
app_id="", # Target agent's app_id
28+
app_id="" or environ.get("TARGET_APP_ID"), # Target agent's app_id
2729
resource_url="http://localhost:3999/api/messages",
2830
token_provider="ChannelConnection",
2931
channel_factory="HttpAgentClient",
3032
endpoint="http://localhost:3999/api/messages",
3133
)
3234
],
3335
HOST_ENDPOINT="http://localhost:3978/api/botresponse/",
34-
HOST_APP_ID="", # usually the same as CLIENT_ID
36+
HOST_APP_ID="" or environ.get("CLIENT_ID"), # usually the same as CLIENT_ID
3537
)

test_samples/agent_to_agent/agent_2/app.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Licensed under the MIT License.
33

44
from aiohttp.web import Application, Request, Response, run_app
5+
from dotenv import load_dotenv
56

67
from microsoft.agents.builder import RestChannelServiceClientFactory
78
from microsoft.agents.hosting.aiohttp import CloudAdapter, jwt_authorization_middleware
@@ -15,6 +16,8 @@
1516
from agent2 import Agent2
1617
from config import DefaultConfig
1718

19+
load_dotenv()
20+
1821
AUTH_PROVIDER = MsalAuth(DefaultConfig())
1922

2023

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
from os import environ
12
from microsoft.agents.authentication.msal import AuthTypes, MsalAuthConfiguration
23

34

45
class DefaultConfig(MsalAuthConfiguration):
56
"""Agent Configuration"""
67

7-
AUTH_TYPE = AuthTypes.client_secret
8-
TENANT_ID = ""
9-
CLIENT_ID = ""
10-
CLIENT_SECRET = ""
11-
PORT = 3999
8+
def __init__(self) -> None:
9+
self.AUTH_TYPE = AuthTypes.client_secret
10+
self.TENANT_ID = "" or environ.get("TENANT_ID")
11+
self.CLIENT_ID = "" or environ.get("CLIENT_ID")
12+
self.CLIENT_SECRET = "" or environ.get("CLIENT_SECRET")
13+
self.PORT = 3999

0 commit comments

Comments
 (0)
0