【Microsoft ID プラットフォーム】(Azure AD) シングルページ アプリ（SPA）の検証-Node.js編-

はじめに（背景)
------------------------------------
Office365を導入して、数年が経ちました。
皆様が慣れてきて、そろそろ、Office365とのシングルサインをすれば、便利になるんじゃない！！との声が出来てきました。そして、上司から、"Single Sign On よろしく！"との恐ろしい声がかかりました。

確かにIDaaSとしてのAzure ADは既に稼働しているので、後は、連携するアプリケーションの準備が出来れば可能ですが、、、このオンプレWebアプリケーションとIDaaSとのSSOは敷居が高い。

なぜなら、アプリケーション側でSAML/OpenIDConnect/OAuthとおしゃべりができないので、改修が必須となる。そこで、Microsoft ID プラットフォームを使えば、ライブラリが提供されているので、これをうまく活用すれば、SSOの敷居が少しでも低くるなると考え、検証を開始致しました。

Microsoft ID プラットフォーム 
------------------------------------

『Microsoft ID プラットフォーム (旧称: 開発者向け Azure Active Directory)』

https://docs.microsoft.com/ja-jp/azure/active-directory/develop/

>Microsoft ID プラットフォームは、Azure Active Directory (Azure AD) 開発者プラットフォームの進化版です。 これにより、すべての Microsoft ID にサインインして、Microsoft API (Microsoft Graph) や開発者が構築した API を呼び出すためのトークンを取得するアプリケーションを開発者が構築できます。 これはフル機能を備えたプラットフォームであり、OAuth 2.0 および OpenID Connect 標準に準拠した認証サービス、オープンソース ライブラリ、アプリケーションの登録および構成、充実した概念とリファレンスのドキュメント、クイック スタート サンプル、コード サンプル、チュートリアル、攻略ガイドによって構成されています。

ふむふむ。確かにサンプルコードがあるので、できそうかも。。。

いざトライ！！
----------------------------------

###1.参照ページ

『クイック スタート:JavaScript SPA 内でユーザーをサインインさせ、アクセス トークンを取得する』
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-v2-javascript

###2.登場人物

1.Identity Provider (Azure AD)
  * オンマイクロソフトアカウントを使います。
2.Relying Party (JavaScript Single Application)
　* Node.js (事前の準備をお願い致します。インストール方法は割愛させて頂きます)
  * サンプルコード (以降の手順でダウンロード致します。)
3.Web API (Microsoft Graph API)
  * サインインのユーザー情報取得に使います。

###3.手順

####◆手順 1:アプリケーションの登録

