microsoft / BotFramework-Services

Microsoft Bot Framework Services
Creative Commons Attribution 4.0 International
38 stars 11 forks source link

OAuth Sign in: Unable to let the user switch the credentials #340

Closed RamkumarManavalan closed 2 years ago

RamkumarManavalan commented 2 years ago

Details of the Bot Framework Composer version I use: Version: 2.1.1 Electron: 8.2.4 Chrome: 80.0.3987.165 NodeJS: 12.13.0 V8: 8.0.426.27-electron.0

I use the 'OAuth Login' of the composer to let the user sign in via service providers (I support Google & Microsoft for now). This works.

When the user logs out, I tried using "Sign out user" option of composer, but I kept getting the error: "signOutUser() not supported by the current adapter". So, I wrote a custom action (see below):

const adapter = new BotFrameworkAdapter({
        msAppId,
        msAppPwd
      });
adapter.signOutUser(dc.context, connectionName, userId)

The above executes without any error.

However, the challenge I face is I am not able to let the user switch the account next time when they want to log in. As I read from numerous blogs, issues and documents, I understand that the existing access token is sent back if it already exists. This is a nice feature because it does not let user to go through the consent prompt over and over. However, in my case, I need to give my users an option to re-login with the same account or re-login with a different account. So, I am stuck.

In case of Google, during logout, I tried revoking the access token through this API: "POST https://oauth2.googleapis.com/revoke?token=". Though this revokes the token successfully, the "OAuth Login" component of Bot composer returns the same revoked token to me back, instead of taking the user to the account selection and consent pages.

Possible solutions I would expect are:

Or is there any solution for me to let my user change the account/credentials during re-login? Please help me.

tdurnford commented 2 years ago

@dmvtech Any updates on this?

dmvtech commented 2 years ago

Hi @RamkumarManavalan I am currently investigating and will update shortly.

dmvtech commented 2 years ago

@RamkumarManavalan The sign out action should work. Can you confirm that the token property you are using in the prompt is exactly turn.token.

        {
          "$kind": "Microsoft.OAuthInput",
          "$designer": {
            "id": "IDje66"
          },
          "timeout": 900000,
          "property": "turn.token",
          "maxTurnCount": 3,
          "allowInterruptions": true,
          "connectionName": "<REMOVED>",
          "text": "Log in to <REMOVED>",
          "title": "Login"
        },

I believe the SDK requires this and it should not be changed.

image

You can assign the property (turn.token) to another property after the prompt is complete.

        {
          "$kind": "Microsoft.SetProperties",
          "$designer": {
            "id": "WW3kOX"
          },
          "assignments": [
            {
              "property": "user.oauthtoken2",
              "value": "=turn.token"
            }
          ]
        },
RamkumarManavalan commented 2 years ago

@dmvtech, It is turn.token only.

dmvtech commented 2 years ago

@RamkumarManavalan You are using the Node runtime, correct? What version of bot framework SDK are you using?

RamkumarManavalan commented 2 years ago

Yes, it is node. Please find the version details below.

Bot framework Composer Version: 2.1.1 Electron: 8.2.4 Chrome: 80.0.3987.165 NodeJS: 12.13.0 V8: 8.0.426.27-electron.0

dmvtech commented 2 years ago

Thank you. I'm able to reproduce the same error in Node runtime and am investigating further. Please be aware that the Node runtime for Composer is still in preview and there is no current ETA for general release.

RamkumarManavalan commented 2 years ago

Thank you. Until then, is there an option for me to write a custom action (node module) to accomplish the same?

RamkumarManavalan commented 2 years ago

@dmvtech , any update on this? This is causing many issues for our customers. Any quick help will be highly appreciated. Thanks.

EricDahlvang commented 2 years ago

Hi @RamkumarManavalan

Regarding the third option mentioned above:

This might be doable using the OAuth 2 Generic Provider. image

This allows for parameter templating, where you might be able to force prompt consent|login: https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-identity-providers?view=azure-bot-service-4.0&tabs=adv2%2Ca2gp#oauth-generic-providers

RamkumarManavalan commented 2 years ago

@EricDahlvang , even I am able to overcome this problem in my web application using the same consent parameter. However, my issue here is with the bot framework composer which does not support consent parameter yet.

EricDahlvang commented 2 years ago

Composer uses the OAuth Connection Name while calling the Azure Bot Service user OAuth apis. The bot service apis make the calls to the configured oauth provider. I'm suggesting it might be possible to setup the OAuth Connection so the consent parameter is sent during the login step, as part of the parameterized 'Token URL Query String Template' or 'Token Body Template' https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-identity-providers?view=azure-bot-service-4.0&tabs=adv2%2Ca2gp#oauth-generic-providers

ref with info not in the doc: https://github.com/microsoft/BotFramework-Services/issues/140#issuecomment-547670227

RamkumarManavalan commented 2 years ago

@EricDahlvang , I tried your approach and could make some progress, but I ended up getting redirected to "https://token.botframework.com/.auth/web/redirect?code=..&state=...&session_state=.." which resulted in the error below:

{ "error": { "code": "ServiceError", "message": "Missing session cookie (consent12345) in consent redirect request." } }

However, earlier when I used Microsoft instead of Oauth2 Generic Provider, I was redirected to "https://token.botframework.com/api/oauth/PostSignInCallback?signin=...&code=..." which would display the validation code to copy to clipboard.

EricDahlvang commented 2 years ago

Hi @RamkumarManavalan

Sorry, I'm not sure why that is happening. I've transferred this issue to the BotFramework-Services repository as the token service is part of Azure Bot Service. Maybe someone here will have some ideas.

xieofxie commented 2 years ago

Hi @RamkumarManavala it is advised to use Service Provider Azure Active Directory v2 for Microsoft and Google for Google.

I have verified that they worked in signin and signout scenario (after signout, user could not get token any more).

Hi @EricDahlvang, could you help to verify Composer works as what SDK does? Thanks~

EricDahlvang commented 2 years ago

Yes, Composer and SDK work similarly. What this issue is about however, is the account selection or consent popup. For AAD apps, you can go here: https://portal.office.com/account/?ref=MeControl#apps and remove consent under 'You can revoke permission for these apps' The login experience is different when consent has not been provided. As far as I know, the bot framework user auth api does not provide a parameter to always force consent. I was hoping the oauth 2 generic provider would expose these parameters and enable forcing consent every time.

RamkumarManavalan commented 2 years ago

@xieofxie , the signout user of the composer does not work as you have mentioned. Even after doing the signout, the previous token is still sent in the next login attempt.

Note: I have tried Azure AD V2, Google and Oauth2 generic provider too.

What I am really looking forward to is the below: The 'OAuth Login' option in the composer should accept "prompt" parameter, accepting the respective values ('consent' for Google and 'login' for Microsoft). Setting prompt=login or prompt=consent works from my other web applications, as intended.

xieofxie commented 2 years ago

@RamkumarManavalan For the signout, please reach out to Composer / SDK for fix. For your request, I have verified with the following configs, please test:

Microsoft: Name Value
Authorization URL Template https://login.microsoftonline.com/common/oauth2/v2.0/authorize
Authorization URL Query String Template ?client_id={ClientId}&response_type=code&scope={Scopes}&redirect_uri={RedirectUrl}&state={State}&prompt=login
Token URL Template https://login.microsoftonline.com/common/oauth2/v2.0/token
Token URL Query String Template ?
Token Body Template code={Code}&redirect_uri={RedirectUrl}&scope={Scopes}&grant_type=authorization_code&client_id={ClientId}&client_secret={ClientSecret}
Refresh URL Template https://login.microsoftonline.com/common/oauth2/v2.0/token
Refresh URL Query String Template ?
Refresh Body Template refresh_token={RefreshToken}&redirect_uri={RedirectUrl}&grant_type=refresh_token&client_id={ClientId}&client_secret={ClientSecret}
Google: Name Value
Authorization URL Template https://accounts.google.com/o/oauth2/auth
Authorization URL Query String Template ?client_id={ClientId}&response_type=code&scope={Scopes}&redirect_uri={RedirectUrl}&state={State}&access_type=offline&prompt=consent
Token URL Template https://accounts.google.com/o/oauth2/token
Token URL Query String Template ?
Token Body Template code={Code}&redirect_uri={RedirectUrl}&scope={Scopes}&grant_type=authorization_code&client_id={ClientId}&client_secret={ClientSecret}
Refresh URL Template https://accounts.google.com/o/oauth2/token
Refresh URL Query String Template ?
Refresh Body Template refresh_token={RefreshToken}&grant_type=refresh_token&client_id={ClientId}&client_secret={ClientSecret}
luhan2017 commented 2 years ago

closed since inactive for long time, please reopen if needed.