﻿# ASP.NET Identity 如何取得 Facebook 登入的 Access Token

經過長時間的研究，發現 ASP.NET Identity 真的是個很神奇的產品，不但官網缺乏文件，也缺乏完整的 API 文件，我實在不想讓這個好東西就此埋沒，今天特別整理 Facebook 登入後該如何將 Access Token 安全地保存在 Cookie 中。由於 Facebook 的 Access Token 有明確的到期時間，預設透過網站登入只有 2 小時的使用期限，因此沒必要像 GitHub 那樣將 Access Token 保存在資料庫中，本篇文章也一樣用逐步教學的方式，示範如何在你的網站增加 Facebook 驗證機制，並成功取得一個臨時的 Access Token。

**1\. 建立 ASP.NET MVC 5 專案 ( 請使用 Visual Studio 2013 開發工具 )**

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

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

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

-   在檔案最上方新增命名空間  
    using Microsoft.Owin.Security.Facebook;
-   在 ConfigureAuth() 方法最下方新增以下程式：

```csharp
var facebookOptions = new FacebookAuthenticationOptions()
{
    AppId = "應用程式ID",
    AppSecret = "應用程式密鑰",

    Provider = new FacebookAuthenticationProvider()
    {
        OnAuthenticated = async (context) =>
        {
            context.Identity.AddClaim(
                new System.Security.Claims.Claim(
                    "urn:facebook:access_token",
                    context.AccessToken,
                    "http://www.w3.org/2001/XMLSchema#string",
                    "Facebook"));

            context.Identity.AddClaim(
                new System.Security.Claims.Claim(
                    "urn:facebook:email",
                    context.Email,
                    "http://www.w3.org/2001/XMLSchema#string",
                    "Facebook"));
        }
    }

};

facebookOptions.Scope.Add("email");

app.UseFacebookAuthentication(facebookOptions);
```

**備註**：有哪些 Scope 可以加入請參考 [Permissions with Facebook Login](https://developers.facebook.com/docs/facebook-login/permissions) 文件說明。

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

將 SignInAsync() 整個方法置換成以下程式碼：

```csharp
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    ClaimsIdentity ext = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

    if (ext != null)
    {
        var ignoreClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims";

        foreach (var c in ext.Claims)
        {
            if (!c.Type.StartsWith(ignoreClaim))
                if (!identity.HasClaim(c.Type, c.Value))
                    identity.AddClaim(c);
        }
    }

    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
```

大功告成！

之後只要使用者登入，就可以用以下程式碼取得 Facebook Access Token 的 Claim 物件：

```
Claim token = ((ClaimsIdentity)User.Identity).FindFirst("urn:facebook:access_token");
```

若要取得 Token 值，可以取得該物件的 Value 屬性：

```
Claim token = ((ClaimsIdentity)User.Identity).FindFirst("urn:facebook:access_token");
if (token != null){    ViewBag.token = token.Value;}
```

底下示範 Facebook 上面註冊 Applications 的設定步驟：

1\. 前往 [https://developers.facebook.com/](https://developers.facebook.com/ "https://developers.facebook.com/") 開發人員網站

2\. 製作新應用程式

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6e5ed796c083adb06eed-image_2467.png)

3\. 填寫顯示名稱 ( Display Name ) 與 任選一個類別，然後點選「建立應用程式」

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

4\. 然後輸入一個考驗人腦極限的圖片驗證碼 ( captcha )

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/7ad4ee28f8366ca2a3ae-image_2469.png)

5\. 點選「設定」—>「新增平台」

[![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3d7c176acceda9ec12a7-image_thumb_196.png)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/d260fa0aa90d74c654dd-image_2470.png)

6\. 請選擇「網站」，因為我們打算從自己的網站透過 ASP.NET Identity 登入 Facebook

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

7\. 請輸入你要測試的網站網址，即便為 Localhost 也沒關係，請把 Visual Studio 2013 提供的網站網址貼上「網站URL」欄位。

[![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3b72e11ee35c61f55fa4-image_thumb_197.png)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6e29a3087416194b9542-image_2472.png)

8\. 取得最上方的「**應用程式ID**」與「**應用程式密鑰**」，其中「應用程式密鑰」部分須按右邊的「顯示」按鈕才會顯示該欄位的內容，請將「應用程式ID」與「應用程式密鑰」寫入 **App\_Start\\Startup.Auth.cs** 檔案的 Facebook 設定裡面。

![SNAGHTMLc418746](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/4663797d97262439345d-SNAGHTMLc418746.png "SNAGHTMLc418746")

**相關連結**

-   [Facebook 開發人員](https://developers.facebook.com/)

-   [Permissions with Facebook Login](https://developers.facebook.com/docs/facebook-login/permissions)
-   [Access Tokens](https://developers.facebook.com/docs/facebook-login/access-tokens)
-   [How-To: Handle expired access tokens](https://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/)

-   [How to access Facebook private information by using ASP.NET Identity (OWIN)?](http://stackoverflow.com/questions/18942196/how-to-access-facebook-private-information-by-using-asp-net-identity-owin)
-   [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/)
-   [Facebook SDK for .NET](http://facebooksdk.net/) ( 官網 )
-   [Facebook SDK for .NET](https://github.com/facebook-csharp-sdk/facebook-csharp-sdk) ( GitHub )
-   [The Graph API – Facebook](https://developers.facebook.com/docs/graph-api)

-   [Graph API Explorer](https://developers.facebook.com/tools/explorer)