1.Azure portal(https://portal.azure.com) にサインインします。

2.[ホーム]-> [Azure AD Active Directory] -> [アプリの登録]へ進む。 
<img width="200" alt="1.appregi.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/8d75c830-4f28-35ef-be54-f58a4145a4de.png">

3.[新規登録] をクリックします。
<img width="300" alt="2.appnew.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/24c0ed32-203a-6065-331b-f077da76ca61.png">

4.アプリケーション登録で下記項目を選択して、[登録]をクリック。
(1).名前欄：任意のアプリケーション名を入力
(2).サポートされているアカントの種類：この組織ディレクトリのみに含まれるアカウント
(3).リダイレクトURL：空白　=> (後ほど、入力されます。)

<img width="500" alt="3.newregi.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/ae30b0ba-61c5-c75a-c91c-58bac0508593.png">

5.登録したアプリケーションが表示されますので、[クイックスタート]をクリック。

<img width="500" alt="4.quickstart.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/2eeb8076-4907-9de3-f57f-a5fd7878e7be.png">

6.シングルページアプリケーションの[JavaScript]をクリック。

<img width="500" alt="5.Java Scriptを選択.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/689b1546-1ed1-c19b-a499-a735a0e6e08f.png">

7.[これらの変更を行います]をクリック

<img width="500" alt="6.change.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/8c29244f-4db0-f095-848a-119c5c7442d7.png">

8.下記構成内容が表示されますので、[更新する]をクリック。
(1).リダイレクト URI : http://localhost:30662 
(2).アクセストークン・IDトークン：Ture
*上記トークンは、インプリシットフローで利用するトークンとなります。

<img width="500" alt="8.app registration-URL.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/e1ada910-df1c-1ca9-0609-0deae5278926.png">

*下記の[認証]画面から構成の反映を確認可能です。

<img width="500" alt="7.Authentication.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/2bbc064d-a384-cf08-9374-fe6d74879193.png">

####◆手順 2:プロジェクトのダウンロード

1.Node.js を使用して Web サーバーでプロジェクトを実行致しますので、コアプロジェクトファイルをダウンロードします。 

コアプロジェクトファイル：active-directory-javascript-graphapi-v2-quickstart.zip

<img width="406" alt="9.ダウンロード.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/b552e86b-1ee2-8143-0e84-7dcd5c4dc157.png">

2.ダウンロードした zip ファイルを任意のフォルダに解凍致します。
下記は、[C:\tmp\active-directory-javascript-graphapi-v2-quickstart]の例となります。

<img width="500" alt="10.ファイル解凍.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/4235cb02-827d-1b3b-eed5-19f46421e587.png">

####◆手順 3:JavaScript アプリの構成

1.任意のフォルダに解凍したファイルの中のJavaScriptSPAフォルダーのindex.html を編集し、msalConfig を置き換えます。

<img width="500" alt="11.indexファイル編集.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/8a764660-bdf8-4552-de7c-54d8c5cbc8c8.png">

```javascript

const msalConfig = {
    auth: {
        clientId: "5c1e11c4-4d6d-4396-be85-c3f435dd3ada",
        authority: "https://login.microsoftonline.com/a94216cd-7c42-4b24-8ba0-ce5c210951bd",
        redirectURI: "http://localhost:30662/"
    },
    cache: {
        cacheLocation: "localStorage",
        storeAuthStateInCookie: true
    }
};
```
*実際の値はお客様環境により異なりますので、適宜編集をお願い致します。
*クイックスタート画面では、varで案内されておりますが、プロジェクトファイルは、constとなっております。どちらも変数を宣言することに変わりはないので、続きの手順は、constで進んでおります。
<img width="165" alt="12-1.varmsalconfig.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/76d1c982-de00-b909-d09d-a4635adf9fdb.png">

####◆手順 4:プロジェクトを実行する

1.[スタート]-> [Node.js]->[Node.js command prompt]の順にクリックします。

<img width="195" alt="13.Nodejs.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/6371dd02-bc52-5754-9a24-464f4bc96196.png">

2.active-directory-javascript-graphapi-v2-quickstart ディレクトリで、以下コマンドを実行し、30662のportを起動します。

>npm install
>node server.js

<img width="491" alt="14.nodejs2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/99e87c92-33a5-f7c9-2c97-65c0fa83aa06.png">

####◆手順5: サインイン

* 認証の流れを確認する為に、Fiddler でパケットを取得!!
* 暗黙的な許可のフローを確認

https://docs.microsoft.com/ja-jp/azure/active-directory/develop/v2-oauth2-implicit-grant-flow
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/75af2d49-9ed7-549c-ff90-9d7237fe4d79.png)

*ダウンロードしたコアプロジェクトサンプルの仕組み
<img width="500" alt="flow.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/7300af06-649a-4a17-ef2e-91685d3e7aa4.png">

>msal.js
MSAL ライブラリは、ユーザーをサインインさせ、Microsoft ID プラットフォームによって保護された API へのアクセスに使用されるトークンを要求します。 クイックスタートの index.html ファイルにはこのライブラリへの参照が含まれています。"https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/msal.min.js"

(1).http://localhost:30662/ へアクセスして[Sign In]をクリック

<img width="300" alt="15.signin.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/e78e8a68-23a2-3768-a237-c97416d2844b.png">

(2).認可エンドポイント(/oauth2/v2.0/authorize)へリダイレクト

```
GET https://login.microsoftonline.com/a94216cd-7c42-4b24-8ba0-ce5c210951bd/oauth2/v2.0/authorize?response_type=id_token
&scope=user.read openid profile
&client_id=5c1e11c4-4d6d-4396-be85-c3f435dd3ada
&redirect_uri=http://localhost:30662/
&state=89bf09ea-d9bd-417c-92ff-81f30d1ab6a2
&nonce=011779c1-154d-4d05-85fd-374a2af4e1c1
&client_info=1
&x-client-SKU=MSAL.JS
&x-client-Ver=1.0.0
&client-request-id=cb77df46-36b4-4395-b926-7e39d87cc31f
&response_mode=fragment
&sso_reload=true HTTP/1.1
Referer: https://login.microsoftonline.com/a94216cd-7c42-4b24-8ba0-ce5c210951bd/oauth2/v2.0/authorize?
```

(3).ログイン画面が表示され、ユーザー名とパスワードを入力

<img width="300" alt="16.signin.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/388731c3-8620-32f1-793b-00b600d2422d.png">

<img width="300" alt="17.signin.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/14945d77-7a13-73c5-a6ad-95167ebe4617.png">

