影片

在 2015 年 F8 大會,Jonathan Gross 和 Brent Dorman 提出一些方法來協助您提升整合的「Facebook 登入」安全性。

安全性檢查清單

以下會列出使用「Facebook 登入」的應用程式一律必須執行的基本必要步驟。您可視需要為應用程式加入其他功能;請您持續思考如何能更有效的保障應用程式的安全,有安全疑慮的應用程式將失去廣告受眾的信賴,最終將流失大量用戶。

不要在用戶端或可反編譯的程式碼中加入您的應用程式密鑰

以您的應用程式密鑰簽署所有伺服器對伺服器的圖形 API 呼叫

在用戶端上使用不重複的短期權杖

請勿相信您應用程式使用的存取權杖真的是由您的應用程式所產生

使用登入對話方塊時一律使用 state 參數

盡可能使用官方 SDK 登入

鎖定您的 Facebook 應用程式設定,從中縮小應用程式可能遭攻擊的區域

使用 HTTPS

應用程式密鑰

應用程式密鑰可用在某些登入流程來產生存取權杖,而且密鑰本身是用於確保您的應用程式僅限信賴的用戶使用。密鑰可用於輕鬆建立應用程式存取權杖,而應用程式存取權杖可代表這個應用程式的任何用戶提出 API 要求,因此可保護應用程式密鑰不遭人盜用至關重要。

因此,請絕對不要在任何程式碼中,加入應用程式密鑰或應用程式存取權杖。

建議您一律直接從您的應用程式伺服器使用應用程式存取權杖,以保障應用程式安全無虞。如果是原生應用程式,建議您讓應用程式與您自己的伺服器溝通,接著再透過這台伺服器使用應用程式存取權杖,向 Facebook 提出 API 要求。基於上述原因,如果在應用程式主控板的進階設定中,您的「應用程式類型」是設為 Native/Desktop,我們會假設您原生應用程式的二進位檔中含有應用程式密鑰或應用程式存取權杖,並拒絕繼續進行由應用程式存取權杖簽署的呼叫。此 API 接著會顯示沒有提供存取權杖。

使用 appsecret_proof 的安全伺服器端呼叫

您可以要求向 Facebook API 的伺服器對伺服器呼叫以 appsecret_proof 參數簽署,進而減少遭遇惡意軟體和濫發垃圾郵件者的風險。應用程式密鑰證明是存取權杖的 sha256 雜湊值,使用應用程式密鑰當作產生雜湊值的密鑰。您可以在應用程式主控板的「設定」>「基本」中找到應用程式密鑰。

產生證明

下列程式碼範例是呼叫以 PHP 所呈現的樣子:

$appsecret_proof= hash_hmac('sha256', $access_token.'|'.time(), $app_secret); 

有些作業系統和程式設計語言會傳回浮點數值的時間戳記。請務必先轉換成整數值,再計算應用程式密鑰證明。有些程式設計語言會將雜湊建立成摘要物件。請務必以十六進位物件來表示雜湊。

新增證明

將結果當作 appsecret_proof 參數加入,並將 appsecret_time 設定為在對每個發出的呼叫進行應用程式密鑰雜湊處理時使用的時間戳記:

curl \
  -F 'access_token=ACCESS-TOKEN' \
  -F 'appsecret_proof=APP-SECRET-PROOF' \
  -F 'appsecret_time=APP-SECRET-TIME' \
  -F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/accounts"}]' \
  https://graph.facebook.com

加上時間戳記的應用程式密鑰證明會在 5 分鐘後視為過期,所以建議您在發出每個圖形 API 呼叫時,各產生新的內嵌證明。

要求證明

在「應用程式主控板」的「設定」>「進階」區塊中,在「安全」區塊中啟用「需要應用程式密鑰」。啟用此設定後,我們將只允許包含 appsecret_proof 的 API 呼叫。

使用短期權杖和程式碼流程的安全用戶端呼叫

如果使用某些設定,應用程式會在多個用戶端之間重複使用長期權杖,但請不要這樣做。請改用從程式碼流程產生的短期權杖,如同我們的存取權杖文件所述。

權杖劫持

若要瞭解權杖為何遭到劫持,您可以想像有個要進行 API 呼叫的原生 iOS 應用程式,但這個應用程式沒有直接這樣做,而是和相同應用程式所擁有的伺服器溝通,並傳遞使用這個 iOS SDK 所產生的權杖給這台伺服器,而伺服器之後可能會使用這個權杖來進行 API 呼叫。

這台伺服器用來接收權杖的端點可能被盜用,因此其他用戶可能將完全不同之應用程式的存取權杖傳遞給這台伺服器。這顯然不安全,但還有一種方法可以避免這種情況,也就是永遠不應假設存取權杖來自使用這些存取權杖的應用程式,請改用偵錯端點檢查這些存取權杖。

