進階驗證功能

1. 設定

取得原始碼

在本程式碼研究室中,您會從一個即將完成的友善 Chat 範例應用程式開始著手,因此首先需要複製原始碼:

$ git clone https://github.com/firebase/codelab-friendlychat-web --branch security

接著,請移至 security-start 目錄,您將在這些程式碼研究室的其餘部分執行:

$ cd codelab-friendlychat-web/security-start

現在,請安裝依附元件,以便執行程式碼。如果網際網路連線速度較慢,可能需要一兩分鐘的時間:

$ npm install && (cd functions && npm install)

瞭解這個存放區

security-solution/ 目錄包含範例應用程式的完整程式碼。security-start 目錄是您完成程式碼研究室的練習,但缺少驗證實作的幾個重要部分。security-start/security-solution/ 的主要檔案和功能如下:

  • functions/index.js 包含 Cloud Functions 程式碼,您會在其中編寫驗證封鎖函式。
  • public/ - 包含即時通訊應用程式的靜態檔案
  • public/scripts/main.js - 系統會編譯即時通訊應用程式 JS 程式碼 (src/index.js) 的位置
  • src/firebase-config.js - 包含用來初始化即時通訊應用程式的 Firebase 設定物件
  • src/index.js - 您的即時通訊應用程式 JS 程式碼

取得 Firebase CLI

模擬器套件是 Firebase CLI (指令列介面) 的一部分,您可以使用下列指令安裝到機器:

$ npm install -g firebase-tools@latest

使用 webpack 建構 JavaScript,這會在 public/scripts/ 目錄中建立 main.js。

webpack build

接著,請確認您有最新版的 CLI。本程式碼研究室適用於 11.14 以上版本。

$ firebase --version
11.14.2

連結至 Firebase 專案

如果您沒有 Firebase 專案,請在 Firebase 控制台建立新的 Firebase 專案。記下您選擇的專案 ID,後續步驟將會用到。

現在請將這個程式碼連結至 Firebase 專案,首先,請執行下列指令登入 Firebase CLI:

$ firebase login

接著執行下列指令,建立專案別名。將 $YOUR_PROJECT_ID 替換為 Firebase 專案的 ID。

$ firebase use $YOUR_PROJECT_ID

您現在可以執行應用程式了!

2. 執行模擬器

在本節中,您將在本機執行應用程式。這表示可以啟動模擬器套件了。

啟動模擬器

在程式碼研究室的來源目錄中執行下列指令,啟動模擬器:

$ firebase emulators:start

系統會在 http://127.0.0.1:5170 提供您的應用程式,並在您進行變更時持續重建原始碼。您只需要在瀏覽器中強制重新整理 (ctrl-shift-r) 即可看到變更。

輸出內容應如下所示:

i  emulators: Starting emulators: auth, functions, firestore, hosting, storage
✔  functions: Using node@16 from host.
i  firestore: Firestore Emulator logging to firestore-debug.log
✔  firestore: Firestore Emulator UI websocket is running on 9150.
i  hosting[demo-example]: Serving hosting files from: ./public
✔  hosting[demo-example]: Local server: http://127.0.0.1:5170
i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "[...]" for Cloud Functions...
✔  functions: Loaded functions definitions from source: beforecreated.
✔  functions[us-central1-beforecreated]: providers/cloud.auth/eventTypes/user.beforeCreate function initialized (http://127.0.0.1:5011/[...]/us-central1/beforecreated).
i  Running script: npm start
 
> security@1.0.0 start
> webpack --watch --progress
[...]
webpack 5.50.0 compiled with 1 warning in 990 ms

看到「All emulators 準備好」訊息後,就表示應用程式已準備就緒。

3. 實作 MFA

這個存放區已部分實作 MFA。您需要先加入程式碼,先註冊使用者多重驗證,然後提示註冊多重驗證的使用者進行第二重驗證。

在編輯器中開啟 src/index.js 檔案,然後找出 startEnrollMultiFactor() 方法。請加入以下程式碼來設定 reCAPTCHA 驗證器,以防止手機遭到濫用 (reCAPTCHA 驗證器已設為隱藏,使用者不會看到):

async function startEnrollMultiFactor(phoneNumber) {
  const recaptchaVerifier = new RecaptchaVerifier(
    "recaptcha",
    { size: "invisible" },
    getAuth()
  );

接著,請找出 finishEnrollMultiFactor() 方法,並新增下列指令來註冊第二個步驟:

// Completes MFA enrollment once a verification code is obtained.
async function finishEnrollMultiFactor(verificationCode) {
  // Ask user for the verification code. Then:
  const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
  const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
 
  // Complete enrollment.
  await multiFactor(getAuth().currentUser)
    .enroll(multiFactorAssertion)
    .catch(function (error) {
      alert(`Error finishing second factor enrollment. ${error}`);
      throw error;
    });
  verificationId = null;
}

接著,找出 signIn 函式並新增下列控制流程,提示已註冊 MFA 的使用者輸入第二個驗證步驟:

async function signIn() {
  // Sign in Firebase using popup auth and Google as the identity provider.
  var provider = new GoogleAuthProvider();
  await signInWithPopup(getAuth(), provider)
    .then(function (userCredential) {
      // User successfully signed in and is not enrolled with a second factor.
    })
    .catch(function (error) {
      if (error.code == "auth/multi-factor-auth-required") {
        multiFactorResolver = getMultiFactorResolver(getAuth(), error);
        displaySecondFactor(multiFactorResolver.hints);
      } else {
        alert(`Error signing in user. ${error}`);
      }
    });
}

實作的其餘部分 (包括在此叫用的函式) 已完成。如要瞭解這些功能的運作方式,請瀏覽檔案的其他部分。

4. 嘗試在模擬器中使用 MFA 登入

現在來試試 MFA 實作吧!請確保模擬器仍在執行,並前往 localhost:5170 造訪本機代管的應用程式。嘗試登入後,在系統提示您提供 MFA 代碼時,終端機視窗中會顯示 MFA。

模擬器完整支援多因素驗證,因此開發環境可以是完全獨立的開發環境。

若要進一步瞭解如何實作 MFA,請參閱我們的參考文件

5. 建立封鎖函式

有些應用程式僅供特定的使用者群組使用。針對這類情況,建議您建立自訂條件,讓使用者註冊或登入您的應用程式。

此時封鎖函式就提供:建立自訂驗證規定的方法。也就是 Cloud Functions,但與大多數功能不同的是,使用者嘗試註冊或登入時,會同步執行。

如要建立封鎖函式,請在編輯器中開啟 functions/index.js,然後找出註解排除的 beforecreated 函式。

將下列程式碼改成只有網域為 example.com 的使用者可建立帳戶:

exports.beforecreated = beforeUserCreated((event) => {
  const user = event.data;
  // Only users of a specific domain can sign up.
  if (!user.email || !user.email.endsWith("@example.com")) {
    throw new HttpsError("invalid-argument", "Unauthorized email");
  }
});

6. 試用模擬器中的封鎖函式

如要試用封鎖函式,請確認模擬器正在執行,並在 localhost:5170 網頁應用程式中登出。

然後嘗試使用結尾不是 example.com 的電子郵件地址建立帳戶。封鎖函式會導致作業失敗。

現在請使用結尾為 example.com 的電子郵件地址再試一次。你已成功建立帳戶。

透過封鎖函式,您可以設定驗證時需要的任何限制。詳情請參閱參考文件

重點回顧

太好了!您在網頁應用程式中加入多重驗證功能,協助使用者保障帳戶安全,隨後建立了自訂規定,讓使用者使用封鎖功能註冊。你獲得了一張 GIF!

GIF 圖片,呈現辦公室中有人在跳舞