第三方登入系列文章的第五篇「在 ASP.NET Core 整合 GitHub 做第三方登入」,GitHub 是全世界最大的程式原始碼管理平台,每個開發者應該都要有一個 GitHub 帳號,如果我們的網站的服務對象是開發者,應該要有一個 GitHub 第三方登入給使用者使用,整個整合的過程,就記錄在這篇文章當中。
其他的第三方登入解決方案可以參考下面的連結:
- 在 ASP.NET Core 整合 LINE Login 做為網站的第三方登入
- 在 ASP.NET Core 整合 Facebook 做為網站的第三方登入
- 在 ASP.NET Core 整合 Google 做為網站的第三方登入
- 在 ASP.NET Core 整合 Microsoft 做為網站的第三方登入
- 在 ASP.NET Core 整合 Twitter 做為網站的第三方登入
建立 OAuth App
先讓 GitHub 認識我們的應用程式,在 GitHub 的個人設定裡面的最下面有一個「Developer settings
」,點擊進去之後會看到「OAuth Apps
」,點擊中間的「Register a new application
」來註冊我們的應用程式。
必填的欄位只有三個,分別是:
Application name
:應用程式名稱Homepage URL
:應用程式的首頁,這邊我輸入我自己部落格的網址。Authorization callback URL
:接收 authorization code 的 Callback URL,提前先將規劃好的 Web Api 網址填入,不然就隨便先亂填一個,之後再回來改。
最後,按下「Register application
」就建立成功了,建立成功之後,我們還要取得「Client ID
」以及「Client secrets
」,Client ID 就顯示在畫面上,而 Client secrets 則需要按下「Generate a new client secret
」來產生。
當 Client secrets 產生了之後,把它跟 Client ID 一起複製下來備用。
準備 Authorization callback URL
下面我們來撰寫 Callback URL 的程式,使用者授權成功之後,GitHub 會把 code
回傳到我們的 Web Api,我們要拿著 code 發送 POST 到 GitHub 交換 Access Token
,然後還要拿著 Access Token 再去跟 GitHub 拿使用者授權的資訊,下面是交換 Access Token 時所需要的資料:
Access Token URL
:https://github.com/login/oauth/access_tokenUser Info Url
:https://api.github.com/userclient_id
:即 Client IDclient_secret
:即 Client secretscode
:即我們拿到的 coderedirect_uri
:即 Authorization callback URL
在跟 GitHub 拿使用者授權資料的時候,需要加上「User-Agent
」 Header,而 User-Agent 的值有就好,下面是程式碼:
[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 userInfo = await this.GetUserInfo(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, "Access Token Url");
request.Content = new FormUrlEncodedContent(
new Dictionary<string, string>
{
["client_id"] = "Client ID",
["client_secret"] = "Client secrets",
["code"] = code,
["redirect_uri"] = "Authorization callback URL"
});
var response = await client.SendAsync(request);
if (response.StatusCode != HttpStatusCode.OK) return null;
var content = await response.Content.ReadAsStringAsync();
var result = Regex.Matches(content, "([^&=]+)=([^&=]+)").ToDictionary(m => m.Groups[1].Value, m => m.Groups[2].Value);
return result["access_token"];
}
private async Task<string> GetUserInfo(string accessToken)
{
var client = this.httpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, "User Info Url");
request.Headers.Authorization = AuthenticationHeaderValue.Parse($"Bearer {accessToken}");
request.Headers.Add("User-Agent", "my-chef-my-life");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
return result;
}
授權網址
再來,我們要來兜授權網址,使用者點擊這個授權網址之後就開始登入的流程,GitHub 的授權網址為:https://github.com/login/oauth/authorize,所需參數如下:
client_id
:即 Client IDredirect_uri
:即 Authorization callback URLstate
:隨機產生的一段唯一的字串,主要是可以用來避免 CSRF(Cross Site Request Forgery)。scope
:想請使用者授權給我們的資料範圍,可參考 Scopes for OAuth Apps - GitHub Docs。
根據上述的資訊,我兜出的授權網址如下:
整個登入的流程大概就像下圖這樣:
使用者在點擊了授權網址,經由 GitHub 授權成功後,我們能順利拿到使用者的資料,就算是整合成功了。
GitHub 果然還是服務開發者的網站,有關於整合 OAuth 的文件寫得非常清楚,整合的過程相當順利,沒有遇到太大的阻礙,以上,整合 GitHub 做為第三方登入的過程就分享給大家,希望對大家有一點幫助。
參考資料
- Creating an OAuth App - GitHub Docs
- Authorizing OAuth Apps - GitHub Docs
- Scopes for OAuth Apps - GitHub Docs
- Creating a custom badge for your OAuth App - GitHub Docs