「Open棟梁 wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
汎用認証サイト(Multi-purpose Authentication Site)
の導入前の評価を行うためのファーストステップガイド。
(4) では、「認証連携コードの実装」を行う。
ここでは、クライアントのプロジェクトとして、ASP.NET MVCを選択する。
ASP.NET MVCの(ASP.NET Web Application)プロジェクトを新規作成する。
[メニュー] ---> [新規作成] --->
[プロジェクト] ---> [ASP.NET Web Application(.NET Framework)]
テンプレート選択画面で以下のように選択する。
HomeController?から以下のアクション・メソッドを削除
/Home/About.cshtml
/Home/Contact.cshtml
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container body-content">
@RenderBody()
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - マイ ASP.NET アプリケーション</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> @RenderBody() @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
/Home/Index.cshtml
@{ ViewBag.Title = "Home Page"; }
汎用認証サイトのAccountControllerからサンプルのRedirectエンドポイントである
AccountController?.OAuthAuthorizationCodeGrantClient?アクション・メソッドをコピーする。
[HttpGet] [AllowAnonymous] public async Task<ActionResult> OAuthAuthorizationCodeGrantClient(string code, string state) { // ・・・コメントアウト・・・ return View(""); }
"f53469c17c5a432f86ce563b7805ab89": { "client_secret": "cKdwJb6mRKVIJpGxEWjIC94zquQltw_ECfO-55p21YM", "redirect_uri_code": "http://(クライアント・サイトのアドレス:ポート)/Home/OAuthAuthorizationCodeGrantClient", "redirect_uri_token": "http://hogehoge0/bbb", "client_name": "test_icon"
http://(汎用認証サイトのアドレス:ポート)/MultiPurposeAuthSite/Account/OAuthAuthorize?client_id=67d328bfe8604aae83fb15fa44780d8b&response_type=code&scope=profile%20email%20phone%20address%20userid%20aaa%20bbb&state=vj9NCxij4L
<a href="http://(クライアント・サイトのアドレス:ポート)/MultiPurposeAuthSite/Account/OAuthAuthorize?client_id=67d328bfe8604aae83fb15fa44780d8b&response_type=code&scope=profile%20email%20phone%20address%20userid%20aaa%20bbb&state=vj9NCxij4L">開始</a>
<a href="http://(クライアント・サイトのアドレス:ポート)/MultiPurposeAuthSite/Account/OAuthAuthorize?client_id=f53469c17c5a432f86ce563b7805ab89&response_type=code&scope=profile%20email%20phone%20address%20userid%20aaa%20bbb&state=vj9NCxij4L">開始</a>
RedirectエンドポイントであるOAuthAuthorizationCodeGrantClient?アクション・メソッドにブレークポイントを仕掛ける。
この状態でクライアント・サイトをデバッグ実行して、スターターをクリックしてみる。
以下を必要とする。
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
POST /MultiPurposeAuthSite/OAuthBearerToken HTTP/1.1 Host: (汎用認証サイトのアドレス:ポート) Authorization: Basic ["client_Id:client_secret"をbase64 url encodeした値] Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=[取得した仲介コードの値]
http://(汎用認証サイトのアドレス:ポート)/MultiPurposeAuthSite/OAuthBearerToken
を利用する。
http://(クライアント・サイトのアドレス:ポート)/Home/OAuthAuthorizationCodeGrantClient
だいたい、以下のような感じのコードになる。
using System; using System.Text; using System.Collections.Generic; using System.Web.Mvc; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using Microsoft.Owin.Security.DataHandler.Encoder; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace WebApplication1.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpGet] [AllowAnonymous] public async Task<ActionResult> OAuthAuthorizationCodeGrantClient(string code, string state) { if (state == "vj9NCxij4L") // CSRF(XSRF)対策のstateの検証は重要 { HttpClient httpClient = new HttpClient(); // HttpRequestMessage (Method & RequestUri) HttpRequestMessage httpRequestMessage = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri("http://10.231.20.145/MultiPurposeAuthSite/OAuthBearerToken"), }; // HttpRequestMessage (Headers & Content) httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes( string.Format("{0}:{1}", "f53469c17c5a432f86ce563b7805ab89", "cKdwJb6mRKVIJpGxEWjIC94zquQltw_ECfO-55p21YM")))); httpRequestMessage.Content = new FormUrlEncodedContent( new Dictionary<string, string> { { "grant_type", "authorization_code" }, { "code", code }, { "redirect_uri", System.Web.HttpUtility.HtmlEncode("http://localhost:62517/Home/OAuthAuthorizationCodeGrantClient") }, }); // HttpResponseMessage HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(httpRequestMessage); string response = await httpResponseMessage.Content.ReadAsStringAsync(); // 汎用認証サイトのOAuth2.0のレスポンスに含まれるaccess_tokenは、id_tokenのようなformatをしている。ここからsubを取得可能。 Base64UrlTextEncoder base64UrlEncoder = new Base64UrlTextEncoder(); Dictionary<string, string> dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(response); JObject jobj = ((JObject)JsonConvert.DeserializeObject(Encoding.UTF8.GetString(base64UrlEncoder.Decode(dic["access_token"].Split('.')[1])))); string sub = (string)jobj["sub"]; } return View(""); } } }
必要に応じて、/userinfoエンドポイントなどのResourcesServer?のWebAPIにアクセスして結果を画面に出力する。