Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import Dict, List, Optional
from microsoft.agents.hosting.core.authorization import (
from microsoft.agents.hosting.core import (
AgentAuthConfiguration,
AccessTokenProviderBase,
ClaimsIdentity,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import unittest
from unittest.mock import Mock
import pytest
from msal import ManagedIdentityClient, ConfidentialClientApplication
from microsoft.agents.authentication.msal import MsalAuth
from microsoft.agents.hosting.core.authorization import AgentAuthConfiguration


class TestingMsalAuth(MsalAuth):
"""
Mock object for MsalAuth
"""

def __init__(self, client_type):
super().__init__(AgentAuthConfiguration())
mock_client = Mock(spec=client_type)

mock_client.acquire_token_for_client = Mock(
return_value={"access_token": "token"}
)
mock_client.acquire_token_on_behalf_of = Mock(
return_value={"access_token": "token"}
)
self.mock_client = mock_client

self._create_client_application = Mock(return_value=self.mock_client)


class TestMsalAuth:
"""
Test suite for testing MsalAuth functionality
"""

@pytest.mark.asyncio
async def test_get_access_token_managed_identity(self):
mock_auth = TestingMsalAuth(ManagedIdentityClient)
token = await mock_auth.get_access_token(
"https://test.api.botframework.com", scopes=["test-scope"]
)

assert token == "token"
mock_auth.mock_client.acquire_token_for_client.assert_called_with(
resource="https://test.api.botframework.com"
)

@pytest.mark.asyncio
async def test_get_access_token_confidential(self):
mock_auth = TestingMsalAuth(ConfidentialClientApplication)
token = await mock_auth.get_access_token(
"https://test.api.botframework.com", scopes=["test-scope"]
)

assert token == "token"
mock_auth.mock_client.acquire_token_for_client.assert_called_with(
scopes=["test-scope"]
)

@pytest.mark.asyncio
async def test_aquire_token_on_behalf_of_managed_identity(self):
mock_auth = TestingMsalAuth(ManagedIdentityClient)

try:
await mock_auth.aquire_token_on_behalf_of(
scopes=["test-scope"], user_assertion="test-assertion"
)
except NotImplementedError:
assert True
else:
assert False

@pytest.mark.asyncio
async def test_aquire_token_on_behalf_of_confidential(self):
mock_auth = TestingMsalAuth(ConfidentialClientApplication)
mock_auth._create_client_application = Mock(return_value=mock_auth.mock_client)

token = await mock_auth.aquire_token_on_behalf_of(
scopes=["test-scope"], user_assertion="test-assertion"
)

assert token == "token"
mock_auth.mock_client.acquire_token_on_behalf_of.assert_called_with(
scopes=["test-scope"], user_assertion="test-assertion"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from os import environ
from microsoft.agents.activity import load_configuration_from_env
from microsoft.agents.hosting.core import AuthTypes
from microsoft.agents.authentication.msal import MsalConnectionManager


class TestMsalConnectionManager:
"""
Test suite for the Msal Connection Manager
"""

def test_msal_connection_manager(self):
mock_environ = {
**environ,
"CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID": "test-tenant-id-SERVICE_CONNECTION",
"CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID": "test-client-id-SERVICE_CONNECTION",
"CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET": "test-client-secret-SERVICE_CONNECTION",
"CONNECTIONS__MCS__SETTINGS__TENANTID": "test-tenant-id-MCS",
"CONNECTIONS__MCS__SETTINGS__CLIENTID": "test-client-id-MCS",
"CONNECTIONS__MCS__SETTINGS__CLIENTSECRET": "test-client-secret-MCS",
}

config = load_configuration_from_env(mock_environ)
connection_manager = MsalConnectionManager(**config)
for key in connection_manager._connections:
auth = connection_manager.get_connection(key)._msal_configuration
assert auth.AUTH_TYPE == AuthTypes.client_secret
assert auth.CLIENT_ID == f"test-client-id-{key}"
assert auth.TENANT_ID == f"test-tenant-id-{key}"
assert auth.CLIENT_SECRET == f"test-client-secret-{key}"
assert auth.ISSUERS == [
"https://api.botframework.com",
f"https://sts.windows.net/test-tenant-id-{key}/",
f"https://login.microsoftonline.com/test-tenant-id-{key}/v2.0",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from os import environ
from typing import Dict
from microsoft.agents.activity import load_configuration_from_env
from microsoft.agents.hosting.core import AgentAuthConfiguration, AuthTypes


class TestAuthorizationConfiguration:
"""
Unit tests to validate Authorization Configuration cases
"""

def test_auth_configuration_basic(self):
# test AgentAuthConfiguration with manual insertion of fields
auth_config = AgentAuthConfiguration(
auth_type=AuthTypes.client_secret,
tenant_id="test-tenant-id",
client_id="test-client-id",
client_secret="test-client-secret",
cert_pem_file="test-cert.pem",
cert_key_file="test-cert.key",
connection_name="test-connection",
authority="https://login.microsoftonline.com",
scopes=["test-scope-1", "test-scope-2"],
)

assert auth_config.AUTH_TYPE == AuthTypes.client_secret
assert auth_config.TENANT_ID == "test-tenant-id"
assert auth_config.CLIENT_ID == "test-client-id"
assert auth_config.CLIENT_SECRET == "test-client-secret"
assert auth_config.CERT_PEM_FILE == "test-cert.pem"
assert auth_config.CERT_KEY_FILE == "test-cert.key"
assert auth_config.CONNECTION_NAME == "test-connection"
assert auth_config.AUTHORITY == "https://login.microsoftonline.com"
assert auth_config.SCOPES == ["test-scope-1", "test-scope-2"]
assert auth_config.ISSUERS == [
"https://api.botframework.com",
f"https://sts.windows.net/test-tenant-id/",
f"https://login.microsoftonline.com/test-tenant-id/v2.0",
]

def test_load_configuration_from_env(self):
# test load_configuration_from_env, passed to AgentAuthConfiguration
mock_environ = {
**environ,
"CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID": "test-tenant-id-SERVICE_CONNECTION",
"CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID": "test-client-id-SERVICE_CONNECTION",
"CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET": "test-client-secret-SERVICE_CONNECTION",
"CONNECTIONS__MCS__SETTINGS__TENANTID": "test-tenant-id-MCS",
"CONNECTIONS__MCS__SETTINGS__CLIENTID": "test-client-id-MCS",
"CONNECTIONS__MCS__SETTINGS__CLIENTSECRET": "test-client-secret-MCS",
}

mock_config = load_configuration_from_env(mock_environ)

raw_configurations: Dict[str, Dict] = mock_config.get("CONNECTIONS", {})

for name, settings in raw_configurations.items():
auth_config = AgentAuthConfiguration(**settings["SETTINGS"])
assert auth_config.AUTH_TYPE == AuthTypes.client_secret
assert auth_config.CLIENT_ID == f"test-client-id-{name}"
assert auth_config.TENANT_ID == f"test-tenant-id-{name}"
assert auth_config.CLIENT_SECRET == f"test-client-secret-{name}"
assert auth_config.ISSUERS == [
"https://api.botframework.com",
f"https://sts.windows.net/test-tenant-id-{name}/",
f"https://login.microsoftonline.com/test-tenant-id-{name}/v2.0",
]

def test_empty_settings(self):
auth_config = AgentAuthConfiguration()
assert auth_config.AUTH_TYPE == AuthTypes.client_secret
assert auth_config.TENANT_ID == None
assert auth_config.CLIENT_ID == None
assert auth_config.CLIENT_SECRET == None
assert auth_config.CERT_PEM_FILE == None
assert auth_config.CERT_KEY_FILE == None
assert auth_config.CONNECTION_NAME == None
assert auth_config.AUTHORITY == None
assert auth_config.SCOPES == None
Loading