本文檔介紹了在封鎖第三方 cookie 的瀏覽器上使用重定向登入的最佳實務。您必須遵循此處列出的選項之一, signInWithRedirect()
才能在所有瀏覽器中的生產環境中按預期運行。
概述
為了讓您和您的使用者能夠無縫地執行signInWithRedirect()
流程,Firebase 驗證 JavaScript SDK 使用連接到您應用的 Firebase 託管網域的跨來源 iframe。但是,此機制不適用於阻止第三方儲存存取的瀏覽器。
由於要求使用者停用瀏覽器上的儲存分區功能很少是一種選擇,因此您應該根據用例的具體情況,將以下設定選項之一應用於您的應用程式。
- 如果您使用 Firebase Hosting 在
firebaseapp.com
的子網域上託管應用程序,則您不會受到此問題的影響,無需採取任何措施。 - 如果您使用 Firebase Hosting 在自訂網域或
web.app
的子網域上託管應用程序,請使用選項 1 。 - 如果您使用 Firebase 以外的服務託管應用,請使用Option 2 、 Option 3 、 Option 4或Option 5 。
選項 1:更新您的 Firebase 配置以使用自訂網域作為authDomain
如果您使用自訂網域透過 Firebase Hosting 來託管您的應用程式,則可以將 Firebase SDK 設定為使用您的自訂網域作為authDomain
。這可確保您的應用程式和身份驗證 iframe 使用相同的網域,從而防止登入問題。 (如果您不使用 Firebase 託管,則需要使用其他選項。)
若要更新您的 Firebase 設定以使用自訂網域作為驗證網域,請執行下列操作:
配置 Firebase JS SDK 以使用您的自訂網域作為
authDomain
:const firebaseConfig = { apiKey: "<api-key>", authDomain: "<the-domain-that-serves-your-app>", databaseURL: "<database-url>", projectId: "<project-id>", appId: "<app-id>" };
將新的
authDomain
新增至 OAuth 提供者的授權重定向 URI 清單中。如何執行此操作取決於提供者,但一般來說,您可以按照任何提供者(例如Facebook 提供者)中的「開始之前」部分來取得準確說明。更新後的授權 URI 看起來像https://<the-domain-that-serves-your-app>/__/auth/handler
— 結尾的/__/auth/handler
很重要。同樣,如果您使用 SAML 提供程序,請將新的
authDomain
新增至 SAML 斷言消費者服務 (ACS) URL。
選項 2:切換到signInWithPopup()
使用signInWithPopup()
而不是signInWithRedirect()
。應用程式程式碼的其餘部分保持不變,但 UserCredential 物件的擷取方式有所不同。
網路模組化API
// Before
// ==============
signInWithRedirect(auth, new GoogleAuthProvider());
// After the page redirects back
const userCred = await getRedirectResult(auth);
// After
// ==============
const userCred = await signInWithPopup(auth, new GoogleAuthProvider());
Web 命名空間 API
// Before
// ==============
firebase.auth().signInWithRedirect(new firebase.auth.GoogleAuthProvider());
// After the page redirects back
var userCred = await firebase.auth().getRedirectResult();
// After
// ==============
var userCred = await firebase.auth().signInWithPopup(
new firebase.auth.GoogleAuthProvider());
```
彈出視窗登入並不總是適合用戶 - 彈出視窗有時會被裝置或平台阻止,並且行動用戶的流程不太順暢。如果您的應用程式存在使用彈出視窗的問題,則您需要遵循其他選項之一。
選項 3:將身份驗證請求代理到 firebaseapp.com
signInWithRedirect
流程首先從您的應用程式網域重新導向到 firebase 設定中的authDomain
參數中指定的網域(“authDomain
託管重定向到身分提供者的登入幫助程式程式碼,成功後,身分提供者將重定向回應用程式網域。
當身份驗證流程返回您的應用程式網域時,將存取登入幫助程式網域的瀏覽器儲存。此選項和以下選項(自行託管程式碼)消除了跨來源儲存訪問,否則會被瀏覽器阻止。
在應用程式伺服器上設定反向代理,以便將對
https://<app domain>/__/auth/
GET/POST 請求轉送至https://<project>.firebaseapp.com/__/auth/
。確保此轉發對於瀏覽器是透明的;這不能透過 302 重定向來完成。如果您使用 nginx 來服務您的自訂網域,則反向代理程式配置將如下所示:
# reverse proxy for signin-helpers for popup/redirect sign in. location /__/auth { proxy_pass https://<project>.firebaseapp.com; }
請依照選項 1中的步驟更新授權的
redirect_uri
、 ACS URL 和您的authDomain
。重新部署應用程式後,跨網域儲存存取權應該不再發生。
選項 4:在您的網域中自行託管登入說明程式碼
消除跨網域儲存存取的另一種方法是自行託管 Firebase 登入幫助程式程式碼。但是,此方法不適用於 Apple 登入或 SAML。僅當選項 3 中的反向代理設定不可行時才使用此選項。
託管幫助程式程式碼有以下步驟:
透過執行以下命令,從
<project>.firebaseapp.com
位置下載要託管的檔案:mkdir signin_helpers/ && cd signin_helpers wget https://<project>.firebaseapp.com/__/auth/handler wget https://<project>.firebaseapp.com/__/auth/handler.js wget https://<project>.firebaseapp.com/__/auth/experiments.js wget https://<project>.firebaseapp.com/__/auth/iframe wget https://<project>.firebaseapp.com/__/auth/iframe.js
將上述文件託管在您的應用程式網域下。確保您的 Web 伺服器可以回應
https://<app domain>/__/auth/<filename>
。以下是下載和託管文件的範例伺服器實作。我們建議定期下載和同步文件,以確保獲取最新的錯誤修復和功能。
請依照選項 1中的步驟更新授權的
redirect_uri
和您的authDomain
。重新部署應用程式後,跨網域儲存存取權應該不再發生。
選項 5:獨立處理提供者登入
Firebase 驗證 SDK 提供了signInWithPopup()
和signInWithRedirect()
作為封裝複雜邏輯的便利方法,並避免需要涉及另一個SDK。您可以完全避免使用任何一種方法,方法是獨立登入您的提供者,然後使用signInWithCredential()
將提供者的憑證交換為 Firebase 驗證憑證。例如,您可以使用Google Sign In SDK範例程式碼取得 Google 帳戶憑證,然後透過執行下列程式碼實例化新的 Google 憑證:
網路模組化API
// `googleUser` from the onsuccess Google Sign In callback.
// googUser = gapi.auth2.getAuthInstance().currentUser.get();
const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
const result = await signInWithCredential(auth, credential);
Web 命名空間 API
// `googleUser` from the onsuccess Google Sign In callback.
const credential = firebase.auth.GoogleAuthProvider.credential(
googleUser.getAuthResponse().id_token);
const result = await firebase.auth().signInWithCredential(credential);
呼叫signInWithCredential()
後,應用程式的其餘部分的功能與之前相同。
有關取得 Apple 憑證的說明,請參閱此處。