Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React MSAL - Silent SSO could not be completed, when token expired #2934

Closed
5 of 26 tasks
MarekLani opened this issue Jan 25, 2021 · 18 comments
Closed
5 of 26 tasks

React MSAL - Silent SSO could not be completed, when token expired #2934

MarekLani opened this issue Jan 25, 2021 · 18 comments
Labels
b2c Related to Azure B2C library-specific issues msal-react Related to @azure/msal-react question Customer is asking for a clarification, use case or information.

Comments

@MarekLani
Copy link

MarekLani commented Jan 25, 2021

Library

  • msal@1.x.x or @azure/msal@1.x.x
  • @azure/msal-browser@2.x.x
  • @azure/msal-node@1.x.x
  • @azure/msal-react@1.x.x (Alpha 1)
  • @azure/msal-angular@0.x.x
  • @azure/msal-angular@1.x.x
  • @azure/msal-angular@2.x.x
  • @azure/msal-angularjs@1.x.x

Framework

  • Angular
  • React
  • Other

Description

I am developing react app and authenticating user against AAD B2C using react msal library. I was able to make the authentication working and I am able to acquire token silently, however I am facing issue when original token expires:

BrowserAuthError: silent_sso_error: Silent SSO could not be completed - insufficient information was provided. Please provide either a loginHint or sid.

I assume this has something to do with token not being refreshed. Is there anything I should do explicitly, so that token gets refreshed?

Error Message

BrowserAuthError: silent_sso_error: Silent SSO could not be completed - insufficient information was provided. Please provide either a loginHint or sid.

MSAL Configuration

const tenant = "mytenant.onmicrosoft.com";

const signInPolicy = "B2C_1A_signup_signin";
const applicationID = "<appid>";
const reactRedirectUri = "http://localhost:1234/home";
const tenantSubdomain = tenant.split(".")[0];
const instance = `https://${tenantSubdomain}.b2clogin.com/`;
const signInAuthority = `${instance}${tenant}/${signInPolicy}`;// Msal Configurations
const authorityDomain = "mytenant.b2clogin.com"
// Config object to be passed to Msal on creation
export const msalConfig = {
  auth: {
      clientId: applicationID,
      authority: signInAuthority,
      knownAuthorities: [
        authorityDomain
      ]
  }
};

export const loginRequest: RedirectRequest = {
  scopes: ["https://mytenant.onmicrosoft.com/api/read"]
};

Reproduction steps

Login using sample code
Wait for 24 hours for token to expire
Issue appears

    React.useEffect(() => {
        if (account && inProgress === "none")
            instance.acquireTokenSilent({
                ...loginRequest,
                account: account
            }).then((response) => {
                ...
            })

    }, [account])

Expected behavior

AcquireTokenSilently would acquire the token

Identity Provider

  • Azure AD
  • Azure B2C Basic Policy
  • Azure B2C Custom Policy
  • ADFS
  • Other

Browsers/Environment

  • Chrome
  • Firefox
  • Edge
  • Safari
  • IE
  • Other (Please add browser name here)

Regression

  • Did this behavior work before?
    Version:

Security

  • Is this issue security related?

Source

  • Internal (Microsoft)
  • Customer request
@MarekLani MarekLani added bug-unconfirmed A reported bug that needs to be investigated and confirmed question Customer is asking for a clarification, use case or information. labels Jan 25, 2021
@jo-arroyo jo-arroyo added b2c Related to Azure B2C library-specific issues msal-react Related to @azure/msal-react labels Jan 25, 2021
@tnorling
Copy link
Collaborator

@MarekLani You have 3 options in this scenario:

  1. Configure your tenant to return the emails claim on idTokens. Read more here
  2. Explicitly include loginHint with the user's email on the request object passed to acquireTokenSilent
  3. Call an interactive method such as acquireTokenPopup or acquireTokenRedirect when acquireTokenSilent fails. (We recommend you do this anyway, in addition to one of the first 2)

@MarekLani
Copy link
Author

@tnorling thank you for response, however I am not able to set loginHint on acquireTokenSilent, it seems not to be valid parameter (I am using typescript)

@tnorling
Copy link
Collaborator

@MarekLani My mistake, you're right loginHint is not part of the acquireTokenSilent request object. You should use the account object and ensure the username field is populated. You can do this either by enabling the emails claim on your B2C tenant and MSAL will handle this automatically, or you can manually update the username property with the user's login before passing it to acquireTokenSilent

@MarekLani
Copy link
Author

Thank you @tnorling, I was trying to enable emails claim in my custom policy, but I probably made mistake somewhere, can't find documentation on doing it, but will try to manually set the username using email from idTokenClaims. Will report back

@hectormmg hectormmg removed the bug-unconfirmed A reported bug that needs to be investigated and confirmed label Feb 2, 2021
@code-by-gijs
Copy link

code-by-gijs commented Feb 4, 2021

The accesstoken will always expire after 24 hours, even if you refresh your tokens. There is no rolling window. This is how the flow works within a SPA. As @tnorling explained, you should trigger an interactive flow when acquireTokenSilent fails.

offtopic: I really hope this will be changed within b2c... It's really hard to create a user friendly app when your token expires every 24 hours.

@MarekLani
Copy link
Author

@code-by-gijs thanks for additional context, would this be helpful in this case: https://docs.microsoft.com/en-us/azure/active-directory-b2c/session-behavior?pivots=b2c-custom-policy

@tnorling
Copy link
Collaborator

tnorling commented Feb 4, 2021

The accesstoken will always expire after 24 hours, even if you refresh your tokens. There is no rolling window. This is how the flow works within a SPA. As @tnorling explained, you should trigger an interactive flow when acquireTokenSilent fails.

