Google 致力于为黑人社区推动种族平等。查看具体举措

在 JavaScript 中使用 Microsoft 进行身份验证

如需让您的用户能够使用 OAuth 提供方(如 Microsoft Azure Active Directory)进行 Firebase 身份验证,您可以使用 Firebase SDK 执行端到端登录流程,将通用 OAuth 登录机制集成到您的应用中。

准备工作

要让用户能够通过 Microsoft 帐号(Azure Active Directory 和个人 Microsoft 帐号)登录,您必须先启用 Microsoft 作为您的 Firebase 项目的登录服务提供方:

  1. 将 Firebase 添加至您的 JavaScript 项目
  2. Firebase 控制台中,打开身份验证部分。
  3. 登录方法标签页中,启用 Microsoft 提供方。
  4. 将该提供方的开发者控制台中的客户端 ID客户端密钥添加至提供方配置:
    1. 如需注册 Microsoft OAuth 客户端,请按照快速入门:使用 Azure Active Directory v2.0 端点注册应用中的说明进行操作。 请注意,此端点同时支持使用 Microsoft 个人帐号和 Azure Active Directory 帐号进行登录。 详细了解 Azure Active Directory v2.0。
    2. 通过这些提供方注册应用时,请务必将项目的 *.firebaseapp.com 网域注册为应用的重定向网域。
  5. 点击保存

使用 Firebase SDK 处理登录流程

如果您是在构建 Web 应用,希望通过用户的 Microsoft 帐号对其进行 Firebase 身份验证,最简单的方法是使用 Firebase JavaScript SDK 来处理整个登录流程。

