本文檔介紹了在阻止第三方 cookie 的瀏覽器上使用重定向登錄的最佳做法。您必須遵循此處列出的選項之一,以便signInWithRedirect()
在所有瀏覽器的生產環境中按預期運行。
概述
為了讓您和您的用戶無縫地使用signInWithRedirect()
流程,Firebase 身份驗證 JavaScript SDK 使用連接到您應用的 Firebase 託管域的跨源 iframe。但是,此機制不適用於阻止第三方存儲訪問的瀏覽器。
因為要求您的用戶在瀏覽器上禁用存儲分區功能很少是一種選擇,所以您應該根據您的用例的具體情況,將以下設置選項之一應用於您的應用程序。
- 如果您使用 Firebase 託管在
firebaseapp.com
的子域上託管您的應用,則您不會受此問題影響,也無需採取任何措施。 - 如果您使用 Firebase 託管在自定義域或
web.app
的子域上託管您的應用,請使用選項 1 。 - 如果您使用 Firebase 以外的服務託管您的應用,請使用Option 2 、 Option 3 、 Option 4或Option 5 。
選項 1:更新您的 Firebase 配置以使用您的自定義域作為您的authDomain
如果您使用自定義域通過 Firebase 託管託管您的應用,則可以配置 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 Authentication 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 憑據的說明在此處。