Skip to content

How to use the cached tokens from Msal acquireTokenSilent #6

Description

@fong1999

Hi! @derisen I watched the youtube video https://www.youtube.com/watch?v=7oPSL5wWeS0. Very helpful!

I have some questions regarding how to use the token.

The way we are currently having is to call acquireTokenSilent (I attached the code below) on the page initial load at the beginning. What we need is to have all the users authenticated at the page loading time, so that the tokens are available. In parallel, we need to the id token to a process in order to call another API for different data besides calling Azure graph API. With those tokens are cached in sessionStorage (which we defined/ default to use sessionStorage for now), which way to use them for this purpose? I see in your code example, you get access token from useMsalAuthentication. (We don’t use pop up. We authenticate the users by redirect. ) Should I use the same way to get the id token? using useMsalAuthentication with setting up the InteractionType to redirect? Can this be done to achieve our goal?

The way we have now is to get the id token at the time that “acquireTokenSilent” is being called, but is it possible that we can use the id token afterwards? In other words, to get the token from sessionStorage by using sessionstorage getItem function?
—————————————————————————————-

export function getIdTokenFromAzure(): Promise<string> {
  return getTokenRedirect(loginRequest).then(response => {
    if (!response || !response.idToken) {
      console.log("MsalAuthService >>> getIdTokenFromAzure : Failed to get access token, no redirect response");
      return "";
    } else {
      return response.idToken;
    }
  })
}

———————————————————————————————
Another question: I noticed that if I make a call to via getIdTokenFromAzure function in App.tsx, I will get a warning message MsalAuthService.ts:85 MsalAuthService >>> getTokenRedirect : BrowserAuthError: no_account_error: No account object provided to acquireTokenSilent and no active account has been set. Please call setActiveAccount or provide an account on the request. The reason is I call it too early before the account is set.

And also, how to use the token from sessionStorage to serve other API calls that use it in parallel?

Any suggestions? Much appreciated! Thanks!

export const msalConfig = {
  auth: {
    clientId: EnvironmentService.getAzureClientId(),
    redirectUri: `${window.location.origin}`,
    authority: `https://login.microsoftonline.com/${EnvironmentService.getAzureTenantId()}`
  },
  cache: {
    cacheLocation: "sessionStorage", // This configures where your cache will be stored
    storeAuthStateInCookie: true, // Set this to "true" if you are having issues on IE11 or Edge
  },
  system: {
    loggerOptions: {
      loggerCallback: (level: any, message: any, containsPii: any) => {
        if (containsPii) {
          return;
        }
        switch (level) {
          case LogLevel.Error:
            console.error(message);
            return;
          case LogLevel.Info:
            console.info(message);
            return;
          case LogLevel.Verbose:
            console.debug(message);
            return;
          case LogLevel.Warning:
            console.warn(message);
            return;
          default:
            return;
        }
      }
    }
  }
}

const loginRequest = {
  scopes: ["openid", "profile", "User.Read"]
}

/**
 * Sets flag forceRefresh to true, the program will skip the cached id token in sessionStorage,
 * it will call the server directly to get a new id token and replace the catched one with this new
 * value to sessionStorage.
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/FAQ.md#how-do-i-renew-tokens-with-msaljs
 */
const tokenRequestForceRefresh = {
  scopes: ["User.Read"],
  forceRefresh: true,
}

export let myMSALObj = new PublicClientApplication(msalConfig);
export let username = "";

if (!BrowserUtils.isIframe()) {
  // Redirect: once login is successful and redirects with tokens, call Graph API
  myMSALObj.handleRedirectPromise().then(handleResponse).catch(err => {
    console.error(err);
  });
}

export function hasActiveMsalSession(): boolean {
  return !!username;
}

function handleResponse(resp) {
  if (resp !== null) {
    username = resp.account.username;
    myMSALObj.setActiveAccount(resp.account);
  } else {
    /**
     * See here for more info on account retrieval:
     * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
     */
    const currentAccounts = myMSALObj.getAllAccounts();
    if (currentAccounts === null) {
      return;
    } else if (currentAccounts.length > 1) {
      // Add choose account code here
      console.warn("MsalAuthService >>> handleResponse >>> Multiple accounts detected.");
    } else if (currentAccounts.length === 0) {
      signIn();
    } else if (currentAccounts.length === 1) {
      username = currentAccounts[0].username;
      myMSALObj.setActiveAccount(currentAccounts[0]);
    }
  }
}

function signIn() {
  myMSALObj.loginRedirect(loginRequest);
}


function getTokenRedirect(request) {
  /**
   * See here for more info on account retrieval:
   * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
   */
  return myMSALObj.acquireTokenSilent(request).catch(error => {
    console.warn("MsalAuthService >>> getTokenRedirect : Silent token acquisition fails. acquiring token using redirect");
    if (error instanceof Msal.InteractionRequiredAuthError) {
      // fallback to interaction when silent call fails
      return myMSALObj.acquireTokenRedirect(request);
    } else {
      console.warn("MsalAuthService >>> getTokenRedirect : " + error);
    }
  });
}

export function getAccessToken(): Promise<string> {
  return getTokenRedirect(loginRequest).then(response => {
    if (!response || !response.accessToken) {
      console.log("MsalAuthService >>> getAccessToken : Failed to get access token, no redirect response");
      return "";
    } else {
      return response.accessToken;
    }
  })
}


export function getIdTokenFromAzure(): Promise<string> {
  return getTokenRedirect(loginRequest).then(response => {
    if (!response || !response.idToken) {
      console.log("MsalAuthService >>> getIdTokenFromAzure : Failed to get access token, no redirect response");
      return "";
    } else {
      return response.idToken;
    }
  })
}

Thanks so much!!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions