microsoft / CopilotStudioSamples

MIT License
241 stars 215 forks source link

Token Acquisition Issue #199

Open Billb12 opened 2 months ago

Billb12 commented 2 months ago

What sample tool are you using? SharePoint SSO

Describe the bug When selecting the "Copilot" button to open the dialog, it more times than not won't connect because "no_tokens_found".

Console:

InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in. at t [as constructor] (pva-sso-application-customizer_ba3616945095930aee75.js:2:1106851) at new t (pva-sso-application-customizer_ba3616945095930aee75.js:2:1155775) at t.createNoTokensFoundError (pva-sso-application-customizer_ba3616945095930aee75.js:2:1156107) at t. (pva-sso-application-customizer_ba3616945095930aee75.js:2:1304441) at pva-sso-application-customizer_ba3616945095930aee75.js:2:1097921 at Object.next (pva-sso-application-customizer_ba3616945095930aee75.js:2:1098026) at pva-sso-application-customizer_ba3616945095930aee75.js:2:1096963 at new Promise () at Zs (pva-sso-application-customizer_ba3616945095930aee75.js:2:1096711) at t.acquireTokenWithCachedRefreshToken (pva-sso-application-customizer_ba3616945095930aee75.js:2:1303986)

BrowserAuthError: monitor_window_timeout: Token acquisition in iframe failed due to timeout. For more visit: aka.ms/msaljs/browser-errors.
at t [as constructor] (pva-sso-application-customizer_ba3616945095930aee75.js:2:1106851)
at new t (pva-sso-application-customizer_ba3616945095930aee75.js:2:1121634)
at t.createMonitorIframeTimeoutError (pva-sso-application-customizer_ba3616945095930aee75.js:2:1124303)
at pva-sso-application-customizer_ba3616945095930aee75.js:2:1350042

To Reproduce Steps to reproduce the behavior: Click to open dialog

Expected behavior As designed

Screenshots If applicable, add screenshots to help explain your problem.

Additional context We are in a GCC High Tenant

There are times that the dialog connects and I can interact with the bot. Sometimes when signing out of SharePoint and signing back in. But this doesn't always work.

adilei commented 2 months ago

InteractionRequiredAuthError is handled in the code by initiating a login pop-up.

Can you run this locally using "gulp serve" to see where exactly in the code the exception is being raised?

gobigfoot commented 2 months ago

Running the solution locally I'm not getting InteractionRequiredAuthError's today. Instead I'm getting the more generic BrowserAuthError: monitor_window_timeout: Token acquisition in iframe failed due to timeout. This failed multiple times in a row over the span of about an hour testing. Now the token request is successful, but will crop back up without any change to the code base.

pm38702003 commented 2 months ago

I am getting the exact error, it started 2 days ago without any changes to code or configuration. I have been unable to get the bot online again. This is only happening in the prod tenant, the test tenant seems fine:

BrowserAuthError: monitor_window_timeout: Token acquisition in iframe failed due to timeout. For more visit: aka.ms/msaljs/browser-errors. at t [as constructor] (chat-bot-web-part_e5029bb6fec13faa588c.js:2:1383703) at new t (chat-bot-web-part_e5029bb6fec13faa588c.js:2:1398486) at t.createMonitorIframeTimeoutError (chat-bot-web-part_e5029bb6fec13faa588c.js:2:1401155) at chat-bot-web-part_e5029bb6fec13faa588c.js:2:1626926

both MSALWrapper.handleLoggedInUser and MSALWrapper.acquireAccessToken return null

image

image

adilei commented 2 months ago

It's possible that what everyone is seeing is due to IDP (Entra ID) throttling. I'm not sure how to test this on the IDP side, but I can look into this.

Maybe a way around this would be changing the design to we don't ask for a token each time the dialog is loaded. Just a direction, nothing definite right now.

I'm not getting this error, so it would help if anyone could validate it is actually IDP throttling.

EDIT: one more thing - handleLoggedInUser isn't supposed to return null if the user is already signed-in. Can you (plural) please check why is it returning null? Is it because that getAllAccounts() is coming back empty, no accounts are found for userEmail or is acquireTokenSilent failing?

pm38702003 commented 2 months ago

in my case the getAllAccounts() is coming back empty

pm38702003 commented 2 months ago

This is what I am seeing.. I have converted this to a WebPart when the WebPart is deployed on the homepage https://site/home and https://site/home is in the redirect URL collection everything works. However. if I use the WebPart from https://site/home/page.aspx without first going to https://site/home and using the WebPart the account comes back as null. It looks like I need to register the entire URL in the redirect URL in order to get this to work like I want. I was working under the impression that https://site/home/ would cover everything under that path

gobigfoot commented 2 months ago

It's possible that what everyone is seeing is due to IDP (Entra ID) throttling. I'm not sure how to test this on the IDP side, but I can look into this.

Maybe a way around this would be changing the design to we don't ask for a token each time the dialog is loaded. Just a direction, nothing definite right now.

I'm not getting this error, so it would help if anyone could validate it is actually IDP throttling.

EDIT: one more thing - handleLoggedInUser isn't supposed to return null if the user is already signed-in. Can you (plural) please check why is it returning null? Is it because that getAllAccounts() is coming back empty, no accounts are found for userEmail or is acquireTokenSilent failing?

getAllAccounts returns as expected. [{ homeAccountId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", environment: "login.microsoftonline.us", tenantId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", username: "xxxxxxx@xxxxxx.com", localAccountId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", name: "Xxxxxxxx, Xxxxxx", idTokenClaims: undefined, nativeAccountId: undefined, }]

adilei commented 2 months ago

This is what I am seeing.. I have converted this to a WebPart when the WebPart is deployed on the homepage https://site/home and https://site/home is in the redirect URL collection everything works. However. if I use the WebPart from https://site/home/page.aspx without first going to https://site/home and using the WebPart the account comes back as null. It looks like I need to register the entire URL in the redirect URL in order to get this to work like I want. I was working under the impression that https://site/home/ would cover everything under that path

Yes, that makes sense, Redirect URIs are absolute. It is possible to define wildcard URIs, but we advise against it. See here: https://learn.microsoft.com/en-us/entra/identity-platform/reply-url#restrictions-on-wildcards-in-redirect-uris

adilei commented 2 months ago

It's possible that what everyone is seeing is due to IDP (Entra ID) throttling. I'm not sure how to test this on the IDP side, but I can look into this. Maybe a way around this would be changing the design to we don't ask for a token each time the dialog is loaded. Just a direction, nothing definite right now. I'm not getting this error, so it would help if anyone could validate it is actually IDP throttling. EDIT: one more thing - handleLoggedInUser isn't supposed to return null if the user is already signed-in. Can you (plural) please check why is it returning null? Is it because that getAllAccounts() is coming back empty, no accounts are found for userEmail or is acquireTokenSilent failing?

getAllAccounts returns as expected. [{ homeAccountId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", environment: "login.microsoftonline.us", tenantId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", username: "xxxxxxx@xxxxxx.com", localAccountId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", name: "Xxxxxxxx, Xxxxxx", idTokenClaims: undefined, nativeAccountId: undefined, }]

Great, thanks. Is username the same as userEmail that's being passed?

If the answer to that is yes, then the code will try to execute this block:


const accessTokenRequest = {
            scopes: scopes,
            account: userAccount
          };

          return this.msalInstance.acquireTokenSilent(accessTokenRequest).then((response) => {            
            return response;
          }).catch((errorinternal) => {  
            console.log(errorinternal);  
            return null;
          });