Firebase Auth With MIcrosoft Graph (accessToken)

I am super hopeful someone can help me - I'm kind of stuck.

I'm happily using firebase auth with Microsoft AD. My AuthProvider is firebase.auth.OAuthProvider('').

When I call firebase.auth().signInWithPopup() with that provider, everything works GREAT. I can pick out the accessToken from the resulting UserCredential and access Microsoft Graph api's no problem (yay!).

Firebase persists and renews the authentication and my app gets the expected callback via onAuthStateChanged with the new firebase.User when the user returns to my SPA later (also yay!).

The bad news (where I'm stuck) is: how do I get the Microsoft Graph accessToken in this flow (e.g. when the user returns to my app later)? I don't want them to have to re-authenticate with another popup (yech).

Basically, how do I go from a valid firebase.User to a MS Graph accessToken when the user returns?

Thanks so so much for any help!



UPDATE/answer: so it turns out to be simpler than I thought:

The basic idea is to authenticate (re-authenticate) using firebase and use the same clientID for silent microsoft authentication. However, you must supply a loginHint parameter to the microsoft auth, even if you were previously authorized. loginHint can be the email address for the firebase user...

In that scenario, the authentication is shared and you won't need to popup a second sign-in for the "microsoft half" of the process - the firebase auth works fine.

I ended up using microsoft's MSAL library ( something like this:

const graphDebug = false;
const msalLogger = new Logger(msalLogCallback, { level: LogLevel.Error });

export async function graphClient(loginHint: string) {
  const msal = new UserAgentApplication({
    // gotcha: MUST set the redirectUri, otherwise get weird errors when msal
    // tries to refresh an expired token.
    auth: { clientId: CLIENT_ID, redirectUri: window.location.origin },
    system: { logger: msalLogger },
    // TODO: should we set cache location to session/cookie?

   * Create an authprovider for use in subsequent graph calls. Note that we use
   * the `aquireTokenSilent` mechanism which works because firebase has already
   * authenticated this user once, so we can share the single sign-on.
   * In order for that to work, we must pass a `loginHint` with the user's
   * email. Failure to do that is fatal.
  const authProvider: AuthProvider = callback => {
      .acquireTokenSilent({ scopes: SCOPES, loginHint })
      .then(result => {
        callback(null, result.accessToken);
      .catch(err => callback(err, null));

  const client = Client.init({
    debugLogging: graphDebug,

  return client;