OfficeDev / teams-toolkit

Developer tools for building Teams apps
Other
459 stars 189 forks source link

Login too slow for getToken? #8589

Closed jke-r closed 1 year ago

jke-r commented 1 year ago

Hi TeamsFX,

I have a problem with current teamsfx package. I am using:

    "@microsoft/mgt-react": "^2.5.0",
    "@microsoft/mgt-teamsfx-provider": "^2.5.0",
    "@microsoft/microsoft-graph-client": "^3.0.1",
    "@microsoft/teams-js": "^2.6.0",
    "@microsoft/teamsfx": "^2.2.0",
    "@microsoft/teamsfx-react": "^2.1.1",

My code (snippet):

App.tsx:

const { loading, themeString, theme, teamsUserCredential } = useTeamsUserCredential({
    clientId: process.env.REACT_APP_CLIENT_ID as string,
    initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL as string,
  });

  return (
    <TeamsFxContext.Provider value={{ theme, themeString, teamsUserCredential }}>
      <Provider themeName={initTeamsTheme(themeString)} lang="en-US">
[...]
      </Provider>
    </TeamsFxContext.Provider>

Some component:

const { teamsUserCredential  } = useContext(TeamsFxContext);
[...]

Some function:

       await teamsUserCredential.login(scope);
       const token = await teamsUserCredential.getToken(scope);
[..]

My problem:

When I call the getToken function after Login, it says there is no consent given (but consent was given). We figured out that login method return before the token is cached. We have built a workaround where we call the getToken method in a loop with a delay after each call for 1.5 sec. After the 9th attempt in the loop, the token is finally returned.

My expectation is that when login method returns, the token is cached and I can call getToken immediately.

Any idea? Running a loop with a delay of 1.5 sec after each call is a workaround, but that is far away from good programming.

Thanks!

ghost commented 1 year ago

Thank you for contacting us! Any issue or feedback from you is quite important to us. We will do our best to fully respond to your issue as soon as possible. Sometimes additional investigations may be needed, we will usually get back to you within 2 days by adding comments to this issue. Please stay tuned.

SLdragon commented 1 year ago

Hi, @jke-r, did this happen when you first login to get token or it occurs every time for when visit your page?

By the way, we're using msal library to acquire token, you can find the code as below: https://github.com/OfficeDev/TeamsFx/blob/31a1a651584aa4188ab960d05ef82ffeb3737c8e/packages/sdk/src/credential/teamsUserCredential.browser.ts#LL240C50-L240C68

Maybe there are some bugs inside msal library, or it just related to AAD service delay.

Could you share the full error message so that we can identify which steps it happens, thank you!

jke-r commented 1 year ago

@SLdragon : I get the following error message: "r.UiRequiredError: Failed to get access token cache silently, please login first: you need login first before get access token."

However, if you try to receive the token in a loop, we get the error message for the first 2-3 times and then we receive the token.

Somehow there seems to be an issue with caching of the token. The async function with the code is called as an event from a button in react. Maybe we have any side effects here. We were not able to find anything unusual in the code you provided.

SLdragon commented 1 year ago

Hi, @jke-r , there are 2 steps when the code try to get token:

  1. first call await this.msalInstance!.acquireTokenSilent, this will try to get token from the local cache
  2. If there is no token cache, it will call await this.msalInstance!.ssoSilent to get token using a hidden iframe

For your problem, I think this is related to the AAD consent delay. After the first login, there is no cache for msal library, so step 1 will failed, then it will use step 2 to get token, howerver, because there is some delay of AAD consent, it may fail when you call await this.msalInstance!.ssoSilent immediately, only after 2~3 second, it would work.

You can import setLogLevel function from teamsfx sdk, changes the level as below to get the detailed error message when call ssoSilent (https://github.com/OfficeDev/TeamsFx/blob/31a1a651584aa4188ab960d05ef82ffeb3737c8e/packages/sdk/src/credential/teamsUserCredential.browser.ts#L258)

setLogLevel(LogLevel.Info);

Maybe you can add a loading animation or refresh button for your scenario.

adashen commented 1 year ago

close as the question is answered and no recent updates.