def test_constructor(): should_default_to_channel_scope = AppCredentials() assert (should_default_to_channel_scope.oauth_scope == AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE) should_default_to_custom_scope = AppCredentials(oauth_scope="customScope") assert should_default_to_custom_scope.oauth_scope == "customScope"
async def callback(context: TurnContext): TestBotFrameworkAdapter.get_creds_and_assert_values( context, skill_1_app_id, skill_2_app_id, 1, ) TestBotFrameworkAdapter.get_client_and_assert_values( context, skill_1_app_id, skill_2_app_id, skill_2_service_url, 1, ) # pylint: disable=protected-access client_cache = context.adapter._connector_client_cache client = client_cache.get( BotFrameworkAdapter.key_for_connector_client( skill_2_service_url, skill_1_app_id, skill_2_app_id, ) ) assert client turn_state_client = context.turn_state.get( BotFrameworkAdapter.BOT_CONNECTOR_CLIENT_KEY ) assert turn_state_client client_creds = turn_state_client.config.credentials assert skill_1_app_id == client_creds.microsoft_app_id assert skill_2_app_id == client_creds.oauth_scope assert client.config.base_url == turn_state_client.config.base_url scope = context.turn_state[BotFrameworkAdapter.BOT_OAUTH_SCOPE_KEY] assert skill_2_app_id == scope # Ensure the serviceUrl was added to the trusted hosts assert AppCredentials.is_trusted_service(skill_2_service_url)
async def test_channel_msa_header_valid_service_url_should_be_trusted( self): activity = Activity( service_url="https://smba.trafficmanager.net/amer-client-ss.msg/") header = ( "Bearer " + MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F").get_access_token()) credentials = SimpleCredentialProvider( "2cd87869-38a0-4182-9251-d056e8f0ac24", "") await JwtTokenValidation.authenticate_request(activity, header, credentials) assert AppCredentials.is_trusted_service( "https://smba.trafficmanager.net/amer-client-ss.msg/")
def test_should_not_send_token_for_anonymous(): # AppID is None app_creds_none = AppCredentials(app_id=None) assert app_creds_none.signed_session().headers.get( "Authorization") is None # AppID is anonymous skill app_creds_anon = AppCredentials( app_id=AuthenticationConstants.ANONYMOUS_SKILL_APP_ID) assert app_creds_anon.signed_session().headers.get( "Authorization") is None
async def test_continue_conversation_with_audience(self): mock_credential_provider = unittest.mock.create_autospec(CredentialProvider) settings = BotFrameworkAdapterSettings( app_id="bot_id", credential_provider=mock_credential_provider ) adapter = BotFrameworkAdapter(settings) skill_1_app_id = "00000000-0000-0000-0000-000000skill1" skill_2_app_id = "00000000-0000-0000-0000-000000skill2" skills_identity = ClaimsIdentity( claims={ AuthenticationConstants.AUDIENCE_CLAIM: skill_1_app_id, AuthenticationConstants.APP_ID_CLAIM: skill_2_app_id, AuthenticationConstants.VERSION_CLAIM: "1.0", }, is_authenticated=True, ) skill_2_service_url = "https://skill2.com/api/skills/" async def callback(context: TurnContext): TestBotFrameworkAdapter.get_creds_and_assert_values( context, skill_1_app_id, skill_2_app_id, 1, ) TestBotFrameworkAdapter.get_client_and_assert_values( context, skill_1_app_id, skill_2_app_id, skill_2_service_url, 1, ) # pylint: disable=protected-access client_cache = context.adapter._connector_client_cache client = client_cache.get( BotFrameworkAdapter.key_for_connector_client( skill_2_service_url, skill_1_app_id, skill_2_app_id, ) ) assert client turn_state_client = context.turn_state.get( BotFrameworkAdapter.BOT_CONNECTOR_CLIENT_KEY ) assert turn_state_client client_creds = turn_state_client.config.credentials assert skill_1_app_id == client_creds.microsoft_app_id assert skill_2_app_id == client_creds.oauth_scope assert client.config.base_url == turn_state_client.config.base_url scope = context.turn_state[BotFrameworkAdapter.BOT_OAUTH_SCOPE_KEY] assert skill_2_app_id == scope # Ensure the serviceUrl was added to the trusted hosts assert AppCredentials.is_trusted_service(skill_2_service_url) refs = ConversationReference(service_url=skill_2_service_url) # Ensure the serviceUrl is NOT in the trusted hosts assert not AppCredentials.is_trusted_service(skill_2_service_url) await adapter.continue_conversation( refs, callback, claims_identity=skills_identity, audience=skill_2_app_id )
async def continue_conversation( self, reference: ConversationReference, callback: Callable, bot_id: str = None, claims_identity: ClaimsIdentity = None, audience: str = None, ): """ Continues a conversation with a user. :param reference: A reference to the conversation to continue :type reference: :class:`botbuilder.schema.ConversationReference :param callback: The method to call for the resulting bot turn :type callback: :class:`typing.Callable` :param bot_id: The application Id of the bot. This is the appId returned by the Azure portal registration, and is generally found in the `MicrosoftAppId` parameter in `config.py`. :type bot_id: :class:`typing.str` :param claims_identity: The bot claims identity :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity` :param audience: :type audience: :class:`typing.str` :raises: It raises an argument null exception. :return: A task that represents the work queued to execute. .. remarks:: This is often referred to as the bots *proactive messaging* flow as it lets the bot proactively send messages to a conversation or user that are already in a communication. Scenarios such as sending notifications or coupons to a user are enabled by this function. """ if not reference: raise TypeError( "Expected reference: ConversationReference but got None instead" ) if not callback: raise TypeError("Expected callback: Callable but got None instead") # This has to have either a bot_id, in which case a ClaimsIdentity will be created, or # a ClaimsIdentity. In either case, if an audience isn't supplied one will be created. if not (bot_id or claims_identity): raise TypeError("Expected bot_id or claims_identity") if bot_id and not claims_identity: claims_identity = ClaimsIdentity( claims={ AuthenticationConstants.AUDIENCE_CLAIM: bot_id, AuthenticationConstants.APP_ID_CLAIM: bot_id, }, is_authenticated=True, ) if not audience: audience = self.__get_botframework_oauth_scope() context = TurnContext(self, get_continuation_activity(reference)) context.turn_state[BotAdapter.BOT_IDENTITY_KEY] = claims_identity context.turn_state[BotAdapter.BOT_CALLBACK_HANDLER_KEY] = callback context.turn_state[BotAdapter.BOT_OAUTH_SCOPE_KEY] = audience # Add the channel service URL to the trusted services list so we can send messages back. # the service URL for skills is trusted because it is applied by the SkillHandler based # on the original request received by the root bot AppCredentials.trust_service_url(reference.service_url) client = await self.create_connector_client(reference.service_url, claims_identity, audience) context.turn_state[BotAdapter.BOT_CONNECTOR_CLIENT_KEY] = client return await self.run_pipeline(context, callback)