如需使用 Firebase JavaScript SDK 处理登录流程,请按以下步骤操作:

  1. 使用提供方 ID microsoft.com 创建 OAuthProvider 的一个实例。

    Web 版本 9

    import { OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');

    Web 版本 8

    var provider = new firebase.auth.OAuthProvider('microsoft.com');
  2. 可选:指定您希望通过 OAuth 请求发送的其他自定义 OAuth 参数。

    Web 版本 9

    provider.setCustomParameters({
      // Force re-consent.
      prompt: 'consent',
      // Target specific email with login hint.
      login_hint: 'user@firstadd.onmicrosoft.com'
    });

    Web 版本 8

    provider.setCustomParameters({
      // Force re-consent.
      prompt: 'consent',
      // Target specific email with login hint.
      login_hint: 'user@firstadd.onmicrosoft.com'
    });

    如需查看 Microsoft 支持的参数,请参阅 Microsoft OAuth 文档。 请注意,您不能使用 setCustomParameters() 传递 Firebase 必需的参数。这些参数包括 client_idresponse_typeredirect_uristatescoperesponse_mode

    如需仅允许来自特定 Azure AD 租户的用户登录应用,可以使用 Azure AD 租户的易记域名或该租户的 GUID 标识符。为此,您可以在自定义参数对象中指定“tenant”字段。

    Web 版本 9

    provider.setCustomParameters({
      // Optional "tenant" parameter in case you are using an Azure AD tenant.
      // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or 'contoso.onmicrosoft.com'
      // or "common" for tenant-independent tokens.
      // The default value is "common".
      tenant: 'TENANT_ID'
    });

    Web 版本 8

    provider.setCustomParameters({
      // Optional "tenant" parameter in case you are using an Azure AD tenant.
      // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or 'contoso.onmicrosoft.com'
      // or "common" for tenant-independent tokens.
      // The default value is "common".
      tenant: 'TENANT_ID'
    });
  3. 可选:指定您希望向身份验证提供方申请获取的个人资料基本信息以外的额外 OAuth 2.0 范围。

    provider.addScope('mail.read');
    provider.addScope('calendars.read');
    

    如需了解详情,请参阅 Microsoft 权限和许可文档

  4. 使用 OAuth 提供方对象进行 Firebase 身份验证。您可以通过打开弹出式窗口或重定向至登录页面,提示用户使用自己的 Microsoft 帐号登录。在移动设备上最好使用重定向方法。

    • 若要使用弹出式窗口登录,请调用 signInWithPopup

    Web 版本 9

    import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    signInWithPopup(auth, provider)
      .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
    
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });

    Web 版本 8

    firebase.auth().signInWithPopup(provider)
      .then((result) => {
        // IdP data available in result.additionalUserInfo.profile.
        // ...
    
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // OAuth access and id tokens can also be retrieved:
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });
    • 如需通过重定向到登录页面进行登录,请调用 signInWithRedirect

    Web 版本 9

    import { getAuth, signInWithRedirect } from "firebase/auth";
    
    const auth = getAuth();
    signInWithRedirect(auth, provider);

    Web 版本 8

    firebase.auth().signInWithRedirect(provider);

    用户完成登录并返回到页面后,您可以通过调用 getRedirectResult 获取登录结果。

    Web 版本 9

    import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
    
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });

    Web 版本 8

    firebase.auth().getRedirectResult()
      .then((result) => {
        // IdP data available in result.additionalUserInfo.profile.
        // ...
    
        /** @type {firebase.auth.OAuthCredential} */
        var credential = result.credential;
    
        // OAuth access and id tokens can also be retrieved:
        var accessToken = credential.accessToken;
        var idToken = credential.idToken;
      })
      .catch((error) => {
        // Handle error.
      });

    成功完成后,可以从返回的 firebase.auth.UserCredential 对象检索与提供方关联的 OAuth 访问令牌。

    使用 OAuth 访问令牌,您可以调用 Microsoft Graph API

    例如,要获取个人资料基本信息,可以调用以下 REST API:

    curl -i -H "Authorization: Bearer ACCESS_TOKEN" https://graph.microsoft.com/v1.0/me
    

    与 Firebase Authentication 支持的其他提供方不同,Microsoft 不提供照片网址,您必须通过 Microsoft Graph API 来请求个人资料照片的二进制数据。

    除了 OAuth 访问令牌,您还可以从 firebase.auth.UserCredential 对象检索用户的 OAuth ID 令牌。ID 令牌中的 sub 声明取决于具体应用,该声明与 Firebase 身份验证使用的联合用户标识不匹配,可通过 user.providerData[0].uid 访问。应改用 oid 声明字段。 使用 Azure AD 租户登录时,oid 声明将完全匹配。不过,对于非租户,系统将填充 oid 字段。对于联合 ID 4b2eabcdefghijkloid 的格式为 00000000-0000-0000-4b2e-abcdefghijkl

  5. 以上示例侧重的是登录流程。除此之外,您也可以使用 linkWithPopup/linkWithRedirect 将 Microsoft 提供方与现有用户相关联。例如,您可以将多个提供方与同一个用户关联,以便用户使用任一提供方服务进行登录。

    Web 版本 9

    import { getAuth, linkWithPopup, OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');
    const auth = getAuth();
    
    linkWithPopup(auth.currentUser, provider)
        .then((result) => {
          // Microsoft credential is linked to the current user.
          // IdP data available in result.additionalUserInfo.profile.
    
          // Get the OAuth access token and ID Token
          const credential = OAuthProvider.credentialFromResult(result);
          const accessToken = credential.accessToken;
          const idToken = credential.idToken;
        })
        .catch((error) => {
          // Handle error.
        });

    Web 版本 8

    var provider = new firebase.auth.OAuthProvider('microsoft.com');
    firebase.auth().currentUser.linkWithPopup(provider)
        .then((result) => {
          // Microsoft credential is linked to the current user.
          // 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((error) => {
          // Handle error.
        });
  6. 上述模式同样适用于 reauthenticateWithPopup/reauthenticateWithRedirect。对于要求用户必须在近期内登录过才能执行的敏感操作,可使用它来检索新的凭据。

    Web 版本 9

    import { getAuth, reauthenticateWithPopup, OAuthProvider } from "firebase/auth";
    
    const provider = new OAuthProvider('microsoft.com');
    const auth = getAuth();
    reauthenticateWithPopup(auth.currentUser, provider)
        .then((result) => {
          // User is re-authenticated with fresh tokens minted and
          // should be able to perform sensitive operations like account
          // deletion and email or password update.
          // IdP data available in result.additionalUserInfo.profile.
    
          // Get the OAuth access token and ID Token
          const credential = OAuthProvider.credentialFromResult(result);
          const accessToken = credential.accessToken;
          const idToken = credential.idToken;
        })
        .catch((error) => {
          // Handle error.
        });

    Web 版本 8

    var provider = new firebase.auth.OAuthProvider('microsoft.com');
    firebase.auth().currentUser.reauthenticateWithPopup(provider)
        .then((result) => {
          // User is re-authenticated with fresh tokens minted and
          // should be able to perform sensitive operations like account
          // deletion and email or password update.
          // 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((error) => {
          // Handle error.
        });

在 Chrome 扩展程序中进行 Firebase 身份验证

如果您是在构建 Chrome 扩展程序应用,则必须添加 Chrome 扩展程序 ID:

  1. Firebase 控制台中打开您的项目。
  2. Authentication 部分中,打开 Sign-in method 页面。
  3. 向“已获授权的网域”列表添加格式如下的 URI:
    chrome-extension://CHROME_EXTENSION_ID

由于 Chrome 扩展程序无法使用 HTTP 重定向,因此只能使用弹出式操作方式(signInWithPopuplinkWithPopupreauthenticateWithPopup)。您应该从后台页面脚本而不是弹出式窗口(浏览器操作)中调用这些方法,因为身份验证的弹出式窗口将取消浏览器操作的弹出式窗口。弹出式操作方式只能在使用 Manifest V2 的扩展程序中使用。较新的 Manifest V3 只允许采用 Service Worker 形式的后台脚本,根本无法执行弹出式操作方式。

在 Chrome 扩展程序的清单文件中,确保将 https://apis.google.com 网址加入 content_security_policy 许可名单中。

后续步骤

在用户首次登录后,系统会创建一个新的用户帐号,并将其与该用户登录时使用的凭据(即用户名和密码、电话号码或者身份验证提供方信息)相关联。此新帐号存储在您的 Firebase 项目中,无论用户采用何种方式登录,您项目中的每个应用都可以使用此帐号来识别用户。

  • 在您的应用中,建议采用在 Auth 对象上设置观察者的方式来了解用户的身份验证状态。然后您可以从 User 对象获取用户的基本个人资料信息。请参阅管理用户

  • 在您的 Firebase Realtime Database 和 Cloud Storage 安全规则中,您可以从 auth 变量获取已登录用户的唯一用户 ID,然后利用此 ID 来控制用户可以访问哪些数据。

您可以将身份验证提供方凭据关联至现有用户帐号,让用户可以使用多个身份验证提供方登录您的应用。

如需将用户退出登录,请调用 signOut

Web 版本 9

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web 版本 8

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});