使用 FirebaseUI 輕鬆將登錄添加到您的 Web 應用

FirebaseUI是一個構建在 Firebase 身份驗證 SDK 之上的庫,它提供了可在您的應用中使用的插入式 UI 流。 FirebaseUI 提供以下好處:

  • 多個提供商- 用於電子郵件/密碼、電子郵件鏈接、電話身份驗證、Google、Facebook、Twitter 和 GitHub 登錄的登錄流程。
  • 帳戶鏈接- 跨身份提供者安全鏈接用戶帳戶的流程。
  • 自定義- 覆蓋 FirebaseUI 的 CSS 樣式以匹配您的應用要求。此外,由於 FirebaseUI 是開源的,您可以分叉該項目並完全根據您的需要對其進行自定義。
  • 一鍵註冊和自動登錄- 與一鍵註冊自動集成,實現快速跨設備登錄。
  • 本地化 UI - 超過 40種語言的國際化。
  • 升級匿名用戶- 通過登錄/註冊升級匿名用戶的能力。有關詳細信息,請訪問升級匿名用戶部分

在你開始之前

  1. 將 Firebase 身份驗證添加到您的 Web 應用程序

  2. 通過以下選項之一包含 FirebaseUI:

    1. 內容分發網絡

      在頁面的 <head> 標記中包含以下腳本和 CSS 文件,位於 Firebase 控制台的初始化代碼段下方:

      <script src="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.js"></script>
      <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.css" />
      
    2. npm 模塊

      使用以下命令通過 npm 安裝 FirebaseUI 及其依賴項:

      $ npm install firebaseui --save
      

      在源文件中require以下模塊:

      var firebase = require('firebase');
      var firebaseui = require('firebaseui');
      
    3. 鮑爾組件

      使用以下命令通過 Bower 安裝 FirebaseUI 及其依賴項:

      $ bower install firebaseui --save
      

      如果您的 HTTP 服務器在bower_components/中提供文件,請在 HTML 中包含所需的文件:

      <script src="bower_components/firebaseui/dist/firebaseui.js"></script>
      <link type="text/css" rel="stylesheet" href="bower_components/firebaseui/dist/firebaseui.css" />
      

初始化 FirebaseUI

導入 SDK 後,初始化 Auth UI。

// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());

設置登錄方法

在您可以使用 Firebase 登錄用戶之前,您必須啟用並配置您想要支持的登錄方法。

電子郵件地址和密碼

  1. Firebase 控制台中,打開身份驗證部分並啟用電子郵件和密碼身份驗證。

  2. 將電子郵件提供商 ID 添加到 FirebaseUI signInOptions列表。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        firebase.auth.EmailAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  3. 可選:可以將EmailAuthProvider配置為要求用戶輸入顯示名稱(默認為true )。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          requireDisplayName: false
        }
      ]
    });
    
  1. Firebase 控制台中,打開身份驗證部分。在登錄方法選項卡上,啟用電子郵件/密碼提供程序。請注意,必須啟用電子郵件/密碼登錄才能使用電子郵件鏈接登錄。

  2. 在同一部分中,啟用電子郵件鏈接(無密碼登錄)登錄方法,然後單擊保存

  3. 將電子郵件提供商 ID 與電子郵件鏈接signInMethod一起添加到 FirebaseUI signInOptions列表中。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          signInMethod: firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
        }
      ],
      // Other config options...
    });
    
  4. 在有條件地呈現登錄 UI 時(與單頁應用程序相關),使用ui.isPendingRedirect()來檢測 URL 是否對應於使用電子郵件鏈接的登錄,並且需要呈現 UI 才能完成登錄。

    // Is there an email link sign-in?
    if (ui.isPendingRedirect()) {
      ui.start('#firebaseui-auth-container', uiConfig);
    }
    // This can also be done via:
    if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
      ui.start('#firebaseui-auth-container', uiConfig);
    }
    
  5. 可選:用於電子郵件鏈接登錄的EmailAuthProvider可以配置為允許或阻止用戶完成跨設備登錄。

    可以定義一個可選的emailLinkSignIn回調來返回發送鏈接時要使用的firebase.auth.ActionCodeSettings配置。這提供了指定如何處理鏈接、自定義動態鏈接、深層鏈接中的附加狀態等的能力。如果未提供,則使用當前 URL 並觸發僅 Web 流。

    FirebaseUI-web 中的電子郵件鏈接登錄與FirebaseUI-AndroidFirebaseUI-iOS兼容,其中從 FirebaseUI-Android 啟動流程的用戶可以打開鏈接並使用 FirebaseUI-web 完成登錄。對於相反的流程也是如此。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          signInMethod: firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD,
          // Allow the user the ability to complete sign-in cross device,
          // including the mobile apps specified in the ActionCodeSettings
          // object below.
          forceSameDevice: false,
          // Used to define the optional firebase.auth.ActionCodeSettings if
          // additional state needs to be passed along request and whether to open
          // the link in a mobile app if it is installed.
          emailLinkSignIn: function() {
            return {
              // Additional state showPromo=1234 can be retrieved from URL on
              // sign-in completion in signInSuccess callback by checking
              // window.location.href.
              url: 'https://www.example.com/completeSignIn?showPromo=1234',
              // Custom FDL domain.
              dynamicLinkDomain: 'example.page.link',
              // Always true for email link sign-in.
              handleCodeInApp: true,
              // Whether to handle link in iOS app if installed.
              iOS: {
                bundleId: 'com.example.ios'
              },
              // Whether to handle link in Android app if opened in an Android
              // device.
              android: {
                packageName: 'com.example.android',
                installApp: true,
                minimumVersion: '12'
              }
            };
          }
        }
      ]
    });
    

OAuth 提供商(Google、Facebook、Twitter 和 GitHub)

  1. Firebase 控制台中,打開身份驗證部分並啟用指定的 OAuth 提供程序登錄。確保還指定了相應的 OAuth 客戶端 ID 和密碼。

  2. 同樣在“身份驗證”部分,確保將呈現登錄頁面的域也添加到授權域列表中。

  3. 將 OAuth 提供者 ID 添加到 FirebaseUI signInOptions列表中。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        // List of OAuth providers supported.
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        firebase.auth.GithubAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  4. 可選:要為每個提供者指定自定義範圍或自定義 OAuth 參數,您可以傳遞一個對象而不僅僅是提供者值:

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID,
          scopes: [
            'https://www.googleapis.com/auth/contacts.readonly'
          ],
          customParameters: {
            // Forces account selection even when one account
            // is available.
            prompt: 'select_account'
          }
        },
        {
          provider: firebase.auth.FacebookAuthProvider.PROVIDER_ID,
          scopes: [
            'public_profile',
            'email',
            'user_likes',
            'user_friends'
          ],
          customParameters: {
            // Forces password re-entry.
            auth_type: 'reauthenticate'
          }
        },
        firebase.auth.TwitterAuthProvider.PROVIDER_ID, // Twitter does not support scopes.
        firebase.auth.EmailAuthProvider.PROVIDER_ID // Other providers don't need to be given as object.
      ]
    });
    

電話號碼

  1. Firebase 控制台中,打開身份驗證部分並啟用電話號碼登錄。

  2. 確保將呈現您的登錄頁面的域也添加到授權域列表中。

  3. 將電話號碼提供商 ID 添加到 FirebaseUI signInOptions列表中。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        firebase.auth.PhoneAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  4. 可選:PhoneAuthProvider 可以使用自定義 reCAPTCHA 參數配置,無論 reCAPTCHA 可見還是不可見(默認為正常)。有關更多詳細信息,請參閱reCAPTCHA API 文檔

    還可以設置在電話號碼輸入中選擇的默認國家/地區。有關代碼的完整列表,請參閱支持的國家代碼列表。如果未指定,電話號碼輸入將默認為美國 (+1)。

    當前支持以下選項。

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
          recaptchaParameters: {
            type: 'image', // 'audio'
            size: 'normal', // 'invisible' or 'compact'
            badge: 'bottomleft' //' bottomright' or 'inline' applies to invisible.
          },
          defaultCountry: 'GB', // Set default country to the United Kingdom (+44).
          // For prefilling the national number, set defaultNationNumber.
          // This will only be observed if only phone Auth provider is used since
          // for multiple providers, the NASCAR screen will always render first
          // with a 'sign in with phone number' button.
          defaultNationalNumber: '1234567890',
          // You can also pass the full phone number string instead of the
          // 'defaultCountry' and 'defaultNationalNumber'. However, in this case,
          // the first country ID that matches the country code will be used to
          // populate the country selector. So for countries that share the same
          // country code, the selected country may not be the expected one.
          // In that case, pass the 'defaultCountry' instead to ensure the exact
          // country is selected. The 'defaultCountry' and 'defaultNationaNumber'
          // will always have higher priority than 'loginHint' which will be ignored
          // in their favor. In this case, the default country will be 'GB' even
          // though 'loginHint' specified the country code as '+1'.
          loginHint: '+11234567890'
        }
      ]
    });
    