The refresh token expires after 24 hours. Access token lifetimes are 1 hour.

offtopic: I really hope this will be changed within b2c... It's really hard to create a user friendly app when your token expires every 24 hours.

When the refresh token expires after 24 hours msal.js will attempt to silently acquire a new set of tokens (including refresh token) using a hidden iframe, this is what @MarekLani was asking about. This will not work if you don't have a login_hint or if your browser blocks 3rd party cookies in which case you will need to invoke an interactive flow.

@MarekLani If you enable the emails claim on your id tokens this should just work, assuming 3rd party cookies are not blocked. There's some short instructions here, however, if you need more help getting this setup you can contact B2C Support as they are more knowledgeable than me about B2C policy setup.

@code-by-gijs
Copy link

code-by-gijs commented Feb 4, 2021

Just to add on to what @tnorling has said, the auth server will send a new refresh token when you use one to renew an access token. So if you call acquireTokenSilent at least once every 24 hours, your application will not perform an interactive flow. The only time you will need to handle the acquireTokenSilent failure with an interactive call is if it has not been called within 24 hours of a token retrieval or renewal.

Nope, you can refresh a token for 24 hours, after those 24 hours, you cannot refresh your token anymore. It is not a rolling window for a SPA. So every 24 hours you will have to perform an interactive flow.

@pkanher617
Copy link
Contributor

My mistake! I was under the impression the new refresh token had a new expiration. please disregard my comment.

@tnorling
Copy link
Collaborator

tnorling commented Feb 4, 2021

So every 24 hours you will have to perform an interactive flow.

@code-by-gijs This is not accurate. See my comment above regarding hidden iframes.

@code-by-gijs
Copy link

So every 24 hours you will have to perform an interactive flow.

@code-by-gijs This is not accurate. See my comment above regarding hidden iframes.

Hidden iframes are not the way to go. They require third party cookies. More and more browsers are dropping support for third party cookies by default.

@pkanher617
Copy link
Contributor

pkanher617 commented Feb 18, 2021

Unfortunately there isn't another workaround at the moment. The limitation of 3p cookies being blocked is going to be more prevalent, as you called out. We are working on solutions that may leverage Storage Access API, but these are still in design and will need time from the server team and the MSAL team to implement correctly. Until then the only way to handle this is to make a request using the redirect or popup APIs every 24 hours.

@RonniePitts
Copy link

RonniePitts commented Mar 2, 2021

The expired acquireTokenSilent call does return the error code from the 400 response however this information isnt available in the catch instead it returns "Silent SSO could not be completed - insufficient information was provided. Please provide either a loginHint or sid."

The actual response from the failed request :

error: "invalid_grant",…}
error: "invalid_grant"
error_description: "AADB2C90080: The provided grant has expired. Please re-authenticate and try again. Current time: 1614680980, Grant issued time: 1614431911, Grant expiration time: 1614514326
↵Correlation ID: xxxxxx
↵Timestamp: 2021-03-02 10:29:40Z
↵"

It would be nice to capture these details as the current errormessage is misleading.

@MarekLani, how do you send across the email address from social accounts, for example google?

@tnorling
Copy link
Collaborator

tnorling commented Mar 2, 2021

@RonniePitts What you're experiencing is by design and the error that you're receiving is telling you what's not working. This happens because acquireTokenSilent internally catches the invalid_grant error and attempts to silently resolve it by using a hidden iframe to acquire new access and refresh tokens. It's this part that is now failing with the insufficient information error because the account object you passed to acquireTokenSilent does not have a username field (which is used as the loginHint metioned in the error). Since you're using B2C you will need to enable the emails claim on your idTokens to ensure your account contains the necessary fields. More information on that can be found here

@RonniePitts
Copy link

@tnorling, doesnt passing the email address become an issue when you may have mutiple social accounts with the same email address? Is it possible to pass across the localAccountId instead which is available from the prior cache object?

@tnorling
Copy link
Collaborator

tnorling commented Mar 2, 2021

@RonniePitts Email is currently the only session identifier the service accepts. With that said, the B2C service doesn't do anything with the loginHint MSAL sends them in most scenarios, they rely on the cookies set during login. The error thrown in the library is to make sure that developers are passing some session identifier as it is used, and required, in other non-B2C scenarios. The multiple account scenario you call out is definitely a valid concern and we're working with the B2C service team to improve this experience. If you would like to give them your feedback directly and/or get some support you can open a ticket with the service team by following these instructions

@vinizinmoraes-concrete
Copy link

@RonniePitts What you're experiencing is by design and the error that you're receiving is telling you what's not working. This happens because acquireTokenSilent internally catches the invalid_grant error and attempts to silently resolve it by using a hidden iframe to acquire new access and refresh tokens. It's this part that is now failing with the insufficient information error because the account object you passed to acquireTokenSilent does not have a username field (which is used as the loginHint metioned in the error). Since you're using B2C you will need to enable the emails claim on your idTokens to ensure your account contains the necessary fields. More information on that can be found here

There is any tutorial to show how to accomplish it using a custom user flow ? My user flow need to be changed in a xml way, but I don`t know how to do it.

@tnorling
Copy link
Collaborator

@vinizinmoraes-concrete You should open a ticket with the B2C service and they should be able to help you configure your user flow.

As the original question has been answered I'm going to go ahead and close this issue. Please open a new issue if you have additional non-service related questions, thanks!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 19, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
b2c Related to Azure B2C library-specific issues msal-react Related to @azure/msal-react question Customer is asking for a clarification, use case or information.
Projects
None yet
Development

No branches or pull requests

8 participants