microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OAuthPrompt with Oauth2 Generic Provider not using refreshed token

jdcsanchez opened this issue · comments

Github issues should be used for bugs and feature requests. Use Stack Overflow for general "how-to" questions.

Version

What package version of the SDK are you using.
"botbuilder-core": "~4.15.0",
"botbuilder": "~4.15.0",
"botbuilder-azure": "^4.15.0",
"botbuilder-dialogs": "~4.15.0",

Describe the bug

I'm working on a Teams bot that uses a custom OAuth identity provider (my employer's) and am using it in an "Oauth2 Generic Provider" OAuth config in the Bot's configuration page.

I have the bot setup to use use stepContext.beginDialog(OAUTH_PROMPT_ID) on every message because I need a JWT token on every message to call an external REST API. From what I've read in Microsoft's documentation, the OAuthPrompt dialog flow should automatically handle refreshing the token, and that bot developers should avoid persisting the token in the bot state.

The OAuthPrompt works as expected in the initial login (i.e. no token is currently present, so it prompts the user to login; after successfully logging in, a token is received in the bot), but in succeeding messages (sent just seconds after the initial login, so the token is still valid), the bot still prompts the user to login, suggesting that it failed to refresh the token.

Taking a look at our OAuth server, I saw that right after the second message was sent, there were three back-to-back-to-back refresh_token requests sent to it that correspond with the Refresh Body Template field in the OAuth config I set, so I can confirm that the OAuth server was able to receive requests to refresh the token, and was also able to respond with a new, valid token on each of those 3 requests. Despite the server sending valid tokens, the bot still prompts the user to login again. This effectively means that the user is made to login on every message.

The OAuth server responds with a JSON object in the following structure:

{
  "access_token":"{Removed for security}",
  "token_type":"Bearer",
  "expires_in":15
}

I've also tried to create a simple Identity Provider Proxy service to add a "refresh_token" to the response object (just the same refresh_token that was sent to the service), but that also did not solve the problem. Three requests are still sent to the proxy service, and the bot then prompts the user to login.

Is there some sort of data structure that refresh token responses should adhere to for them to be considered successfully refreshed by the OAuthPrompt? Or should I be persisting the initial token in the bot state like how this answer suggests, despite being contradictory to Microsoft's documentation?

Expected behavior

Expecting the bot to not prompt the user to login after a successful refresh_token response was sent.

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

Tracking Status

Dotnet SDK TODO

  • PR
  • Merged

Javascript SDK TODO

  • PR
  • Merged

Python SDK TODO

  • PR
  • Merged

Java SDK TODO

  • PR
  • Merged

Samples TODO

  • PR
  • Merged

Docs TODO

  • PR
  • Merged

Tools TODO

  • PR
  • Merged

I am investigating this. Thank you for your patience.

Hi @jdcsanchez

Apologies for the delay. I wasn't able to reproduce the same issue.

but in succeeding messages (sent just seconds after the initial login, so the token is still valid), the bot still prompts the user to login, suggesting that it failed to refresh the token.

  • Is the above something you can share in a reproduction/sample bot?
  • Does it only happen via Teams, or does it repro in Emulator/webchat as well?

Hi @dmvtech - I believe I've found the problem. Our OAuth implementation returns the expires_in value in units of minutes, while most OAuth2 standards have it default to seconds. We have ours defaulting to 15 minutes (expires_in: 15 in the initial issue description), which is interpreted as 15 seconds when it is received by the bot, essentially expiring it right away. Re-calculating the expires_in to use seconds solves this problem.

@jdcsanchez which IdP were you using when you first faced the problem? I'm having the same problem as you described.