登入

要啟動 FirebaseUI 登錄流程,請通過傳遞底層Auth實例來初始化 FirebaseUI 實例。

// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());

定義將呈現 FirebaseUI 登錄小部件的 HTML 元素。

<!-- The surrounding HTML is left untouched by FirebaseUI.
     Your app may use that space for branding, controls and other customizations.-->
<h1>Welcome to My Awesome App</h1>
<div id="firebaseui-auth-container"></div>
<div id="loader">Loading...</div>

指定 FirebaseUI 配置(支持的提供程序和 UI 自定義以及成功回調等)。

var uiConfig = {
  callbacks: {
    signInSuccessWithAuthResult: function(authResult, redirectUrl) {
      // User successfully signed in.
      // Return type determines whether we continue the redirect automatically
      // or whether we leave that to developer to handle.
      return true;
    },
    uiShown: function() {
      // The widget is rendered.
      // Hide the loader.
      document.getElementById('loader').style.display = 'none';
    }
  },
  // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
  signInFlow: 'popup',
  signInSuccessUrl: '<url-to-redirect-to-on-success>',
  signInOptions: [
    // Leave the lines as is for the providers you want to offer your users.
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.TwitterAuthProvider.PROVIDER_ID,
    firebase.auth.GithubAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
    firebase.auth.PhoneAuthProvider.PROVIDER_ID
  ],
  // Terms of service url.
  tosUrl: '<your-tos-url>',
  // Privacy policy url.
  privacyPolicyUrl: '<your-privacy-policy-url>'
};

最後,渲染 FirebaseUI Auth 界面:

// The start method will wait until the DOM is loaded.
ui.start('#firebaseui-auth-container', uiConfig);

升級匿名用戶

啟用匿名用戶升級

當匿名用戶使用永久帳戶登錄或註冊時,您希望確保用戶可以繼續他們在註冊之前所做的事情。為此,只需在配置登錄 UI 時將autoUpgradeAnonymousUsers設置為true (默認情況下禁用此選項)。

處理匿名用戶升級合併衝突

在某些情況下,最初以匿名方式登錄的用戶會嘗試升級到現有 Firebase 用戶。由於現有用戶無法鏈接到另一個現有用戶,因此當發生上述情況時,FirebaseUI 將觸髮帶有錯誤代碼 firebaseui firebaseui/anonymous-upgrade-merge-conflictsignInFailure回調。錯誤對像還將包含永久憑據。應在回調中觸發使用永久憑據登錄以完成登錄。在通過auth.signInWithCredential(error.credential)完成登錄之前,您必須保存匿名用戶的數據並刪除匿名用戶。然後,在登錄完成後,將數據複製回非匿名用戶。下面的示例說明了此流程的工作方式。

// Temp variable to hold the anonymous user data if needed.
var data = null;
// Hold a reference to the anonymous current user.
var anonymousUser = firebase.auth().currentUser;
ui.start('#firebaseui-auth-container', {
  // Whether to upgrade anonymous users should be explicitly provided.
  // The user must already be signed in anonymously before FirebaseUI is
  // rendered.
  autoUpgradeAnonymousUsers: true,
  signInSuccessUrl: '<url-to-redirect-to-on-success>',
  signInOptions: [
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
    firebase.auth.PhoneAuthProvider.PROVIDER_ID
  ],
  callbacks: {
    // signInFailure callback must be provided to handle merge conflicts which
    // occur when an existing credential is linked to an anonymous user.
    signInFailure: function(error) {
      // For merge conflicts, the error.code will be
      // 'firebaseui/anonymous-upgrade-merge-conflict'.
      if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
        return Promise.resolve();
      }
      // The credential the user tried to sign in with.
      var cred = error.credential;
      // Copy data from anonymous user to permanent user and delete anonymous
      // user.
      // ...
      // Finish sign-in after data is copied.
      return firebase.auth().signInWithCredential(cred);
    }
  }
});

下一步

  • 有關使用和自定義 FirebaseUI 的更多信息,請訪問自述文件。
  • 如果您在 FirebaseUI 中發現問題並想報告它,請使用GitHub 問題跟踪器