(4).要求されているアクセス許可を問われるので、[承諾]をクリック。

<img width="300" alt="18.signin.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/2d142206-cb9a-41f0-26db-5c7781f54b27.png">

(5).[承諾]を行うとアクセストークンと IDトークンがユーザー宛に発行されます。

★ID Token
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/b4b04537-8781-8918-ac4b-b3a4cfdaa6d9.png)

```
http://localhost:30662/#id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkhsQzBSMTJza3hOWjFXUXdtak9GXzZ0X3RERSJ9.eyJhdWQiOiI1YzFlMTFjNC00ZDZkLTQzOTYtYmU4NS1jM2Y0MzVkZDNhZGEiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vYTk0MjE2Y2QtN2M0Mi00YjI0LThiYTAtY2U1YzIxMDk1MWJkL3YyLjAiLCJpYXQiOjE1ODA5NjI2NDEsIm5iZiI6MTU4MDk2MjY0MSwiZXhwIjoxNTgwOTY2NTQxLCJhaW8iOiJBVFFBeS84T0FBQUFUQ3cxOGFMeXhGRmlCVDU4SW1FY0xiR2dPaDE1V201VmdtV210bk5DNG44Q1JEYkRla24xdDh1YzZTK0hqY2ptIiwibmFtZSI6InRlc3QxIiwibm9uY2UiOiIwMTE3NzljMS0xNTRkLTRkMDUtODVmZC0zNzRhMmFmNGUxYzEiLCJvaWQiOiJkY2Y2OWI3ZS0yYzY3LTQ2NTgtODVhYy1kYzAxYWVjODcxMmYiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0MUBnaW52aXRhdGlvbjFvdXRsb29rLm9ubWljcm9zb2Z0LmNvbSIsInN1YiI6IkRYb0dhMmJGY0IwOUFCOXlUNWZ2MkVsaUNvZGVsRmxMQXFtWVRuUDBnUnciLCJ0aWQiOiJhOTQyMTZjZC03YzQyLTRiMjQtOGJhMC1jZTVjMjEwOTUxYmQiLCJ1dGkiOiJYOF9FOVBEcTBFbTlfV1RfNHpVZEFBIiwidmVyIjoiMi4wIn0.GRxmgmbGjh21mIt6KtV5YU8AWQBKBPaV6tLE-v2sbt0jSNhGUbvHnAsyiNjGEspz5FdVjt6iZYh_YfSKC-k1TJ0KT8oalHgpWtGHyy7iQAW5W8d_Vk2IxZXgL6uQkCEMmouHtB6aXqT-HGnInmwNWYPUvOLltb2aV4cfhvYuS5qItPow_99cfgqcEUJ7554TqlITpxivsC9Pk8bj1wb1mmosu16UiJnQuj6gkDcTkSqppZGtfUqtyGukj6O_GmLCL7zmS5Dj_YiiehEAtOb19lHQhT9YcISuv_MfHeMmD8GO-hMS77cMrBBcI53SwuPFdzIM6oqHKItiMOFmYtMaBw&client_info=eyJ1aWQiOiJkY2Y2OWI3ZS0yYzY3LTQ2NTgtODVhYy1kYzAxYWVjODcxMmYiLCJ1dGlkIjoiYTk0MjE2Y2QtN2M0Mi00YjI0LThiYTAtY2U1YzIxMDk1MWJkIn0&state=89bf09ea-d9bd-417c-92ff-81f30d1ab6a2&session_state=696af646-afd2-4dd9-b8ca-444174edb797
```

上記IDトークンをコピーして、https://jwt.io へ貼り付けると、ヘッダー、ペイロード、署名が確認できます。

<img width="902" alt="jwt.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/703a93cd-9761-2cc4-7d5a-df0f04805a5f.png">

(6).リダイレクトURIに遷移してaccess_tokenを送付。

★access_token
![New_Feddler_(Access-token).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/d2196661-e6e1-7633-44ec-30d809f0546e.png)


