# Facebook 登入
###### tags: `facebook` `login` `developer`
**Facebook Login** 用於兩種情境:**驗證**和**要求權限**以存取用戶的資料。**Facebook Login** 可以只應用於驗證,或是同時應用於驗證與資料存取。
不需要提交應用程式審查即可向用戶要求兩項[權限](https://developers.facebook.com/docs/facebook-login/permissions):
* [`public_profile`](https://developers.facebook.com/docs/facebook-login/permissions#reference-default_fields)
用戶公開個人檔案某些部分下的子集。
* `id`:The ID of this person's user account. This ID is unique to each app and cannot be used across different apps.<sub>(應用程式範圍編號)</sub>
* `first_name`:The person's first name
* `last_name`:The person's last name
* `middle_name`:The person's middle name
* `name`:The person's full name
* `name_format`:The person's name formatted to correctly handle Chinese, Japanese, or Korean ordering
* `picture`:The person's profile picture
* `short_name`:Shortened, locale-aware name for the person
* [`email`](https://developers.facebook.com/docs/facebook-login/permissions#reference-email)
用戶主要電子郵件地址。
> 即使要求[`email`](https://developers.facebook.com/docs/facebook-login/permissions#reference-email)[權限](https://developers.facebook.com/docs/facebook-login/permissions)亦不保證會取得電子郵件地址。例如用戶使用電話號碼而非電子郵件地址來註冊 Facebook,則電子郵件欄位可能空白。
若需要求其它任何[權限](https://developers.facebook.com/docs/facebook-login/permissions)則應用程式必須事先送交進行審查,使用 Facebook 登入應用程式的用戶才能在登入對話方塊中看到這些要求的[權限](https://developers.facebook.com/docs/facebook-login/permissions)。為了協助開發 Facebook Login 體驗,在應用程式主控板的**角色**區塊中列出的所有用戶不需經由 Facebook 批准即可授予任何有效的[權限](https://developers.facebook.com/docs/facebook-login/permissions)。
Facebook 應用程式提供一項機制,讓用戶能夠要求應用程式刪除應用程式透過 Facebook 取得的用戶個人資料,用戶可以透過這項機制控管自己的資料。若要回應此類要求,請實作[資料刪除回呼](https://developers.facebook.com/docs/apps/delete-data)。
## 整合 Facebook Login 至網頁應用程式
### 重新導向
Enter the app's redirect URL in the **Valid OAuth Redirect URIs** field for successful authorization.

### 網頁應用程式載入時的第一步
透過呼叫`FB.getLoginStatus()`獲取登入狀態以確認用戶是否已登入到網頁應用程式,然後 Facebook 會呼叫 callback function 並回傳結果。
```
FB.getLoginStatus(function(response) {
statusChangeCallback(response);
});
```
回應結果示例:
```
{
"status": "connected",
"authResponse": {
"accessToken": "{access-token}",
"expiresIn": "{unix-timestamp}",
"reauthorize_required_in": "{seconds-until-token-expires}",
"signedRequest": "{signed-parameter}",
"userID": "{user-id}"
}
}
```
`status`反映了用戶的登入狀態:
| 列舉值 | 說明 |
| - | - |
| `connected` | 該用戶已登入 Facebook 並也已登入網頁應用程式。 |
| `not_authorized` | 該用戶已登入 Facebook 但未登入網頁應用程式。 |
| `unknown` | 該用戶未登入 Facebook 或之前呼叫過`FB.logout()`,由於無法連接到 Facebook,因此不知道是否已登入網頁應用程式。 |
若`status`為`connected`還會回傳`authResponse`物件:
| 鍵 | 型態 | 值 |
| - | - | - |
| `accessToken` | 字串 | 代表用戶使用網頁應用程式的**存取權杖**<sub>(access token)</sub>。 |
| `data_access_expiration_time` | 整數 | UNIX 時戳<sub>(精準度:秒)</sub>。 |
| `expiresIn` | 整數 | **存取權杖**<sub>(access token)</sub>失效的 UNIX 時戳,過期後此用戶得重新登入。 |
| `graphDomain` | 字串 | `facebook` |
| `reauthorize_required_in` | 整數 | 登入逾期剩下的秒數,到期後此用戶得重新登入。 |
| `signedRequest` | 字串 | A signed parameter that contains information about the person using your webpage. |
| `userID` | 字串 | 使用網頁應用程式的用戶的 ID。 |
### 使用戶登入
採用下列其中一種方式讓用戶登入。
#### 登入按鈕<sub>(Facebook Login Button)</sub>
1. 使用[外掛程式配置器](https://developers.facebook.com/docs/facebook-login/web/login-button#-------)配置**登入按鈕**並取得程式碼。

**登入按鈕**可調整的設定:
| 鍵 | `<DIV/>`屬性 | 說明 | 值 |
| - | - | - | - |
| `auto_logout_link` | `data-auto-logout-link` | 用戶登入後按鈕會顯示為**登出**按鈕 | **`false`**<sub>(預設)</sub>、`true` |
| `?` | `data-button-type` | ? | `continue_with` |
| `default_audience` | `data-default-audience` | 在要求寫入[權限](https://developers.facebook.com/docs/facebook-login/permissions)時預設的分享對象 | **`friends`**<sub>(預設)</sub>、`everyone`、`only_me` |
| `?` | `data-layout` | ? | `rounded` |
| `onlogin` | `data-onlogin` | 登入程序完成時需觸發(呼叫)的 JavaScript 函式 | JavaScript function |
| `scope` | `data-scope` | 登入期間要求的[權限](https://developers.facebook.com/docs/facebook-login/permissions)清單 | `public_profile`<sub>(預設)</sub>或以逗號分隔的[權限](https://developers.facebook.com/docs/facebook-login/permissions)清單 |
| `size` | `data-size` | 按鈕尺寸 | **`small`**<sub>(預設)</sub>、`medium`、`large`;詳見下表。 |
| `?` | `data-use-continue-as` | ? | `true` |
##### 按鈕大小
| 列舉值 | 高<sub>(像素)</sub> | 寬<sub>(像素)</sub> | 自訂寬度 |
| - | - | - | - |
| `small` | 20 | 200 | 否 |
| `medium` | 28 | 200~320 | 可 |
| `large` | 40 | 240~400 | 可 |
> 若大小超過上限,按鈕會預設為寬度上限。
上述這個方式適合**快速登入**,但根據[最佳作法](https://developers.facebook.com/docs/facebook-login/best-practices#onlyask)的建議:
> 只要求您需要的[權限](https://developers.facebook.com/docs/facebook-login/permissions)。要求的[權限](https://developers.facebook.com/docs/facebook-login/permissions)越少,用戶越容易放心授權。據我們所知,要求的[權限](https://developers.facebook.com/docs/facebook-login/permissions)越少,通常轉換率就越高。在用戶有機會嘗試您的應用程式之後,您便可以要求其它[權限](https://developers.facebook.com/docs/facebook-login/permissions)。
> 只有用戶嘗試在應用程式內完成某個需要特定[權限](https://developers.facebook.com/docs/facebook-login/permissions)的動作時,您才應該觸發[權限](https://developers.facebook.com/docs/facebook-login/permissions)要求。
此時就該使用**登入對話方塊**處理登入了。
#### 登入對話方塊<sub>(Login Dialog)</sub>
> Facebook Login 支援**逐步授權**,您不需要事先要求所有資訊,可以隨著時間提出要求。這表示用戶可以簡單快速地在您的應用程式中建立帳號,而且隨著他們對您的應用程式體驗加深,您可以接著要求其它資訊以進一步提升他們的使用體驗。
使用自己的登入按鈕呼叫`FB.login()`以觸發**登入對話方塊**提示用戶登入:
```
FB.login(function(response){
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
} else {
console.log('User cancelled login or did not fully authorize.');
}
});
```
##### `FB.login()`的引數
| 名稱 | 型態 | 說明 |
| - | - | - |
| `cb` | function | Callback function |
| `opts` | object | Options to modify login behavior |
###### 引數`opts`物件
| 名稱 | 型態 | 說明 |
| - | - | - |
| `auth_type` | 字串 | `rerequest`<sub>(重新請求被拒絕的[權限](https://developers.facebook.com/docs/facebook-login/permissions))</sub>、`reauthenticate`、`reauthorize` |
| `scope` | 字串 | 以逗號分隔的[權限](https://developers.facebook.com/docs/facebook-login/permissions)字串 |
| `return_scopes` | 布林 | 若為`true`則回傳`authResponse.grantScopes` |
| `enable_profile_selector` | 布林 | 若為`true`則提示用戶授權給一或多個粉絲專頁 |
| `profile_selector_ids` | 字串 | Comma separated list of IDs to display in the profile selector |
##### 要求額外權限
> * 您可以等之後需要更多功能時再新增權限。 在您需要新權限時,只要將您需要的權限新增到已授予的清單中,再次啟動「登入」對話方塊後就會要求新的權限。
如需向用戶要求更多[權限](https://developers.facebook.com/docs/facebook-login/permissions)就再次呼叫`FB.login()`,**登入對話方塊**僅會詢問用戶尚未准許的[權限](https://developers.facebook.com/docs/facebook-login/permissions)。
若呼叫`FB.login()`時加上第二個引數物件並將欲要求的[權限](https://developers.facebook.com/docs/facebook-login/permissions)以逗號分隔的字串置入`scope`鍵的值則可向用戶要求除了`public_profile`之外的[權限](https://developers.facebook.com/docs/facebook-login/permissions),而`return_scopes: true`可在回應中取得用戶授予的[權限](https://developers.facebook.com/docs/facebook-login/permissions):
```
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
console.log(authResponse.grantedScopes);
} else {
console.log('User cancelled login or did not fully authorize.');
}
}, {
scope: 'email,user_likes', // 要求更多權限
return_scopes: true // 回傳被授予的權限
});
```
##### 瞭解用戶授權的權限
呼叫[`FB.api()`](https://developers.facebook.com/docs/javascript/reference/FB.api/)查詢`/me/permissions`,下面示例回應:
```
{
"data": [
{
"permission": "public_profile",
"status": "granted"
},
{
"permission": "email",
"status": "granted"
}
]
}
```
##### 再次要求拒絕的權限
> * **「登入」對話方塊**讓用戶可以拒絕向您的應用程式分享您要求的某些權限。您的應用程式應該要處理這種情況。
若查詢`/me/permissions`的回應如下:
```
{
"data": [
{
"permission": "public_profile",
"status": "granted"
},
{
"permission": "user_likes",
"status": "declined"
}
]
}
```
得知`user_likes`權限被**拒絕**,向用戶說明應該授予權限的原因,然後再次要求將已拒絕的權限授予網頁應用程式。用戶一旦拒絕授予某權限,除非明確告知**「登入」對話方塊**要再次要求某個已拒絕的權限,否則該**對話方塊**不會再次要求該權限。藉由將`auth_type: 'rerequest'`新增至`FB.login()`呼叫:
```
FB.login(
function(response) {
// 處理回應
}, {
scope: 'user_likes',
auth_type: 'rerequest' // 重新請求被拒絕的權限
}
);
```
## 建置成功應用程式的基礎
* [最佳作法](https://developers.facebook.com/docs/facebook-login/best-practices)
* [用戶體驗設計](https://developers.facebook.com/docs/facebook-login/userexperience)
* [登入安全性](https://developers.facebook.com/docs/facebook-login/security)
## 要求用戶資料
* [權限](https://developers.facebook.com/docs/facebook-login/permissions/overview)
## 存取權杖、其到期時間,以及其與資料存取的關係
* [存取權杖](https://developers.facebook.com/docs/facebook-login/access-tokens)
* [驗證與資料存取的比較](https://developers.facebook.com/docs/facebook-login/auth-vs-data)
##