botbuilder-python icon indicating copy to clipboard operation
botbuilder-python copied to clipboard

BotBuilder-Python SSO not working

Open jamiesun opened this issue 1 year ago • 6 comments

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

jamiesun avatar Jan 05 '24 06:01 jamiesun

@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.

stevkan avatar Jan 15 '24 23:01 stevkan

@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.

jamiesun avatar Jan 21 '24 07:01 jamiesun

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

tracyboehrer avatar Feb 01 '24 20:02 tracyboehrer

Closing as resolved.

stevkan avatar May 06 '24 21:05 stevkan

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

tracyboehrer avatar May 07 '24 13:05 tracyboehrer

Regarding this issue, after some troubleshooting, significant improvements have been made. I found that the Token Exchange URL was not configured, but after setting it up, the Teams SSO authentication flow finally worked correctly, with the authentication dialog completing as expected. However, the SSO process only succeeds when the application is deployed in the same tenant as the bot. If the application is deployed in a different tenant, the SSO process fails. image

What could be missing here?

jamiesun avatar Sep 03 '24 07:09 jamiesun