﻿# 如何利用 ASP.NET Identity 實作 GitHub OAuth2 登入驗證

在 Visual Studio 2013 新版的 ASP.NET MVC 5 專案範本中已內建 ASP.NET Identity 機制，若要整合第三方驗證機制，除了內建的 [Microsoft Account](http://www.nuget.org/packages/Microsoft.Owin.Security.MicrosoftAccount)、[Facebook](http://www.nuget.org/packages/Microsoft.Owin.Security.Facebook)、[Twitter](http://www.nuget.org/packages/Microsoft.Owin.Security.Twitter) 與 [Google](http://www.nuget.org/packages/Microsoft.Owin.Security.Google) 之外，要怎樣增加其他的驗證機制呢？本篇文章就用逐步教學的方式，示範如何在你的網站增加 [GitHub OAuth2](https://developer.github.com/v3/oauth/) 驗證機制。

**1\. 建立ASP.NET MVC 5專案**

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/eae42dcb3b5ffc8256fe-image_2459.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/d5e8f683056e01e724bd-image_2460.png)

**2\. 透過 NuGet 安裝** [**Owin.Security.Providers**](http://www.nuget.org/packages/Owin.Security.Providers) **套件**

-   Install-Package Owin.Security.Providers

**3\. 修改 App\_Start\\Startup.Auth.cs 檔案**

-   在檔案最上方新增命名空間  
    using Owin.Security.Providers.GitHub;
-   在 ConfigureAuth() 方法最下方新增以下程式：  
    備註: GitHub 提供的 **Scope** 定義請參考 [https://developer.github.com/v3/oauth/#scopes](https://developer.github.com/v3/oauth/#scopes "https://developer.github.com/v3/oauth/#scopes")

```csharp
var opt = new GitHubAuthenticationOptions();
opt.ClientId = "YOUR_GITHUB_CLIENTID";
opt.ClientSecret = "YOUR_GITHUB_CLIENTSECRET";
opt.Scope.Add("user");
opt.Scope.Add("repo");
opt.Scope.Add("public_repo");
opt.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
opt.Provider = new GitHubAuthenticationProvider()
{
    OnAuthenticated = async (context) =>
    {
        context.Identity.AddClaim(new System.Security.Claims.Claim("GitHubAccessToken", context.AccessToken));
    }
};

app.UseGitHubAuthentication(opt);
```

**4\. 修改 Controllers\\AccountController.cs 檔案**

新增一個 private 方法，程式碼如下：

```csharp
private async Task StoreAuthTokenClaims(ApplicationUser user)
{
    // Get the claims identity
    ClaimsIdentity claimsIdentity =
        await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

    if (claimsIdentity != null)
    {
        // Retrieve the existing claims
        var currentClaims = await UserManager.GetClaimsAsync(user.Id);

        // Get the list of access token related claims from the identity
        var tokenClaims = claimsIdentity.Claims.Where(c => c.Type == "GitHubAccessToken");

        // Save the access token related claims
        foreach (var tokenClaim in tokenClaims)
        {
            if (!currentClaims.Contains(tokenClaim))
            {
                await UserManager.AddClaimAsync(user.Id, tokenClaim);
            }
        }
    }
}
```

修改 ExternalLoginCallback / LinkLoginCallback / ExternalLoginConfirmation 這三個可能會用到儲存 Access Token 的動作方法，最主要是要把使用者透過登入取得的 Access Token 儲存到資料庫中，主要就是呼叫上列程式碼：

```
await StoreAuthTokenClaims(user);
```

**備註**：GitHub 的 OAuth2 驗證過程產生的 Access Token 並不會自動過期。

示意圖如下：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a65b8a630280ffd40ff7-image_2461.png)

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/cf26e09cb2cfb138c64b-image_2462.png "image")

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/1db0f9278620591067de-image_2464.png)

大功告成！

之後只要使用者登入，就可以自動用以下程式碼取得 GitHub Access Token：

```
Claim cGitHubAccessToken = ((ClaimsIdentity)User.Identity).FindFirst("GitHubAccessToken");
```

底下顯示 GitHub 上面註冊 **Applications** 的設定畫面，最主要你必須取得 **Client ID** 與 **Client Secret** 並寫入 **App\_Start\\Startup.Auth.cs** 檔案的 GitHub 設定，另一個則是你執行網站的網址必須註冊在 **Authorization callback URL** 欄位，一定要設定正確才能驗證成功！

[![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/d7876b46d959a02dc927-SNAGHTML72f1ed1_thumb.png)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/c94599b052424d7e4d9d-SNAGHTML72f1ed1.png)

至於登入過的 GitHub 使用者，可以到 [https://github.com/settings/applications](https://github.com/settings/applications "https://github.com/settings/applications") 網址撤銷之前授權過的應用程式：

[![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/5e00b865d203a6d9f204-SNAGHTML732a50a_thumb.png)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6c62434430c45c6792dd-SNAGHTML732a50a.png)

**相關連結**

-   [ASP.NET Identity : The Official Microsoft ASP.NET Site](http://www.asp.net/identity)
-   [OAuth | GitHub API](https://developer.github.com/v3/oauth/)
-   [Adding External Logins to your ASP.NET application in Visual Studio 2013](https://devblogs.microsoft.com/dotnet/adding-external-logins-to-your-asp-net-application-in-visual-studio-2013/)
-   [Get more information from Social providers used in the VS 2013 project templates](https://devblogs.microsoft.com/dotnet/get-more-information-from-social-providers-used-in-the-vs-2013-project-templates/)
-   [owin-middleware/OwinOAuthProviders](https://github.com/owin-middleware/OwinOAuthProviders) ( GitHub )  /  NuGet: [Owin.Security.Providers](http://www.nuget.org/packages/Owin.Security.Providers)  
    目前支援以下第三方 OAuth2 登入提供者：

-   LinkedIn
-   Yahoo
-   Google+
-   GitHub
-   Reddit
-   OpenID 2.0 providers
-   Steam

-   [Katana Project](https://github.com/aspnet/AspNetKatana) ( CodePlex ) 包含所有內建第三方登入提供者的實作原始碼

-   [Microsoft.Owin.Security.Facebook](https://github.com/aspnet/AspNetKatana/blob/main/src/Microsoft.Owin.Security.Facebook/FacebookAuthenticationMiddleware.cs)
-   [Microsoft.Owin.Security.Google](https://github.com/aspnet/AspNetKatana/blob/main/src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationMiddleware.cs)
-   [Microsoft.Owin.Security.MicrosoftAccount](https://github.com/aspnet/AspNetKatana/blob/main/src/Microsoft.Owin.Security.MicrosoftAccount/MicrosoftAccountAuthenticationMiddleware.cs)
-   [Microsoft.Owin.Security.Twitter](https://github.com/aspnet/AspNetKatana/blob/main/src/Microsoft.Owin.Security.Twitter/TwitterAuthenticationMiddleware.cs)
-   [Microsoft.Owin.Security.OpenIdConnect](https://github.com/aspnet/AspNetKatana/blob/main/src/Microsoft.Owin.Security.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs)
-   [Microsoft.Owin.Security.OAuth](https://github.com/aspnet/AspNetKatana/blob/main/src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerMiddleware.cs)

-   [打造現代網站應用: (3) ASP.NET Identity](http://channel9.msdn.com/Series/Building-Modern-Web-Apps-CHT/03) ( Channel 9 )

各位也可以觀賞我之前錄製的影片：**[ASP NET MVC 5 新功能探索之《ASP.NET Identity》](https://www.youtube.com/watch?v=Hhy0ePBADfw&hd=1)**

<iframe src="//www.youtube.com/embed/Hhy0ePBADfw?rel=0" width="480" height="360" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
