はじめに
以下の記事で、Angularな SPA で Facebook の OAuth 認証を行いました。
OAuth 認証時に取得したアクセストークンは、サーバーに送信して検証をしなければいけないはずなのですが、Facebook がその情報をきちんと公開していません。
検索を駆使してやっと見つけたのが以下の記事です。
言語は C# ではないのですが、内容を変換しながらコーディングし、実際に動作したソースコードをご紹介します。
なお、環境は以下のようになります。
- Windows 10
- Visual Studio Community 2017
- .NET Core 2.1
- コンソールアプリケーション
Visual Studio の設定
Visual Studio で、.NET Core のコンソールアプリケーションテンプレートより、コンソールアプリケーションのプロジェクトを作成します。
また、JSON を扱うため、Json.NET
をNugetよりインストールします。
サンプルソース
C# のコンソールアプリケーションで、Facebook の OAuth 認証で取得したアクセストークンを検証するソースコードは以下のようになります。
using System; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Collections.Generic; using Newtonsoft; using Newtonsoft.Json; namespace ConsoleApp2 { class Program { static void Main(string[] args) { Task task = ValidateAccessTokenAsync(); task.Wait(); Console.ReadKey(); } static async Task ValidateAccessTokenAsync() { // アプリケーション設定情報 string clientId = "アプリ ID"; string clientSecret = "app secret"; // ログイン画面で取得したアクセストークン string userToken = "アクセストークン"; // 検証用に取得するアクセストークン string appToken; // 検証用に取得するユーザーID string userId; // アクセストークンを再度取得 var parameters = new Dictionary<string, string>() { { "client_id", clientId }, { "client_secret", clientSecret }, { "grant_type", "client_credentials"} }; HttpClient httpClient = new HttpClient(); var response = await httpClient.GetAsync($"https://graph.facebook.com/oauth/access_token?{await new FormUrlEncodedContent(parameters).ReadAsStringAsync()}"); if ((int)response.StatusCode == 200) { AccessToken ret = JsonConvert.DeserializeObject<AccessToken>( await response.Content.ReadAsStringAsync()); appToken = ret.access_token; Console.WriteLine("appToken:" + ret.access_token); } else { Console.WriteLine("Error:" + response.ReasonPhrase); Console.WriteLine("Access Token is invalid !!"); return; } // アクセストークンの検証 var parameters2 = new Dictionary<string, string>() { { "input_token", userToken }, { "access_token", appToken } }; var response2 = await httpClient.GetAsync($"https://graph.facebook.com/debug_token?{await new FormUrlEncodedContent(parameters2).ReadAsStringAsync()}"); if ((int)response2.StatusCode == 200) { ValidateObject ret = JsonConvert.DeserializeObject<ValidateObject>(await response2.Content.ReadAsStringAsync()); userId = ret.data.user_id; // ユーザー ID が取得できたときのみ Valid。 if (string.IsNullOrEmpty(userId)) { Console.WriteLine("Access Token is invalid !!"); return; } Console.WriteLine("userId:" + userId); } else { Console.WriteLine("Error:" + response2.ReasonPhrase); Console.WriteLine("Access Token is invalid !!"); return; } Console.WriteLine("Access Token is valid !!"); } } class AccessToken { public string access_token { get; set; } public string token_type { get; set; } } public class Data { public string app_id { get; set; } public string type { get; set; } public string application { get; set; } public int data_access_expires_at { get; set; } public int expires_at { get; set; } public bool is_valid { get; set; } public List<string> scopes { get; set; } public string user_id { get; set; } } public class ValidateObject { public Data data { get; set; } } }