定期檢查存取權杖有效性

如果您未使用 Facebook SDK,請定期檢查存取權杖是否有效。雖然存取權杖具有排定的到期日,但基於安全理由,權杖可能會提前過期。如果您未在應用程式中使用 Facebook SDK,請務必經常(至少每日)手動執行權杖有效性檢查,以確保應用程式使用的權杖不會因安全理由而提前過期。

State 參數

如果您在網站中使用 Facebook 登入對話方塊state 參數這個不重複字串可保護您的應用程式不受到跨網站偽造要求攻擊。

啟用 Strict 模式

Strict 模式可藉由避免滋事者劫持您的重新導向,進而保護應用程式的安全。所有應用程式必須啟用 Strict 模式。

在應用程式主控板開啟 Strict 模式前,請於「Facebook 登入」設定執行下列動作,以確保您目前的重新導向流量仍可正常運作:

  • 如果應用程式使用動態重新導向 URI,請使用 state 參數,將動態資訊傳回至少數的重新導向 URI。接著將這些有限的重新導向 URI 新增到有效的 OAuth 重新導向 URI 清單。

  • 若應用程式包含有限的重新導向 URI,請將其新增到有效的 OAuth 重新導向 URI 清單。

  • 若應用程式僅使用 Facebook JavaScript SDK,則重新導向流量已受到保護,無需再採取其他行動。

完成上述動作後,請務必啟用 Strict 模式。

Strict 模式的運作方式

Strict 模式會從您有效的 OAuth 重新導向 URI 清單進行精確的比對,防止您的重新導向 URI 遭到劫持。例如,若清單包含 www.example.com,則 Strict 模式不會允許 www.example.com/token 作為有效的重新導向。這個模式也不會允許任何不存在於有效的 OAuth 重新導向 URI 清單中的額外查詢參數。

使用 HTTPS

使用具有加密功能的 HTTPS 作為網際網路通訊協定,而非 HTTP。HTTPS 會維護傳送資料的隱私,保護其不受竊聽攻擊。此外,也能保護資料在傳送過程中不遭到置入廣告或惡意程式碼的竄改。

在 2018 年 10 月 6 日,所有應用程式都必須使用 HTTPS。

啟用「Facebook 登入」的 JavaScript SDK

在您將 Login with JavaScript SDK(使用 JavaScript SDK 登入)的切換開關設定為「是」,以告知使用 JavaScript SDK 用於登入功能時,代管 SDK 的網頁網域必須與 JavaScript SDK 允許網域的其中一個項目相符。這樣可確保存取權杖只會傳回授權網域的回呼。透過 Facebook JavaScript SDK 的授權動作僅支援 https 網頁。

對於到 2021 年 8 月 10 日止建立的現有 JSSDK 整合,此清單將會根據目前使用量回填數值,無需再採取其他行動。

於 2021 年 8 月 10 日之後建立的新整合,您必須在此清單中新增數值。

如果發現您應用程式的 JSSDK 網域欄位含有 *. 開頭的網址,請以絕對網域網址取代,以增加安全性。

重新導向 URI 檢查如何運作

有心人士在登入要求中提供未授權的 redirect_uri 參數時,便會發生開放式重新導向攻擊,可能會導致像存取權杖這樣的敏感資訊,透過重新導向 URI 的查詢字串或片段外洩。

對於自訂網站整合,您必須在應用程式設定中提供授權的重新導向 URI 以防範這類攻擊。滿足登入要求後,系統將會根據清單項目檢查 redirect_uri 參數。完整 URI 必須完全符合,包含所有參數均是如此;選用 state 參數除外,因為其數值會被忽略。

應用程式內瀏覽器和 JavaScript SDK

JavaScript SDK 通常仰賴彈出視窗和回呼來完成登入,但是對於某些禁止彈出視窗的應用程式內瀏覽器,這個動作便會失敗。每當這種情況發生時,SDK 將會自動嘗試使用存取權杖重新導向至發生此情況的網頁。如果該網頁的完整 URI 列於有效的 OAuth 重新導向 URI,才能夠安全地重新導向。

如果應用程式內瀏覽器情況對您的網站應用程式來說非常重要,您應在「Allowed Domains(允許的網域)」中加入登入頁面的網域,並在「Valid OAuth Redirect URIs(有效的 OAuth 重新導向 URI)」中新增完整的 URI(包含路徑和查詢參數)。如果您的應用程式可從多個不同版本的 URI 登入,可以手動指定 fallback_redirect_uri 做為 FB.login() 呼叫中的選項,如此一來您只需要在「Valid OAuth Redirect URIs(有效的 OAuth 重新導向 URI)」清單中新增一個項目。

