手動建立登入流程

如果要為網頁版或桌面版應用程式執行瀏覽器式登入流程而不使用我們的 SDK(例如在原生桌面版應用程式(如 Windows 8)的網頁檢視中執行登入流程,或者執行完全使用伺服器端程式碼的登入流程),您可以使用瀏覽器重新導向來自行建立登入流程。本指南會帶領您了解登入流程的每個步驟,同時說明如何在不使用我們 SDK 的情況下執行各個步驟:

若要在桌面版應用程式中使用 Facebook 登入,您需要在應用程式中內嵌網頁瀏覽器(有時稱為網頁檢視)來執行登入程序。

檢查登入狀態

使用我們 SDK 的應用程式可運用內置功能來檢查用戶是否已登入。其他所有應用程式都必須建立自己的方式來儲存已登入用戶,以及當該指標不存在時,假設用戶已登出而繼續執行程序。如果用戶已經登出,則您的應用程式應該在適當時機將用戶重新導向至登入對話框,例如當用戶點擊登入按鈕時。

登入用戶

不論用戶是未登入您的應用程式或未登入 Facebook,您都可使用登入對話框來提示用戶來登入兩者。如果用戶尚未登入 Facebook,用戶會先看到登入 Facebook 的提示,然後再移至登入您應用程式的程序。系統將會自動偵測,所以您無需額外做任何動作來啟用此行為。


觸發登入對話框並設定重新導向網址

您的應用程式必須發起端點重新導向,重新導向至顯示登入對話框的端點:

https://www.facebook.com/v19.0/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &state={state-param}

此端點的必要參數如下:

  • client_id,位於應用程式管理中心內的應用程式編號。
  • redirect_uri,您想將登入用戶重新導向到的網址,此網址會擷取登入對話框的回應。如果您是在桌面版應用程式內的網頁檢視中使用此網址,則必須設為 https://www.facebook.com/connect/login_success.html。您可以在應用程式管理中心確認已為您的應用程式設定此網址。在應用程式管理中心左側導覽選單中的產品下方,依序點擊 Facebook 登入設定。在用戶端 OAuth 設定部分中,驗證有效的 OAuth 重新導向 URI
  • state,由您應用程式所建立的字串值,用於維持要求和回呼之間的狀態。此參數應用於防範跨網站偽造要求,且會在重新導向 URI 中按照原狀傳回給您。

舉例來說,如果您的登入要求如下所示:

https://www.facebook.com/v19.0/dialog/oauth?
  client_id={app-id}
  &redirect_uri={"https://www.domain.com/login"}
  &state={"{st=state123abc,ds=123456789}"}

那麼系統便會使用下列項目呼叫您的重新導向 URI:

https://www.domain.com/login?state="{st=state123abc,ds=123456789}"
    

此端點亦可選用如下參數:

  • response_type,當重新導向返回應用程式時,決定是在網址參數中還是片段中內含回應資料。請參閱確認身分一節,選擇您應用程式應使用的類型。此類型可為以下項目其中之一:
    • code。回應資料會以網址參數的方式內含,且包含 code 參數(每次登入要求的不重複加密字串)。這是未指定此參數時的預設行為,這在您的伺服器負責處理憑證的情況下最為有用。
    • token,回應資料會以網址片段的方式內含,且包含存取憑證。桌面版應用程式必須在 response_type 中使用此設定,這在用戶端負責處理憑證的情況下最為有用。
    • code%20token。回應資料會以網址片段的方式內含,且包含存取憑證和 code 參數。
    • granted_scopes,傳回用戶在登入時授予應用程式的所有權限,以逗號分隔清單表示。此資料可與其他 response_type 值結合,當與 token 結合時,回應資料會以網址片段的方式內含,否則會以網址參數的方式內含。
  • scope,向使用您應用程式的用戶所要求的各項權限,以逗號或空格分隔清單表示。
如果是 Windows 8 應用程式

如果是為 Windows 應用程式建立登入流程,您可以使用封裝安全識別資料作為您的 redirect_uri。透過呼叫 WebAuthenticationBroker.AuthenticateAsync 並使用登入對話框端點作為 requestUri,以此觸發登入對話框。以下是使用 JavaScript 的範例:

var requestUri = new Windows.Foundation.Uri(
  "https://www.facebook.com/v19.0/dialog/oauth?
    client_id={app-id}
    &display=popup
    &response_type=token
    &redirect_uri=ms-app://{package-security-identifier}");

Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
  options,
  requestUri)
  .done(function (result) {
    // Handle the response from the Login Dialog
  }
);

以上範例在成功時會將控制流程和存取憑證傳回您的應用程式,在失敗時則會將控制流程和錯誤傳回您的應用程式。

處理登入對話框回應

