前言
繼關(guān)于服務(wù)端如何接入Apple, Google 的第三方登錄之后,這里介紹在整合Facebook 和Instagram 的第三方登錄時(shí)服務(wù)端的驗(yàn)證工作。
Facebook的登錄驗(yàn)證與Google相似,同樣是驗(yàn)證客戶端通過(guò)登錄請(qǐng)求獲取到的登錄token是否有效。
根據(jù)官方文檔 顯示,F(xiàn)acebook的身份驗(yàn)證有兩種方式:
- 通過(guò)code交換
access_token,然后用獲取的access_token訪問(wèn)API驗(yàn)證客戶端傳來(lái)的登錄token是否有效。服務(wù)端收到客戶端傳來(lái)的code后,通過(guò)Facebook的API(https://graph.facebook.com/v9.0/oauth/access_token)交換訪問(wèn)口令,即access_token。最后調(diào)用API(https://graph.facebook.com/debug_token?input_token={token-to-inspect}&access_token={app-token-or-admin-token})驗(yàn)證登錄token是否有效。
var (
clientId = "your clientId"
clientSecret = "your clientSecret"
code = "your code"
redirectUri = "your redirectUri"
url = fmt.Sprintf("https://graph.facebook.com/v9.0/oauth/access_token?client_id=%s&redirect_uri=%s&client_secret=%s&code=%s", clientId, redirectUri, clientSecret, code)
)
response, err := http.Get(url)
handleResponse(response)
handleErr(err)
API返回的結(jié)果:
{
"access_token": {訪問(wèn)口令},
"token_type": {type},
"expires_in": {還有多久過(guò)期, 單位: 秒}
}
var (
accessToken = "get from above"
token = "your token"
)
response, err := http.Get(fmt.Sprintf("https://graph.facebook.com/debug_token?input_token=%s&access_token=%s", token, accessToken))
handleResponse(response)
handleErr(err)
- token API
客戶端授權(quán)并取得Facebook返回的登錄token后,將token傳給服務(wù)端,服務(wù)端通過(guò)API: https://graph.facebook.com/debug_token?input_token={token-to-inspect}&access_token={app-token-or-admin-token}
其中input_token為客戶端傳過(guò)來(lái)的登錄token,access_token為API訪問(wèn)口令,注意這里的access_token不是通過(guò)API獲取的,而是client_id|client_secret
var (
clientId = "your clientId"
clientSecret = "your clientSecret"
token = "your token"
url = fmt.Sprintf("https://graph.facebook.com/debug_token?input_token=%s&access_token=%s|%s", token, clientId, clientSecret)
)
response, err := http.Get(url)
handleResponse(response)
handleErr(err)
具體是code還是token API,取決于客戶端在用戶點(diǎn)擊登錄按鈕時(shí),客戶端發(fā)起請(qǐng)求中response_type的值。根據(jù)官網(wǎng)顯示,response_type的值包括:
| 值 | 解釋 |
|---|---|
| code | 響應(yīng)數(shù)據(jù)作為網(wǎng)址參數(shù)納入,且包含 code 參數(shù)(每個(gè)登錄請(qǐng)求獨(dú)有的加密字符串)。如果未指定此參數(shù),這便是默認(rèn)行為。當(dāng)服務(wù)器處理口令時(shí),這尤其有用 |
| token | 響應(yīng)數(shù)據(jù)作為網(wǎng)址片段納入,且包含訪問(wèn)口令。桌面應(yīng)用必須為 response_type 選用此設(shè)置。當(dāng)客戶端處理口令時(shí),這尤其有用 |
| code%20token | 響應(yīng)數(shù)據(jù)作為網(wǎng)址片段納入,且包含訪問(wèn)口令和 code 參數(shù) |
| granted_scopes | 返回用戶在登錄時(shí)授予應(yīng)用的所有權(quán)限的逗號(hào)分隔列表。可與其他 response_type 值合并。與 token 合并時(shí),響應(yīng)數(shù)據(jù)作為網(wǎng)址片段納入;與其他值合并時(shí),響應(yīng)數(shù)據(jù)則作為網(wǎng)址參數(shù)納入。 |
token驗(yàn)證API返回的結(jié)構(gòu)為:
{
"data": {
"app_id": 138483919580948, //應(yīng)用ID,等于client_id
"type": "USER",
"application": "Social Cafe",
"expires_at": 1352419328, //token過(guò)期時(shí)間
"is_valid": true, //是否有效
"issued_at": 1347235328, //什么時(shí)候簽發(fā)的
"metadata": {
"sso": "iphone-safari"
},
"scopes": [ //權(quán)限范圍
"email",
"publish_actions"
],
"user_id": "1207059" //用戶在該應(yīng)用下的唯一ID,類(lèi)似于微信的OpenID
}
}
最后如果需要服務(wù)器自己獲取用戶的頭像、昵稱(chēng)、性別等信息,需要服務(wù)端通過(guò)前面獲取到的access_token自己去調(diào)用Facebook對(duì)應(yīng)的API:
API: https://graph.facebook.com/{facebook_user_id}?fields=name,picture&access_token={access_token}
其中fields字段根據(jù)自己的需求填寫(xiě),用,分隔,具體參考官方文檔
根據(jù)Instagram官方文檔 顯示,Instagram不推薦使用Instagram作為身份驗(yàn)證解決方案,其推薦使用Facebook登錄, 但是為了調(diào)用Instagram的圖譜API,需要開(kāi)發(fā)者完成如下準(zhǔn)備工作:
- Instagram Business 帳戶 或 Instagram 創(chuàng)作者帳戶
- 與該帳戶相關(guān)聯(lián)的 Facebook 公共主頁(yè)
- 一個(gè) Facebook 開(kāi)發(fā)者帳戶,可在公共主頁(yè)上執(zhí)行任務(wù)
- 已注冊(cè)的 Facebook 應(yīng)用 ,且已配置基本設(shè)置
這里介紹如果通過(guò)Instagram 圖譜 API 獲取Instagram的訪問(wèn)口令以及用戶信息
客戶端在App內(nèi)集成Instagram授權(quán)窗口后,在用戶授權(quán)后客戶端將獲取授權(quán)碼,并將其傳給服務(wù)端,然后客戶端使用該授權(quán)碼來(lái)?yè)Q取訪問(wèn)口令(access_token)。
這里需要注意的是,Instagram返回的授權(quán)碼包含了后綴#_,所以使用時(shí)需要將#_去掉才是真正的授權(quán)碼
交換訪問(wèn)口令的API: https://api.instagram.com/oauth/access_token, 需要的參數(shù)有:
| 參數(shù)名 | 參數(shù)值 |
|---|---|
| client_id | Instagram應(yīng)用ID |
| client_secret | 應(yīng)用密鑰 |
| redirect_uri | Instagram后臺(tái)配置的用戶授權(quán)后的重定向URI |
| grant_type | 固定值: authorization_code
|
| code | 授權(quán)碼(注意去掉#_后綴) |
tokenParam := fmt.Sprintf("client_id=%s&client_secret=%s&grant_type=authorization_code&redirect_uri=%s&code=%s", clientId, clientSecret, redirectUri, code)
response, err := http.Post(tokenUrl, "application/x-www-form-urlencoded", strings.NewReader(tokenParam))
if err != nil {
panic(err)
}
if response.StatusCode != http.StatusOK {
panic(err)
}
返回的結(jié)果格式為:
{
"access_token": "IGQVJ...", //訪問(wèn)口令
"user_id": 17841405793187218 //Instagram 應(yīng)用中用戶的唯一ID,類(lèi)似于微信的OpenID
}
最后使用API: https://graph.instagram.com/{instagram_user_id}?fields=username&access_token={access_token} 查詢(xún)用戶節(jié)點(diǎn),其中fields字段參考用戶節(jié)點(diǎn)文檔
參考資料
Facebook登錄
手動(dòng)構(gòu)建登錄流程
Facebook User
Instagram官方文檔
Instagram 圖譜 API
Instagram 用戶節(jié)點(diǎn)文檔