鎖定 Facebook 應用程式設定

啟用及/或停用應用程式未使用的所有驗證流程,以便盡可能縮小可能遭攻擊的區域。

  • 在用戶端使用程式碼產生的短期存取權杖,而非用戶端產生的權杖或伺服器提供的長期權杖。程式碼產生的短期存取權杖流程要求應用程式伺服器必須以權杖來交換程式碼,這樣做會比在瀏覽器中取得權杖還來得安全。應用程式應盡可能優先使用這個流程,這樣才會更加安全;如果應用程式只啟用這個流程,在用戶電腦上執行的惡意軟體就無法取得並濫用存取權杖。請參閱存取權杖文件瞭解詳情。

  • 如果您的應用程式未使用用戶端 OAuth 登入,請將其停用。用戶端 OAuth 登入是使用 OAuth 用戶端權杖流程的全域開關。如果您的應用程式未使用任何包含 Facebook 登入 SDK 的用戶端 OAuth 流程,請停用此流程。但請注意,如果停用用戶端 OAuth 登入,您便無法要求存取權杖的權限。這項設定位於「應用程式主控板」的「產品」>「Facebook 登入」>「設定」區塊中。

  • 請停用網路 OAuth 流程或指定重新導向許可清單。網路 OAuth 登入設定可啟用任何使用 Facebook 網頁版登入對話方塊的 OAuth 用戶端權杖流程,以便將權杖傳回到您自己的網站。這項設定位於「應用程式主控板」的「產品」>「Facebook 登入」>「設定」區塊中。如果您沒有要建置自訂網頁版登入流程,或在網路上使用 Facebook 登入 SDK,請停用這項設定。

  • 強制使用 HTTPS。這項設定要求 OAuth 重新導向以使用 HTTPS,以及所有會回傳或需要只在 HTTPS 頁面出現的存取權杖的 Facebook JavaScript SDK 呼叫。自 2018 年 3 月起,所有新建立的應用程式皆預設為開啟這項設定;您必須在 2018 年 10 月 6 日前移轉所有既有應用程式,以確保這些應用程式只使用 HTTPS 網址。大多數主流雲端應用程式主機都能免費為您的應用程式自動設定 TLS 憑證。如果您在應用程式中實作自我裝載,或代管服務預設為不提供 HTTPS,可以從 Let's Encrypt 取得您網域的免費憑證。

  • 如果您的應用程式未使用嵌入的瀏覽器 OAuth 流程,請將其停用。有些桌面和行動原生應用程式會在嵌入的網頁檢視中執行 OAuth 用戶端流程,藉此驗證用戶。如果您的應用程式並未執行此流程,請在「應用程式主控板」的「產品」>「Facebook 登入」>「設定」區塊中停用這項設定。

  • 如果您的應用程式未使用行動單一登入流程,請將其停用。如果您的應用程式未使用 iOS 或 Android 登入,請在「設定」>「基本」的「iOS」和「Android」區塊中停用「單一登入」設定。

應用程式主控板包含許多其他的設定,可讓開發人員用來關閉可能遭受攻擊的區域,避免發生相關安全性問題:

  • 「基本」>「應用程式密鑰」:如果您的應用程式密鑰曾遭人盜用,您可以在這裡重設應用程式密鑰。
  • 「基本」>「應用程式網域」:請用這項設定來鎖定代表您的應用程式執行「Facebook 登入」的網域和子網域。
  • 「進階」>「應用程式類型」:當您建立行動或桌面原生應用程式,且將應用程式密鑰包含在內時,請將這個選項設定為 Native/Desktop,以保護您的應用程式免於反編譯和應用程式密鑰遭竊。
  • 「進階」>「伺服器 IP 許可清單」:可指定 IP 位址清單,允許從這些 IP 位址使用您的應用程式密鑰進行圖形 API 呼叫。從其他 IP 位址使用您的應用程式密鑰進行的圖形 API 呼叫都將失敗。以用戶存取權杖進行的呼叫不受這項設定影響。
  • 「進階」>「更新設定 IP 許可清單」:鎖定 IP 位址,允許來自這些 IP 位址的用戶調整特定範圍的應用程式設定。在 IP 許可清單中加入住家寬頻時務必謹慎。如果您的 IP 位址改變,您將無法再編輯您的應用程式設定。
  • 「進階」>「更新通知電子郵件」:每當應用程式主控板中有任何應用程式設定出現變更,就會寄送相關通知到電子郵件地址。
  • 「進階」>「串流貼文網址安全」:如果選擇這個選項,您的應用程式將會停止發佈不會指回自己所擁有網域的任何網址。這麼做不一定能保障串流貼文網址的安全;如果您確定應用程式會發佈其他網站連結,更無需多此一舉。