```
http://localhost:30662/#access_token=eyJ0eXAiOiJKV1QiLCJub25jZSI6Ill5QVpZTExvdDBQdE1mWUJoN1hKd2hHNHJGZUZmY1IxN3IwNU4zZGpoVTQiLCJhbGciOiJSUzI1NiIsIng1dCI6IkhsQzBSMTJza3hOWjFXUXdtak9GXzZ0X3RERSIsImtpZCI6IkhsQzBSMTJza3hOWjFXUXdtak9GXzZ0X3RERSJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9hOTQyMTZjZC03YzQyLTRiMjQtOGJhMC1jZTVjMjEwOTUxYmQvIiwiaWF0IjoxNTgwOTYyNjQzLCJuYmYiOjE1ODA5NjI2NDMsImV4cCI6MTU4MDk2NjU0MywiYWNjdCI6MCwiYWNyIjoiMSIsImFpbyI6IkFTUUEyLzhPQUFBQVVOMFprMkwyZnJkZ1k4UlZrdnowbmZxRnFzRUM0MVkzK1NUR1htWkFYYmM9IiwiYW1yIjpbInB3ZCJdLCJhcHBfZGlzcGxheW5hbWUiOiJTUEEtTm9kZS5qcyIsImFwcGlkIjoiNWMxZTExYzQtNGQ2ZC00Mzk2LWJlODUtYzNmNDM1ZGQzYWRhIiwiYXBwaWRhY3IiOiIwIiwiZmFtaWx5X25hbWUiOiIxIiwiZ2l2ZW5fbmFtZSI6InRlc3QiLCJpcGFkZHIiOiIyMTAuMTMwLjI0MS45NyIsIm5hbWUiOiJ0ZXN0MSIsIm9pZCI6ImRjZjY5YjdlLTJjNjctNDY1OC04NWFjLWRjMDFhZWM4NzEyZiIsInBsYXRmIjoiMyIsInB1aWQiOiIxMDAzMjAwMDk3MEJCRTZDIiwic2NwIjoib3BlbmlkIHByb2ZpbGUgVXNlci5SZWFkIGVtYWlsIiwic3ViIjoiSG1IT1FCOEx0SUhQOS1kREFxTUFUdlA0MjVQRjBMR0JYQTFwS2hLbUlmQSIsInRpZCI6ImE5NDIxNmNkLTdjNDItNGIyNC04YmEwLWNlNWMyMTA5NTFiZCIsInVuaXF1ZV9uYW1lIjoidGVzdDFAZ2ludml0YXRpb24xb3V0bG9vay5vbm1pY3Jvc29mdC5jb20iLCJ1cG4iOiJ0ZXN0MUBnaW52aXRhdGlvbjFvdXRsb29rLm9ubWljcm9zb2Z0LmNvbSIsInV0aSI6ImthaTdkNHM1bkVpVDBwMDRNTWNiQUEiLCJ2ZXIiOiIxLjAiLCJ4bXNfc3QiOnsic3ViIjoiRFhvR2EyYkZjQjA5QUI5eVQ1ZnYyRWxpQ29kZWxGbExBcW1ZVG5QMGdSdyJ9LCJ4bXNfdGNkdCI6MTU1MjYzMjMwOH0.o_OGDeyUJB_oB6rKtW4MjFPWCQCkJ1TsKNuVQ3njoZ_jXUMVcPzcH_PHN6P5r1Yh8Y-eFidoTTppvMSMZUUhVoUpojDTq0XA78o57nsSKLNPDYbQ0Mzgz_43Ur-SgHB_H0h3xp64fHzwXBceVKSSpwegacgkPaIleT_kBgNrArzmwrPQCOB2DReZck15TeIZUr3vhw2bINkH16hvuZ8RDyVjNFy6YsMQ7OUhGows3iQCKmdBKfwn_wuAiIuvX4Wl0G5_JaBlc25xdoVrQEdtk3rHAeOnA4qHFwTn56PqmpRQ3rgEXIO9-PcN8890-_F3Ot7-iOb-GrD914xAlCsUfA
&token_type=Bearer
&expires_in=3599
&scope=openid+profile+User.Read+email
&client_info=eyJ1aWQiOiJkY2Y2OWI3ZS0yYzY3LTQ2NTgtODVhYy1kYzAxYWVjODcxMmYiLCJ1dGlkIjoiYTk0MjE2Y2QtN2M0Mi00YjI0LThiYTAtY2U1YzIxMDk1MWJkIn0
&state=ac5bb0ca-a243-4146-afd6-d23f87ac9ede
&session_state=696af646-afd2-4dd9-b8ca-444174edb797
```


(7).トークンを公開鍵を使って検証致します。
(8).認証が完了。

<img width="400" alt="19.signin.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579284/7944c8d7-a090-6bba-2565-d5a718935257.png">

まとめ
----------------------------------

Quick startを使うことにより、サインインまでの確認は、さほど、時間はかかりませんでしたが、トークンの確認に時間を要しました。

恐るべしOpen ID connect !!

次回は、Visual Studioを使ったSPAの検証を予定しております。

最後に、私の記事が少しでも、皆様の役に立てれば幸いでございます。