microsoft / botbuilder-python

The Microsoft Bot Framework provides what you need to build and connect intelligent bots that interact naturally wherever your users are talking, from text/sms to Skype, Slack, Office 365 mail and other popular services.
http://botframework.com
MIT License
676 stars 270 forks source link

BotBuilder-Python SSO not working #2088

Open jamiesun opened 6 months ago

jamiesun commented 6 months ago

Version

4.14.7

Describe the bug

When using the OAuthPrompt Dialog from the SDK, the call to https://api.botframework.com/api/usertoken/GetToken performed by the SDK returns a 400 status error response. According to the code, the SDK awaits either a 200 or 404 status.

Reference:

https://github.com/microsoft/botbuilder-js/issues/4418 https://github.com/microsoft/botframework-sdk/issues/5464 https://github.com/microsoft/botbuilder-dotnet/issues/4927

To Reproduce

Steps to reproduce the behavior:

  1. Run the sample code project 24.bot-authentication-msgraph
  2. Sending a message triggers the SSO process
  3. Click the login button

Expected behavior

Evoke the SSO certification process

question

It's always 404. It looks like the 404 is due to an incorrect parameter. Is something missing?

DEBUG:urllib3.connectionpool:https://api.botframework.com:443 "GET /api/usertoken/GetToken?userId=<user id value>&connectionName=<name>&channelId=msteams&api-version=token HTTP/1.1" 404 2096

I couldn't solve the problem in the end, and I wasn't as lucky as other users to have it fixed automatically, I spent a long time modifying the configuration and trying over and over again, but no luck!

I tried a different way to authenticate

    async def command_login(self, turn_context: TurnContext):
        link = await turn_context.adapter.get_oauth_sign_in_link(
            turn_context,
            self.bot.oauth_name,
        )
        card_data = get_login_card(link)
        card = CardFactory.adaptive_card(card_data)
        message = Activity(
            text="",
            type=ActivityTypes.message,
            attachments=[card],
        )
        await turn_context.send_activity(message)
image image

But when I click on the authentication button(openUrl), it opens the browser into the SSO authentication process, which ultimately returns an authentication CODE, which I need to copy and then validate it

    async def action_validation_code_submit(self, turn_context: TurnContext):
        """ValidationCodeSubmit """
        submit_data = turn_context.activity.value
        if submit_data is None:
            return

        vcode = submit_data.get("ValidationCode")
        if not vcode:
            await turn_context.send_activity("Please enter a verification code")
            return

        token = await turn_context.adapter.get_user_token(turn_context, self.bot.oauth_name, vcode)
        if not token:
            await turn_context.send_activity("The verification code is invalid")
            return

console log

DEBUG:urllib3.connectionpool:https://api.botframework.com:443 "GET /api/usertoken/GetToken?userId=<user id value>&connectionName=<name>&channelId=msteams&code=125204&api-version=token HTTP/1.1" 200 2096

Looks like more code=125204, I'd like to know how this code parameter is configured, and I'd prefer to provide a server-side callback url for the code notification. But I see that the final_redirect parameter in the SDK code is not valid.

    async def get_oauth_sign_in_link(
        self,
        context: TurnContext,
        connection_name: str,
        final_redirect: str = None,  # pylint: disable=unused-argument
        oauth_app_credentials: AppCredentials = None,
    ) -> str:
        """
        Gets the raw sign-in link to be sent to the user for sign-in for a connection name.

        :param context: Context for the current turn of conversation with the user
        :type context: :class:`botbuilder.core.TurnContext`
        :param connection_name: Name of the auth connection to use
        :type connection_name: str
        :param final_redirect: The final URL that the OAuth flow will redirect to.
        :param oauth_app_credentials: (Optional) AppCredentials for OAuth.
        :type oauth_app_credentials: :class:`botframework.connector.auth.AppCredential`

        :return: If the task completes successfully, the result contains the raw sign-in link
        """

        client = await self._create_token_api_client(context, oauth_app_credentials)

        conversation = TurnContext.get_conversation_reference(context.activity)
        state = TokenExchangeState(
            connection_name=connection_name,
            conversation=conversation,
            ms_app_id=client.config.credentials.microsoft_app_id,
            relates_to=context.activity.relates_to,
        )

        final_state = base64.b64encode(
            json.dumps(state.serialize()).encode(encoding="UTF-8", errors="strict")
        ).decode()

        return client.bot_sign_in.get_sign_in_url(final_state)

Screenshots

image

No matter how you click, it doesn't work.

Configuration Validation

This is my configuration, and the test pattern is fine.

image image image image image image
stevkan commented 5 months ago

@jamiesun - Thank you for your patience. It looks like you are using Teams as the client, yes? If you remove the SSO aspect and just focus on getting a user logged in, does it work then? I ran into some issues of my own not related to logging/OAuth that hampered me, but I have my test environment set up now. And, using the 24.bot-authentication-msgraph sample from the Botbuilder-Samples repo, I can log in using OAuth successfully whether communicating in a 1:1 or in a Teams channel with the bot .

It also looks like the scopes might be incomplete. These scopes (openid profile Mail.Read Mail.Send User.Read User.ReadBasic.All) are what are typically specified when setting up OAuth. You may want to try changing the scopes listed in the OAuth app registration and in your bot's OAuth connection settings and see if that possibly makes a difference.

jamiesun commented 5 months ago

@stevkan Thanks for your reply, I've bypassed SSO for now, and I'm able to authenticate the user to get the information. I think I need to create a new development environment and bot to verify the issue again to find out what's causing the problem.

tracyboehrer commented 5 months ago

Possible duplicate of https://github.com/microsoft/BotBuilder-Samples/issues/3829

stevkan commented 2 months ago

Closing as resolved.

tracyboehrer commented 2 months ago

I do think we have a Python SSO issue. Leaving open until we can further review the reported issues.