microsoft-authentication-library-for-js: acquireTokenSilent doesn't renew the id-token

Core Library

MSAL.js v2 (@azure/msal-browser)

Core Library Version

2.18.0

Wrapper Library

Not Applicable

Wrapper Library Version

None

Description

Hi Micrsoft communiy,

We have a react app, which implements your library as described below. We only use it to get an id-token for validating the Microsoft account on our server. Unfortunately, after an hour the id-tokens that are returned by the acquireTokenSilent function are expired.

We have tried to set tokenRenewalOffsetSeconds to 300, but this doesn’t resolve the issue. If we logout, clear the cache or refresh the site a few times, we get a valid token again. But this is unfortunately, very unpleasant for our users.

We get a lot of customer complaints on a daily basis, because of this issue. Please help us. We are thankful for any suggestions. Thanks!!

Error Message

No response

Msal Logs

Here are some logs. Please ignore the “DEBUG” in front of the messages.:

DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:handleRedirectStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : [5c24a3aa-1095-42c9-85a2-d71a097390a4] : msal.js.browser@2.18.0 : Info - handleRedirectPromise called but there is no interaction in progress, returning null. log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:handleRedirectEnd log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:08:42 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess log.js:16:10

// we get an expired id-token

// we refresh the page

// we get the same logs as above and get an expired id-token

// we refresh the page again

DEBUG | Message: [Mon, 01 Nov 2021 16:09:53 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:handleRedirectStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:53 GMT] : [2e893bd0-832f-4730-8cae-22e5108dada7] : msal.js.browser@2.18.0 : Info - handleRedirectPromise called but there is no interaction in progress, returning null. log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:53 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:handleRedirectEnd log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:53 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenFromNetworkStart log.js:16:10
Some cookies are misusing the recommended “SameSite“ attribute 2
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenStart log.js:16:10
DEBUG | Message: [Mon, 01 Nov 2021 16:09:54 GMT] : @azure/msal-browser@2.18.0 : Info - Emitting event: msal:acquireTokenSuccess

// we suddenly get a valid id-token and everything works again as expected

MSAL Configuration

{
    auth: {
      authority: 'https://login.microsoftonline.com/common',
      clientId: <client-id>,
      postLogoutRedirectUri: window.location.origin,
      redirectUri,
      validateAuthority: true,
      navigateToLoginRequestUrl: false,
    },

    system: {
      loggerOptions: {
        loggerCallback: (level, message, containsPii) => {
          console.log(message);
        },
        piiLoggingEnabled: false  // disables personal information
      },
      windowHashTimeout: 60000,
      iframeHashTimeout: 10000,
      loadFrameTimeout: 0,
      // I also tried: tokenRenewalOffsetSeconds: 300
    },

    cache: {
      cacheLocation: 'localStorage',
      storeAuthStateInCookie: true
    }
}

Relevant Code Snippets

const msalScopes = [ 'openid', 'User.Read' ];
const graphScopes = [ ];
const config = ... // see above
const msalClient = new PublicClientApplication(config);

// login (not essential):
const login = async () => {
  const accounts = msalClient.getAllAccounts();
  if (accounts || accounts.length < 1) {
    let tokenResponse = await msalClient.handleRedirectPromise();
    const accountObj = tokenResponse
      ? tokenResponse.account
      : msalClient.getAllAccounts()[0];

    if (!tokenResponse) {
      if (accountObj) {
        // User has logged in, but no tokens:
        try {
          tokenResponse = await msalClient.acquireTokenSilent({
            account: msalClient.getAllAccounts()[0],
            scopes: msalScopes,
          });
        } catch (err) {
          await msalClient.acquireTokenRedirect({ scopes: msalScopes });
        }
      } else {
        // No accountObject or tokenResponse present. User must now login:
        await msalClient.loginRedirect({ scopes: msalScopes });
      }
    }
  }
}

// get id-token (here is the problem):
async getIdToken(scopes=null) {
  const accounts = msalClient.getAllAccounts();
  
  const { idToken } = await msalClient.acquireTokenSilent({
    account: accounts[0],
    scopes: (scopes ? scopes : [...msalScopes, ...graphScopes]).filter(onlyUnique)
  });
  return idToken;
}

Reproduction Steps

  1. Implement the code above
  2. login
  3. get an id-token
  4. wait 1 hour
  5. get another id-token, which is expired

Expected Behavior

The id-token should be refreshed before it expires.

Identity Provider

Azure AD / MSA

Browsers Affected (Select all that apply)

Chrome, Firefox

Regression

No response

Source

External (Customer)

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 15
  • Comments: 32 (5 by maintainers)

Commits related to this issue

Most upvoted comments

I am seeing the same issue in my apps. I chose a variation on the workaround to dynamically set the forceRefresh option based on the id_token being expired. If you have LOTS of API calls using the id_token leveraging the cache is very important…

        const idTokenClaims: { exp?: number } = this.authService.instance.getActiveAccount().idTokenClaims;
        const forceRefresh = (new Date(idTokenClaims.exp + 1000) < new Date()); 
       
        this.authService.instance
            .acquireTokenSilent({
              forceRefresh: forceRefresh
            }).then((authResponse) => {
              // do something with authResponse.idToken 
            });

Looking forward to fix in MSAL library.

Hi, we are facing this exact same issue. The workaround by forcing a refresh is suboptimal for various reasons :-
Is there any eta for an update for this?

I’m going to drop a link on ID Tokens as a reference if folks have additional questions on ID Token usage.
https://learn.microsoft.com/en-us/azure/active-directory/develop/id-tokens

For this particular issue we’re going to have to make an API/interface change to address this to request explicit token types. For instance, you should be able to just request an Access Token without a Refresh Token, or just an ID Token. We’ve got an internal item tracking for this work for a future major release. In the interim, this won’t be changed for MSAL.js v2.x.y releases.

What happens if you provide forceRefresh: true on the acquireTokenSilent request object?

I experience the exact same issue. Could you please have a look on this one @tnorling?

The initial assumption we made when we designed the library is the uniformity between expiry times for id_token and access_token. However, this is not true in all cases and we need to enhance the library to support these various expiry times. Added this to our internal backlog.

However, please note that this would need some redesign from our end and hence will take some time.

@its-miller-time

We were wanting to simply pass the headers along and validate the token in our API but it doesn’t sound like that’s possible? From what I gather the recommended/only solution would be to make an app registration specifically for our api’s and request an additional token? Or will a custom scope allow us to use the same access token?

Access tokens are scoped to a single resource. If you need to access MS Graph APIs in addition to your own API you need 2 access tokens. However, this does not mean you need more than 1 app registration, you can register as many API permissions as you need on a single app registration.

On a side note: the ID token had been working fine for a year prior to this. Did something change in the ID token lifetime to where it expires sooner now?

The issue here is that AAD changed access tokens lifetimes from a static 60 minutes to a variable 60-90 minutes and MSAL.js only checks access token lifetimes. Id tokens still have a static 60 minute lifetime.