在登入流程中的這個階段,用戶會看到登入對話框,並且可選擇取消或讓應用程式存取其資料。

如果使用應用程式的用戶在登入對話框上選擇「確定」,就會授予對其公開個人檔案和朋友清單的存取權,以及您應用程式要求的其他任何權限

不論何種情況,瀏覽器都會回到應用程式,並且內含回應資料,以表示用戶是否已連結或取消。如果應用程式使用上述的重新導向方法,您應用程式將回到的 redirect_uri 會附加網址參數或片段(視乎所選的 response_type),您必須擷取此資料。

因為網頁版應用程式可能使用的程式碼語言有各式各樣的組合,本指南並未提供具體範例。不過,大部分的現代語言都具備網址剖析的功能,方式如下:

用戶端 JavaScript 可擷取網址片段(例如 jQuery BBQ),而用戶端和伺服器端程式碼均可擷取網址參數(例如 PHP 的 $_GETjQuery BBQ 的 jQuery.deparamNode.js 的 querystring.parsePython 的 urlparse)。Microsoft 提供為 Windows 8 應用程式而設的指南和程式碼範例,講解如何連結「網上供應商」(就本例而言,此供應商為 Facebook)。

使用桌面版應用程式來登入時,Facebook 會將用戶重新導向上述的 redirect_uri,並將存取憑證連同其他一些中繼資料(如憑證到期時間)置於 URI 片段中:

https://www.facebook.com/connect/login_success.html#
    access_token=ACCESS_TOKEN...

應用程式需要偵測此重新導向,接著根據您所用的作業系統和開發架構使用其提供的機制,從 URI 讀取出存取憑證。然後,您就可以直接跳至檢查存取憑證的步驟。


已取消的登入

如果使用您應用程式的用戶不接受登入對話框而點擊「取消」,就會被重新導向至以下網址:

YOUR_REDIRECT_URI?
 error_reason=user_denied
 &error=access_denied
 &error_description=Permissions+error.

如需進一步了解用戶拒絕登入時應用程式應如何處理,請參閱處理欠缺的權限

確認身分

因為在此重新導向流程當中,牽涉到從登入對話框將瀏覽器重新導向至您應用程式中的網址,所以流量可能會透過組成的片段或參數來直接存取此網址。如果您的應用程式假設這些都是有效參數,就可能將組成的資料用於潛在惡意目的。因此,應用程式在為用戶產生存取憑證前,應該確認使用應用程式的用戶和回應資料所針對的用戶是同一個人。視乎上述所接收到的 response_type,具體確認身分方式將有所不同:

  • 當接收到 code 時,需要使用端點來將其換取為存取憑證。因為當中牽涉到您的應用程式密鑰,所以這需要是伺服器對伺服器的呼叫。(您的應用程式密鑰絕不應出現在用戶端程式碼中。)
  • 當接收到 token 時,需要加以驗證憑證。您應該向檢查端點執行 API 呼叫,此呼叫會顯示憑證是為誰產生和由哪個應用程式產生。因為此 API 呼叫需要使用應用程式存取憑證,所以切勿從用戶端執行此呼叫,而是應該從可以安全儲存應用程式密鑰的伺服器上執行此呼叫。
  • 當同時接收到 codetoken 時,以上兩個步驟都應該執行。

請注意:您也可以產生您自己的 state 參數,然後用於您的登入要求以提供 CSRF 保護。

交換程式碼以取得存取憑證

若要取得存取憑證,請向以下的 OAuth 端點執行 HTTP GET 要求:

GET https://graph.facebook.com/v19.0/oauth/access_token?
   client_id={app-id}
   &redirect_uri={redirect-uri}
   &client_secret={app-secret}
   &code={code-parameter}

此端點的必要參數如下:

  • client_id,您的應用程式編號
  • redirect_uri,此為必要引數,且必須與啟動 OAuth 登入程序時所用的原先 request_uri 相同。
  • client_secret,您顯示在應用程式管理中心上的不重複應用程式密鑰。此應用程式密鑰絕不應內含於用戶端程式碼或可反編譯的二進位檔案中。此應用程式密鑰必須維持絕對機密,這一點極為重要,因為這是確保您應用程式及其所有用戶安全的核心。
  • code。從上述登入對話框重新導向流程接收到的參數。

注意:自 2.3 版開始,此端點將傳回合適的 JSON 回應。如果您的呼叫沒有指定版本,系統預設將使用最舊的可用版本。

回應

從此端點接收到的回應會以 JSON 格式傳回,而且成功時將如下所示:

{
  "access_token": {access-token}, 
  "token_type": {type},
  "expires_in":  {seconds-til-expiration}
}

不成功時,您會收到說明情況的錯誤訊息。

檢查存取憑證

