第三方登入系列文章的第二篇,在 ASP.NET Core 整合 Facebook 做第三方登入,Facebook 的使用者相當多,用 Facebook 來做第三方登入的普及率不是第一也有第二,算是相當廣泛,有做第三方登入的網站,大都有支援 Facebook,這篇文章記錄了整合的過程。
其他的第三方登入解決方案可以參考下面的連結:
- 在 ASP.NET Core 整合 LINE Login 做為網站的第三方登入
- 在 ASP.NET Core 整合 Google 做為網站的第三方登入
- 在 ASP.NET Core 整合 Microsoft 做為網站的第三方登入
- 在 ASP.NET Core 整合 GitHub 做為網站的第三方登入
- 在 ASP.NET Core 整合 Twitter 做為網站的第三方登入
建立應用程式
所有走 OAuth 2.0 授權機制整合第三方登入的起手式,一定是讓授權伺服器認識我們的應用程式,Facebook 也不例外,我們到 https://developers.facebook.com/apps 這個網頁「建立應用程式
」。
選擇應用程式的「類型
」,這裡就根據我們的需要來做選擇,因為是針對開發用的,所以我選擇「無
」。
提供應用程式的「基本資訊
」,應用程式名稱是必填的,其他欄位就按照我們的需要來填寫。
如果我們的應用程式還在開發中,而且 Redirect URI 的 Host 是 localhost,我們本身也是應用程式的擁有者的話,基本上到這邊應用程式算是建立完成了,將來要開放上線的時候至少還得接續做這兩件事:
- 生出一個對外的 HTTPS Redirect URI
- 取得 public_profile 的進階存取權限,以獲得使用者的 id、name、picture。
準備 Redirect URI
接下來進入程式撰寫的環節,我們不用 Facebook 提供的 JavaScript SDK,而是手動建立登入流程,這樣可以避免讓 Access Token
曝露在瀏覽器端。
使用者透過授權網址授權之後,我們就能拿到 code
,拿 code 就能去換 Access Token 回來,而換 Access Token 的網址及參數如下:
Access Token URL
:https://graph.facebook.com/oauth/access_tokengrant_type
:填入 "authorization_code"code
:即我們拿到的 coderedirect_uri
:即 Redirect URIclient_id
:即應用程式編號client_secret
:即應用程式密鑰
應用程式編號及應用程式密鑰,我們可以在應用程式「設定
」的「基本資料
」裡面找到。
Facebook 傳給我們 Redirect URI 的資料就只有 Access Token,所以我們還需要拿著 Access Token 再去跟 Facebook 要使用者授權的資料,我這邊只有要 id
、name
、picture
,而要資料的網址是 https://graph.facebook.com/me?fields=id,name,picture{url}
,下面是整個 Redirect URI 的程式碼:
[HttpGet("callback")]
public async Task<IActionResult> Callback()
{
if (!this.Request.Query.TryGetValue("code", out var code))
{
return this.StatusCode(400);
}
var accessToken = await this.ExchangeAccessToken(code);
if (accessToken == null)
{
return this.StatusCode(400);
}
var userProfile = await this.GetUserProfile(accessToken);
// TODO: Save AccessToken and UserProfile
// TODO: User Login
return this.Redirect("/");
}
private async Task<string> ExchangeAccessToken(string code)
{
var client = this.httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Post, "AccessTokenUrl");
request.Content = new FormUrlEncodedContent(
new Dictionary<string, string>
{
["grant_type"] = "authorization_code",
["code"] = code,
["redirect_uri"] = "Redirect URI",
["client_id"] = "ClientId",
["client_secret"] = "ClientSecret"
});
var response = await client.SendAsync(request);
if (response.StatusCode != HttpStatusCode.OK) return null;
var content = await response.Content.ReadAsStringAsync();
var result = JsonNode.Parse(content);
return result["access_token"].GetValue<string>();
}
private async Task<string> GetUserProfile(string accessToken)
{
var client = this.httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, "UserInfoUrl");
request.Headers.Authorization = AuthenticationHeaderValue.Parse($"Bearer {accessToken}");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
return result;
}
授權網址
最後我們要組合出授權網址,使用者點擊這個授權網址即開始進入登入流程,Facebook 的授權網址是 https://www.facebook.com/dialog/oauth
,所需的參數為:
response_type
:填入 "code"client_id
:即應用程式編號redirect_uri
:即 Redirect URIstate
:隨機產生的一段唯一的字串,主要是可以用來避免 CSRF(Cross Site Request Forgery)。scope
:想請使用者授權給我們的資料範圍
我就依據我的需要,組合出下面這個網址:
整個登入的流程如下圖:
我們點擊授權網址,登入 Facebook 之後,就會看到授權的頁面,授權成功後,沒意外的話就能登入成功了,而授權畫面會有一個紅色驚嘆號,是因為我的應用程式還沒通過審查,我是使用應用程式擁有者的身份才有辦法進到這個授權畫面。
以上,以手動建立登入流程的方式,整合 Facebook 第三方登入,分享給各位朋友,希望對大家有起到一點幫助。