使用 MIcrosoft Graph (accessToken) 的 firebase 身份验证

firebase auth with MIcrosoft Graph (accessToken)

我非常希望有人能帮助我 - 我有点卡住了。

我很高兴将 firebase 身份验证与 Microsoft AD 结合使用。我的 AuthProvider 是 firebase.auth.OAuthProvider('microsoft.com').

当我通过该提供商致电 firebase.auth().signInWithPopup() 时,一切正常。我可以从结果 UserCredential 中挑选出 accessToken 并访问 Microsoft Graph api 没问题(耶!)。

Firebase 坚持并更新身份验证,当用户 returns 稍后访问我的 SPA 时,我的应用程序通过 onAuthStateChanged 和新的 firebase.User 获得预期的回调(也是耶!)。

坏消息(我被卡住的地方)是:如何在此流程中获取 Microsoft Graph accessToken(例如,当用户 returns 稍后访问我的应用程序时)?我不希望他们必须使用另一个弹出窗口重新进行身份验证 (yech)。

基本上,当用户 returns 时,如何从有效 firebase.User 到 MS 图表 accessToken

非常感谢您的帮助!

Firebase Auth 仅专注于身份验证。他们将 return 通过 UserCredential 成功登录时的 OAuth 访问令牌,但会丢弃 Microsoft OAuth 刷新令牌并且不存储与提供者关联的任何 OAuth 凭据。因此您之后无法获得新的访问令牌。如果您有充分的理由让 Firebase Auth 管理 OAuth 访问令牌,请提交 official feature request.

当您使用 signInWithPopup 时,结果对象包含您要查找的凭据。

firebase.auth().signInWithPopup(provider)
  .then(function(result) {
    // User is signed in.
    // IdP data available in result.additionalUserInfo.profile.
    // OAuth access token can also be retrieved:
    // result.credential.accessToken
    // OAuth ID token can also be retrieved:
    // result.credential.idToken
  })
  .catch(function(error) {
    // Handle error.
  });

希望对您有所帮助。

UPDATE/answer:原来比我想的要简单:

基本思路是使用 firebase 进行身份验证(重新身份验证),并使用相同的 clientID 进行静默 Microsoft 身份验证。但是,您必须提供loginHint microsoft auth 的参数,即使您之前已获得授权。 loginHint 可以 是 firebase 用户的电子邮件地址...

在那种情况下,身份验证是共享的,您不需要为进程的“微软一半”弹出第二次登录 - firebase 身份验证工作正常。

我最终使用了微软的 MSAL 库 (https://github.com/AzureAD/microsoft-authentication-library-for-js)...像这样:

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 => {
    msal
      .acquireTokenSilent({ scopes: SCOPES, loginHint })
      .then(result => {
        callback(null, result.accessToken);
      })
      .catch(err => callback(err, null));
  };

  const client = Client.init({
    authProvider,
    debugLogging: graphDebug,
  });

  return client;
}

如果你看得足够深,你应该在 (firebaseAuth.currentUser as zzx).zzj()

下的 firebase 响应中找到 msal 访问令牌