Search code examples
javascriptreactjsazure-ad-msal

I don't get any account information with MSAL


I'm fairly new to Javascript and web development in general. Sorry in advance if I expressed myself incorrectly.

Now to the problem: I want to create a login page with the MSAL, but when testing I always get the following error and can´t Login:

Uncaught (in promise) 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.

_AuthError chunk-3XQJSEYN.js:319

_BrowserAuthError chunk-3XQJSEYN.js:8258

createBrowserAuthError chunk-3XQJSEYN.js:8264

acquireTokenSilent chunk-3XQJSEYN.js:14613

acquireTokenSilent PublicClientApplication.ts:134

Login Login.js:30

The App regestration is configured correctly and i have acces. It looks like I can't get any account information.

When I log:

msalInstance.getAllAccounts()[0] 

all I get is undefined.

The same with:

msalInstance.setActiveAccount(account);

here is my code:

import { AuthConfig } from "../Config/AuthenticationConfig.js";
import { PublicClientApplication } from "@azure/msal-browser";

export async function Login() {
  const msalInstance = new PublicClientApplication({
    auth: {
      clientId: AuthConfig.clientId,
      redirectUri: AuthConfig.redirectUri,
      postLogoutRedirectUri: AuthConfig.postLogoutRedirectUri,
      authority: AuthConfig.authority,
    },
    cache: {
      cacheLocation: "sessionStorage",
      storeAuthStateInCookie: false,
    },
  });

  await msalInstance.initialize();

  const account = msalInstance.getAllAccounts()[0];

  const accessTokenRequest = {
    scopes: ["User.Read"],
    account: account
  };

  await msalInstance.setActiveAccount(account);
  console.log(account + "test");

  await msalInstance.acquireTokenSilent(accessTokenRequest).then((tokenResponse) => {
    console.log(JSON.stringify(tokenResponse.accessToken));
  });


  await msalInstance.loginPopup({
    scopes: AuthConfig.scopes,
    prompt: "select_account",
  });

  return;
}

Here is my configuration file for the PublicClientApplication instances:

export const AuthConfig = {
  clientId: "***",
  redirectUri: "http://localhost:***/",
  postLogoutRedirectUri: "http://localhost:***/Login",
  scopes: ["User.Read"],
  authority:
    "https://login.microsoftonline.com/***",
};

Here is my Page

import * as apiservice from "../Utility/Login.js";
import "../App.css";
import "../index.css";

export function ShowLoginPage() {
  return (
    <div className="App">
      <header>
        <div className="LogginBackground">
          <img
            src={
              "****"
            }
            className="App-logo"
            alt="logo"
          />
          <img
            src={"****"}
            className="picture"
            alt="picture"
          />
          <p>
            <button
              onClick={async () => {
                await apiservice.Login();
              }}
            >
              Login
            </button>
          </p>
        </div>
      </header>
    </div>
  );
}

my goal is to execute .acquireTokenSilent(accessTokenRequest) and get the token for further use

I tried to postpone the initialization and also change the position of SetActiveAccount and getAllAccounts, but unfortunately without success.


Solution

  • It looks to me like you are trying to fetch the account before you log in. The login process gives you the account info.

    The other thing to note is that you try Silent Sign on first and then if that doesnt work you use login prompt.

    Here is some code that I have used previously. It is maybe 1 year old, so not sure if things have changed- eg I didnt use msal.initialize(). I would have drawn heavily from the msal sample code.

    msalintsance.js

    
    import * as msal from "@azure/msal-browser";
    import authConfig from "xxx.js";
    
    export const msalConfig = {
      auth: {
        authority: authConfig.authority,
        clientId: authConfig.clientId,
        scopes: authConfig.scopes,
        redirectUri: "/",
      },
      cache: {
        cacheLocation: "localStorage",
        storeAuthStateInCookie: false,
      },
    };
    
    export const msalInstance = new msal.PublicClientApplication(msalConfig);
    
    

    auth.js

    
    import { msalConfig, msalInstance } from "./msalInstance";
    
    let homeAccount = null;
    let signedInAs = null;
    
    
    async function SignIn() {
      
      const loginRequest = { scopes: msalConfig.auth.scopes };
      let loginResponse = null;
    
      // signedInAs is a module variable with the last email address that the app used to sign in. 
      // Used as a hint for sso
      if (signedInAs) {
        loginRequest.loginHint = signedInAs;
      }
    
      try {
        loginResponse = await msalInstance.ssoSilent(loginRequest);
        console.log("Silent Sign On completed");
        ProcessADSignIn(loginResponse);
      } catch (err) {
        if (err.name === "InteractionRequiredAuthError") {
          console.log("Unable to Silently Sign On. Using Login Popup");
    
          try {
            loginResponse = await msalInstance.loginPopup(loginRequest);
            ProcessADSignIn(loginResponse);
          } catch (error) {
            console.log("Interactive Sign On FAILED", error);
          }
        } else {
          console.log(
            "An unexpected error (Not an authentication error) occured during Silent Sign On"
          );
          console.log(err);
        }
      }
    
    }
    
    
    async function ProcessADSignIn(loginResponse) {
    
      signedInAs = loginResponse.idTokenClaims.preferred_username;
    
      let allAccounts = msalInstance.getAllAccounts();
    
      if (allAccounts.length > 0) {
        homeAccount = msalInstance.getAccountByHomeId(allAccounts[0].homeAccountId);
      }
    
    
      await FetchPersonProfile();
      // etc...
      
    }