- 記事一覧 >
- ブログ記事
MSAL Reactを使用してサインインするSPAをAzure Static Web Appsにデプロイ
はじめに
MSAL を使って Azure Active Directory (Azure AD) のユーザーでサインイン(ログイン)できるシングルページアプリケーションを Azure Static Apps にデプロイしました。
とは言っても、自力でアプリを実装した話ではなく、公式サンプルのソースコードをデプロイしただけです。デプロイ手順は、公式サンプルにあるチュートリアルを実施しました。
それだけの場合、チュートリアルを読めば分かる話ですが、気を付けないといけないこと等ありましたので、この記事に書くことにしました。
さらに、本家には無い画面の画像を使って説明してきます。本家に載っていないことも書いています。
この記事にソースコードの説明は有りません。
2022/07 現在の内容をベースにしています。
今回、サインインするユーザーは、会社や組織のアカウントを想定し、Azure AD を使用します。"Azure AD" は、一般ユーザー(Googleアカウントなど)を扱う Azure AD (B2B) の事ではありません。
作業にあたり、前提としては、以下になります。
・Azure AD テナント作成済み
・操作している人は、Azure AD テナント管理ができたり、Azure Static Web Apps にアプリをデプロイできるものとします。
・今回操作対象のテナントには、サインインできるユーザーアカウントがあるものとします。(操作している人でも良いですが。)
・VS Code(Visual Studio Code) インストール済み
・VS Code に Azure Static Web Apps 拡張機能 インストール済み
・GitHub アカウント登録済み(リポジトリ作成可)
・Azure-Samples/ms-identity-javascript-react-tutorial4-Deployment/2-deploy-static のソースコード群が D:\sample
に配置済みとします。(配置場所はどこでも良いです。)
用語まとめ
【 MSAL 】
Microsoft Authentication Library(MSAL)は、マイクロソフト社提供の認証セキュリティ系機能を提供するライブラリです。
MSAL は、.NET、JavaScript、Java、Python、Android、iOS などの、さまざまなアプリケーション アーキテクチャとプラットフォームをサポートします。
MSAL は Azure AD および Azure AD B2C の両方に対応しています。
【 React 】
React (リアクト) は、Meta(旧Facebook)とコミュニティによって開発されているユーザインタフェース構築のためのJavaScriptライブラリです。
Reactはシングルページアプリケーションやモバイルアプリケーションの開発におけるベースとして使用することができます。
【 SPA 】
シングルページアプリケーション(single-page application、SPA)とは、単一のWebページのみから構成することで、デスクトップアプリケーションのようなユーザ体験を提供するWebアプリケーションまたはWebサイトです。
【 Azure AD 】
Azure Active Directory (Azure AD) は、クラウドベースの ID およびアクセス管理サービスです。
テナント/ディレクトリ、サブスクリプション、リソースなどの用語が有ります。それぞれを詳しく知るには、他の記事をあたった方が良いですが、ざっくりとした関係性は以下のMicrosoft公式ドキュメントの図のようになります。
画像リンク元:Azure 課金プランと Active Directory Domain Services テナント - 設計領域の概要
画像リンク元:従来のサブスクリプション管理者ロール、Azure ロール、および Azure AD ロール - 各ロールの関係
【 Azure Static Web Apps 】
Azure Static Web Apps は、コードリポジトリ(GitHub)から Azure に静的 Web アプリを自動的にビルドしてデプロイするサービスです。
APIは、
api/*
(例:api/HelloUser/index.js
) に実装すると、Azure Functions にデプロイされて、動的になります。
シナリオ
1.クライアントアプリケーションは、MSAL Reactを使用してユーザーにサインインし、Azure ADからJWT アクセストークンを取得します。
2.アクセストークンは、POSTリクエストを使用して Function API(/api/HelloUser)に送信されます。
3.Function API は、アクセストークンを検証し、Azure AD から新しいアクセストークンを取得します。
4.Function API は、新しいアクセストークンを Microsoft Graph API への Bearer トークン として使用します。(Authorization: Bearer
ヘッダに載せる)
5.Microsoft Graph APIが応答し、Function API がそれをクライアントアプリケーションに伝播します。
【 JWT 】
JSON Web Token(ジェイソン・ウェブ・トークン)は、JSONデータに署名や暗号化を施す方法を定めたオープン標準 (RFC 7519) です。
【 Microsoft Graph API 】
Azure Active Directory で管理されている様々なデータにアクセス可能なAPIです。主なAPIの機能として、Azure Active Directory で管理されているOffice365のデータへのアクセスが可能です。
【 Bearerトークン 】
Bearer(ベアラー)=(小切手・手形の)持参人。
BearerトークンはBearer(それを持ってきた存在)にアクセス権限を与える特性を持ちます。
On-behalf-of (OBO)フロー
本家チュートリアルでは、詳しく触れられていませんが、Profile、FunctionAPI とでは、フローが異なります。
Profile
Microsoft Graph API を直接呼び出しています。
FunctionAPI
Azure によって保護された自前の API から Microsoft Graph API を呼び出しています。(Microsoft Graph API はサインインした人から呼び出されていません。)上記シナリオは、こちらのことです。
【 On-behalf-of (OBO) 】
OAuth 2.0 の On-Behalf-Of (OBO) フローは、アプリケーションがサービス/Web API を呼び出し、それがさらに別のサービス/Web API を呼び出す必要のあるユース ケースに対応します。
アプリの登録
Azure AD のテナントに SPA アプリ(Reactと/api/hello
)の情報について登録します。
アプリのソースコードを登録したりとか、インストールしたりとかの意味ではありません。
1.
Azure ポータル(https://portal.azure.com/
)にアクセスして、Azure Active Directory をクリックします。
2.
アプリの登録 → 新規登録 をクリックします。
3.
アプリ情報を入力します。
名前:msal-react-spa
サポートされているアカウントの種類:この組織ディレクトリのみに含まれるアカウント (<テナント名> のみ - シングル テナント)
リダイレクト URI (省略可能):シングルページアプリケーション (SPA)
http://localhost:3000/
リダイレクト URIは、アプリのURLで、今回、Azure Static Appsにデプロイし、http://localhost:3000/ ではないため、後で変える手順があります。
4.
登録 をクリックします。
5.
アプリケーション (クライアント) ID、ディレクトリ (テナント) ID が表示されます。これは、後で設定するところで必要になります。この アプリの概要 画面で何度でも確認できます。
6.
原文は、
6.Select Save to save your changes.ですが、それにあたる操作はありませんでした。 (アプリの登録は完了しています。)
アプリの登録 からアプリを作成したら、“エンタープライズ アプリケーション“ も同時に作成されます。
このエンタープライズ アプリケーションは、“サービス プリンシパル“ と呼ばれるオブジェクトです。
正確にはエンタープライズ アプリケーションがサービス プリンシパルの一種ですが基本的には “サービス プリンシパル” と “エンタープライズ アプリケーション”はほぼ同義だと考えて OK です。
7.
アプリの概要 画面のまま、左側にある 証明書とシークレット をクリックします。証明書とシークレット 画面は、シークレットを作成したり、証明書をアップロードできる画面です。
8.
クライアントシークレット を選択して、新しいクライアントシークレット をクリックします。
説明:app secret
有効期限:12 ヵ月
(任意)
とし、追加 をクリックします。
追加し終わると、値 と シークレット ID が表示されます。これは、他の画面に移ると、二度と表示されませんので、どこかへコピーペーストしておく必要があります。
後で必要になるのは、値 の方です。
9.
左側から API の公開 をクリックし、Scope の追加 をクリックします。
ここで言うAPIとは、自分のAPI
/api/hello
のことです。
アプリケーション ID の URI が api://{clientId}
で表示されるため、そのままにして、保存してから続ける をクリックします。
10.
API の URI に加えて、スコープを定義する必要があります。
以下のように入力します。
スコープ名:access_as_user
同意できるのはだれですか?:管理者とユーザー
管理者の同意の表示名:Access msal-react-spa
管理者の同意の説明:Allows the app to access msal-react-spa as the signed-in user.
ユーザーの同意の表示名:Access msal-react-spa
ユーザーの同意の説明:Allow the application to access msal-react-spa on your behalf.
状態:有効
入力したら、 スコープの追加 をクリックします。
結果、
api://アプリケーションID/access_as_user
が世界の誰とも重複しないスコープ名になります。
11.
左側から API のアクセス許可 をクリックして、アプリケーションに必要な API へのアクセス許可を追加するページを開きます。
Microsoft Graph API への User.Read アクセス許可設定は、デフォルトで追加されていますので、そのままにします。
クライアント(React)から自分のAPI へアクセスをできるようにします。
Microsoft Graph API への User.Read スコープ(ユーザー情報取得)のアクセスは最初から登録されていて、最初からクライアント(React)からアクセスできるようになっているということです。
アクセス許可の追加 をクリックします。
自分の API をクリックします。
msal-react-spa
をクリックします。
アプリケーションに必要なアクセス許可の種類:委任されたアクセス許可
とし、アクセス許可:access_as_user Access msal-react-spa にチェックを入れて、アクセス許可の追加 をクリックします。
12.
左側から マニフェスト をクリックして、
"accessTokenAcceptedVersion": null,
を
"accessTokenAcceptedVersion": 2,
に変更後、保存 をクリックします。
https://login.microsoftonline.com/
を使うから、2 です。/oauth2/v2.0/
デプロイ
本家チュートリアルでは、デプロイの前に
App/src/.env
の変更手順がありますが、.env
が commit されないため、その手順は、スキップします。環境変数は、後で設定します。
前提 の通り、
Azure-Samples/ms-identity-javascript-react-tutorial4-Deployment/2-deploy-static のソースコード群が D:\sample
に配置済みとします。(配置場所はどこでも良いです。)
1.
App フォルダ内で、VS Code を開いて、ソース管理 → リポジトリを初期化する をクリックします。
initial commit
のようにコミットメッセージを入力して、コミットをクリックします。
2.
App フォルダ内で、VS Code を開いて、Azure → Sign in to Azure... をクリックして、Azure にサインインします。(既にサブスクリプションが表示されている場合は、サインインしていますので、不要です。)
3.
Create Resource → Create Static Web App... をクリックします。
GitHub と連携していない場合、GitHub へのサインインが行われます。
↓
↓
↓
Web アプリ名を入力し、エンターキーを押します。(以降同様に、入力後、エンターキーが必要です。)
GitHub リポジトリ名を入力します。(この名前で push されます。)
4.
GitHub にリポジトリが作成されて、ソースコード群が push されます。
push がトリガーとなり、GitHub Actions が起動して、Azure Static Web Apps への自動デプロイが開始されます。https://github.com/<github account>/react-test-spa/actions
で状況確認ができます。
静的 Web アプリ → react-test-spa
にてデプロイされた URL が確認できます。
アプリの登録 更新
正式な URL が分かったため、アプリの登録を更新します。
1.
Azure ポータル(https://portal.azure.com/
)にアクセスして、Azure Active Directory をクリックします。
2.
左側から アプリの登録 をクリックします。
3.
登録済みアプリの msal-react-spa
をクリックします。
4.
左側 ブランド化とプロパティ から、ホーム ページ URL に デプロイしたアプリの URL を入力して、保存 をクリックします。(例:https://reactspa1.z22.web.core.windows.net/
)
URLは、以下の部分です。
5.
左側 認証 をクリックして、リダイレクト URI に デプロイしたアプリの URL を追加して、保存 をクリックします。
環境変数の登録
1.
Azure ポータル(https://portal.azure.com/
)にアクセスして、静的 Web アプリ をクリックします。
2.
作成したアプリ react-test-spa
をクリックします。
3.
左側から 構成 をクリックして、アプリケーション設定 → 追加 にて、以下の環境変数を追加していきます。
CLIENT_ID: b2b9de9e-****-****-****-************
アプリの登録 → msal-react-spa
→ 概要の アプリケーション (クライアント) ID です。
TENANT_INFO: 2670387a-****-****-****-************
アプリの登録 → msal-react-spa
→ 概要の ディレクトリ (テナント) ID です。
CLIENT_SECRET: S_a8Q~s*********************************
クライアントシークレットで表示された 値 です。(シークレット ID ではありません。)
EXPECTED_SCOPES: access_as_user
API の公開で設定したスコープ名です。(access_as_user
で良いです。)
追加したら、保存 をクリックします。
これは、APIが参照する環境変数です。(画面側は、参照してなく、Staticのため、即時反映されず、今設定しても無意味です。)
この手順は、本家のチュートリアルに無いのですが、(本家の方は、.env
を設定していますが、この手順では push されません。)React をビルドするときの環境変数を設定します。
GitHub のリポジトリへアクセスして、Settings → Secrets → Actions をクリックします。
New repository secret から
REACT_APP_AAD_APP_CLIENT_ID=b2b9de9e-****-****-****-************
アプリの登録 → msal-react-spa
→ 概要の アプリケーション (クライアント) ID です。
REACT_APP_AAD_APP_TENANT_ID=2670387a-****-****-****-************
アプリの登録 → msal-react-spa
→ 概要の ディレクトリ (テナント) ID です。
REACT_APP_AAD_APP_REDIRECT_URI=https://mango-water-******************************
アプリの登録 → msal-react-spa
→ 認証のリダイレクト URI です。
REACT_APP_AAD_APP_FUNCTION_SCOPE_URI=api://b2b9de9e-****-****-****-************
API の公開で設定したスコープ URI です。/access_as_user
はソースコードに書かれているため、/access_as_user
無しで設定します。
を設定していきます。
設定し終わったら、VS Code の Azure → Static Web Apps → react-test-spa
のところで、右クリックして、Edit Workflow... をクリックします。
name: Build and Deploy Job
のところに、以下を追記します。
env:
REACT_APP_AAD_APP_CLIENT_ID: ${{ secrets.REACT_APP_AAD_APP_CLIENT_ID }}
REACT_APP_AAD_APP_TENANT_ID: ${{ secrets.REACT_APP_AAD_APP_TENANT_ID }}
REACT_APP_AAD_APP_REDIRECT_URI: ${{ secrets.REACT_APP_AAD_APP_REDIRECT_URI }}
REACT_APP_AAD_APP_FUNCTION_SCOPE_URI: ${{ secrets.REACT_APP_AAD_APP_FUNCTION_SCOPE_URI }}
上書き保存して、ソース管理 → コミットしてプッシュ でリポジトリへ push します。 そうすると、再度ビルドが動き、上記で設定した環境変数が反映されます。
画面側(React)が参照する環境変数です。(Staticのため、ビルドするときに反映されます。)
終わったら、いよいよ動作確認に入れます。
動作確認
Sign in をクリックします。
Sign in using Popup(ポップアップがログイン画面) または、Sign in using Redirect(画面全体がログイン画面) をクリックします。(どちらでも良いですが、ポップアップの方は、ポップアップを許可する必要があるかもしれません。)
ちなみにですが、デプロイ先のテナントとアカウントとアプリ登録先のテナントは、別々のものでも動作します。(その場合、デプロイ先のテナントのアカウントではサインインできません。)
その他、宣伝、誹謗中傷等、当方が不適切と判断した書き込みは、理由の如何を問わず、投稿者に断りなく削除します。
書き込み内容について、一切の責任を負いません。
このコメント機能は、予告無く廃止する可能性があります。ご了承ください。
コメントの削除をご依頼の場合はTwitterのDM等でご連絡ください。