不論您的應用程式是否使用 codetoken 作為登入對話框的 response_type,都會接收到存取憑證。您可使用 Graph API 端點來為這些憑證執行自動檢查:

GET graph.facebook.com/debug_token?
     input_token={token-to-inspect}
     &access_token={app-token-or-admin-token}

此端點採用下列參數:

  • input_token,您要檢查的憑證。
  • access_token應用程式存取憑證或應用程式開發人員的存取憑證。

API 呼叫的回應為 JSON 陣列,當中包含與所檢查的憑證相關的資料。例如:

{
    "data": {
        "app_id": 138483919580948, 
        "type": "USER",
        "application": "Social Cafe", 
        "expires_at": 1352419328, 
        "is_valid": true, 
        "issued_at": 1347235328, 
        "metadata": {
            "sso": "iphone-safari"
        }, 
        "scopes": [
            "email", 
            "publish_actions"
        ], 
        "user_id": "1207059"
    }
}

app_iduser_id 欄位可協助您的應用程式驗證存取憑證是否對於用戶以及您的應用程式都有效。如需其他欄位的完整說明,請參閱取得存取憑證相關資訊的指南

檢查權限

您可呼叫 /me/permissions 關係連線,以檢索特定用戶已授予或拒絕的權限之清單。您的應用程式可使用此方式來檢查哪些要求的權限無法用於特定用戶。

重新要求被拒權限

Facebook 登入可讓用戶拒絕與您的應用程式分享一些權限。登入對話框會包含類似以下的畫面:

public_profile 權限任何時候一律均為必要,而且會因無法停用而呈灰調。

不過,如果用戶在此範例中取消勾選 user_likes(讚好的內容),則當您檢查 /me/permissions 以找出哪些權限已獲授予時,結果如下:

{
  "data":
    [
      {
        "permission":"public_profile",
        "status":"granted"
      },
      {
        "permission":"user_likes",
        "status":"declined"
      }
    ]
}

請注意,user_likes 會是已被拒絕而非獲授予。

您可以再一次要求用戶向您的應用程式授予其曾拒絕的權限。您應該顯示說明畫面,向用戶解釋為何其應該向您授予權限,然後重新要求權限。但是,如果您如先前一樣發起登入對話框,系統並不會要求該權限。

這是因為用戶一旦拒絕授予某權限,除非您明確告知登入對話框您正重新要求被拒權限,否則對話框不會重新要求有關權限。

您可以向自己的登入對話框網址加入 auth_type=rerequest 參數,從而執行此操作:

https://www.facebook.com/v19.0/dialog/oauth?
    client_id={app-id}
    &redirect_uri={redirect-uri}
    &auth_type=rerequest
    scope=email
   

使用此參數時,登入對話框會重新要求被拒權限。

儲存存取憑證和登入狀態

在流程中的這個階段,您的用戶已通過驗證並登入。您的應用程式現在可以代表用戶發出 API 呼叫。進行這個動作前,應用程式應該先儲存其用戶的存取憑證和登入狀態。

儲存存取憑證

您的應用程式從上一個步驟接收到存取憑證後,應該將其儲存,以供應用程式任何部分在應用程式執行 API 呼叫時使用。此部分並無明確程序,不過一般而言,如果您建立的是網頁版應用程式,最好是將憑證加入為連線階段變數,以便將該瀏覽器連線階段與特定用戶建立關聯以作識別;如果建立的是原生桌面版或流動應用程式,則應使用您應用程式可用的資料存放區。而且,應用程式在儲存憑證時應該連同 user_id 一起儲存到資料庫,以供識別。

請參閱我們在存取憑證文件中有關存取憑證大小的備註

追蹤登入狀態

同樣地,您的應用程式應該儲存用戶的登入狀態,這有助免卻再次呼叫登入對話框的程序。不論您選擇使用的程序為何,都應修改登入狀態檢查來負責處理。

登出用戶

您可透過復原先前新增的任何登入狀態指標來將用戶登出您的應用程式,例如刪除表示用戶登入的連線階段。您還應該一併移除儲存的存取憑證。

將用戶登出有別於撤銷登入權限(移除先前授予的驗證),後者可分開獨立執行。因此,您應將應用程式建為不會自動將已登出的用戶強制回到登入對話框。

偵測用戶是否解除安裝應用程式

用戶無需與應用程式本身互動,即可透過 Facebook.com 解除安裝應用程式。為了協助應用程式偵測這類事件的發生,我們允許應用程式提供一個取消授權回呼網址,此網址在每次此事件發生時都會 ping。

您可以透過應用程式管理中心啟用取消授權回呼。

回覆用戶資料刪除要求

用戶可以要求應用程式刪除所有從 Facebook 接收到與其相關的資料。如要回應這些要求,請參閱資料刪除要求回呼