Beispiel #1
0
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/")
Beispiel #4
0
    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
        )
Beispiel #6
0
    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)