Open棟梁 wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

汎用認証サイト(Multi-purpose Authentication Site)
の導入前の評価を行うためのファーストステップガイド。

(4) では、「認証連携コードの実装」を行う。

サンプル・プロジェクト

ココで実装するコードは、

下記に添付した、

からダウンロード可能です。

汎用認証サイトをセットアップする。

クライアントのプロジェクトを作成する。

ここでは、クライアントのプロジェクトとして、ASP.NET MVCを選択する。

ASP.NET MVCのプロジェクトを新規作成する。

ASP.NET MVCの(ASP.NET Web Application)プロジェクトを新規作成する。

[メニュー] ---> [新規作成] --->

[プロジェクト] ---> [ASP.NET Web Application(.NET Framework)]

新しいプロジェクト

テンプレート選択

テンプレート選択画面で以下のように選択する。

余分なコードを削除する。

Controller

HomeController?から以下のアクション・メソッドを削除

View

クライアントにRedirectエンドポイントを作成する。

サンプルコードをコピーする。

汎用認証サイトのAccountControllerからサンプルのRedirectエンドポイントである

Authorization Codeグラント種別

AccountController.OAuthAuthorizationCodeGrantClientアクション・メソッドをコピーする。

Implicitグラント種別

AccountController.OAuthImplicitGrantClientアクション・メソッドをコピーする。

サンプルコードを貼り付ける。

Authorization Codeグラント種別

Implicitグラント種別

汎用認証サイトにRedirectエンドポイントのURLを設定する。

認可リクエスト・認可レスポンス

クライアントにスターター(認可リクエスト)のリンクを設置する。

スターターのリンクを取得

0

スターターのリンクを設置

クライアントをデバッグ実行し、認可レスポンスを確認する。

Authorization Codeグラント種別

Implicitグラント種別

アクセストークン・リクエスト、レスポンス(Authorization Codeのみ)

によって、仲介コードを

変換する。

なお、この処理は、Authorization Codeでのみ必要になる。

必要な情報の収集

以下を必要とする。

アクセストークン・リクエストの仕方。

TokenエンドポイントのURL

client_Idとclient_secret

を利用する。

RedirectエンドポイントのURL

HttpClientを使用して仲介コードをアクセストークンとリフレッシュトークンに変換する。

コード

だいたい、以下のような感じのコードになる。

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 httpRequestMessage = null;
                HttpResponseMessage httpResponseMessage = null;

                // HttpRequestMessage (Method & RequestUri)
                httpRequestMessage = new HttpRequestMessage
                {
                    Method = HttpMethod.Post,
                    RequestUri = new Uri("http://(汎用認証サイトのアドレス:ポート)/MultiPurposeAuthSite/OAuthBearerToken"),
                };

                // HttpRequestMessage (Headers & Content)
                httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(
                    "Basic",
                    Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(
                        string.Format("{0}:{1}",
                            "21c7769f16634dabaf14282602b9a5fc",
                            "xrRczIidMMZcMxvYWpIkvSZX1oRj2CLzVFSOkl7ocLY"))));

                httpRequestMessage.Content = new FormUrlEncodedContent(
                    new Dictionary<string, string>
                    {
                        { "grant_type", "authorization_code" },
                        { "code", code },
                        { "redirect_uri", System.Web.HttpUtility.HtmlEncode("http://(クライアント・サイトのアドレス:ポート)/Home/OAuthAuthorizationCodeGrantClient") },
                    });

                // 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);
                string jwtPayload = Encoding.UTF8.GetString(base64UrlEncoder.Decode(dic["access_token"].Split('.')[1]));

                // id_tokenライクなJWTなので、中からsubなどを取り出すことができる。
                JObject jobj = ((JObject)JsonConvert.DeserializeObject(jwtPayload));
                string sub = (string)jobj["sub"];
            }

            return View("");
        }

    }
}

実行結果

上記の、「dic["access_token"]」の部分が、アクセストークンである。

汎用認証サイトでは、設定によってアクセストークンのformatを、ASP.NET Identity形式とJWT形式から選択できる。

2

署名検証、内容検証

アクセストークンのformatgが、JWT形式の場合、
必要に応じて、JWTの署名検証、内容検証を行えば、セキュリティ的に、より確実と言える。

アクセストークンを使用しResource ServerのWebAPIへのアクセス結果を出力する。

Authorization Codeグラント種別

必要な情報の収集

/userinfoエンドポイントにアクセスして、ユーザ属性を取得する。

↓↓↓ 下を追加 ↓↓↓

                // Userエンドポイントに問い合わせを行う。
                
                // HttpRequestMessage (Method & RequestUri)
                httpRequestMessage = new HttpRequestMessage
                {
                    Method = HttpMethod.Get,
                    RequestUri = new Uri("http://(汎用認証サイトのアドレス:ポート)/MultiPurposeAuthSite/userinfo"),
                };

                // HttpRequestMessage (Headers)
                httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", dic["access_token"]);

                // HttpResponseMessage
                httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
                string userinfo = await httpResponseMessage.Content.ReadAsStringAsync();
                jobj = ((JObject)JsonConvert.DeserializeObject(userinfo));
                sub = (string)jobj["sub"];
            }

            // 基本的に、仲介コードやアクセストークンは画面に露見させないこと。
            // このまま画面に表示させるとQuerystringに仲介コードが露見するので、
            // 必要な情報位を取得した後に、一段、Redirect処理などを経由させると良い。

↑↑↑ 上を追加 ↑↑↑

            return View("");
        }

    }
}

注意事項

Implicitグラント種別

前述のAuthorization Codeグラント種別と異なり、
この後の処理をクライアントサイドのJavaScript?で行う。

必要な情報の収集

前述と同じ。

/userinfoエンドポイントにアクセスして、ユーザ属性を取得する。

以下のモジュールから、

以下のようにOAuthImplicitGrantClient?.cshtmlにコードを移植する。

注意事項

URLフラグメントを使用するため、Authorization Codeグラント種別と比べ、
非常に、アクセストークンが画面に露見し易いので注意する。

OpenID Connect

Authorization Code Flow

OpenID ConnectのAuthorization Code Flowをテストする。

上記のスターターのScopeにopenidを加えるだけで、
OpenID ConnectのAuthorization Code Flowをテストできる。

<a href="http://(汎用認証サイトのアドレス:ポート)/MultiPurposeAuthSite/Account/OAuthAuthorize?client_id=21c7769f16634dabaf14282602b9a5fc&response_type=code&scope=profile%20email%20phone%20address%20userid%20aaa%20openid&state=vj9NCxij4L">開始</a>

Implicit Flow

OpenID ConnectのImplicit Flowをテストする。

Implicit Flowでは、Scopeにopenidを加えるだけでなく、
response_typeを、response_type=id_token token, id_tokenに変更する必要がある。

<a href="http://(汎用認証サイトのアドレス:ポート)/MultiPurposeAuthSite/Account/OAuthAuthorize?client_id=21c7769f16634dabaf14282602b9a5fc&response_type=id_token%20token&scope=profile%20email%20phone%20address%20userid%20aaa%20openid&state=vj9NCxij4L">開始</a>

SpringMVC(Java)でやる。

コチラを参考にする。


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS