前回 AzureAD で AppRoles で権限を作って、ユーザーに割り当てました。
続編の今回は、フロントエンドのサンプルアプリで認証するメモです。
Azure AD を設定する上で一番重要と思っている Azure AD の "サポートされているアカウントの種類" とプログラム内の "Authority" の関係 についてもふれています。
- サンプルコードのダウンロード
- Azure AD にて "アプリの登録" のセットアップ
- サンプルプログラムを編集
- サンプルコードの実行
- Azure AD の "サポートされているアカウントの種類" とプログラム内の "Authority" の関係
- おわりに
- 参考ドキュメント
サンプルコードのダウンロード
フロントエンド側の作成は本質じゃないので公式のサンプルコードを使います。以下 GitHub の Repository からコードをクローンします。
このサンプルを選んだのは、まず認証フローが Authorizaition code grant with PKCE だからです。Implicit flow は今からやるのに選択肢としてないかと(がっつり個人的な見解です)。
余談ですが、Authorizaition code grant flow はマイクロソフトのドキュメントだと「承認コードフロー」とか「認証コードフロー」とか翻訳されてますが... OAuth 的には 認可コードフローだよね感があります。日本語の揺れがめんどいので、ここでは Authorization Code grant flow って言っておきます(with PKCE もつくのが当然になってるので省略...)。
Azure AD にて "アプリの登録" のセットアップ
今回大事なことなので何度も書きますが、Authorization Code grant でやります。
まずは、Azure Portal で Azure AD を開き、アプリの登録 > 対象のアプリ(前回作って AppRoles を設定したやつ)をクリックします。
開いた画面で 認証 > プラットフォームの追加 で シングルページアプリケーション を選択します。
(この選択を間違えると、フロントエンドから認証した際に CORS のエラーが出ます。)
今回のサンプルコードでデバッグした時に http://localhost:3000
を listen しますので、リダイレクト URI には http://localhost:3000
を入力します。そして画面上部の 保存 をクリックします。
保存後、サポートされているアカウントの種類 で「この組織ディレクトリに含まれるアカウント...」を選択して保存します。
この選択と、後述するプログラム側で設定する Authority の組み合わせ方が正しくないとトークンが取得できなかったり別のトークンが取れたりしますので注意です。
サンプルプログラムを編集
まず、入力する値は Azure AD の "アプリ登録" で作成したアプリの画面の 概要 の中にありますので開いておきましょう。
サンプルプログラムのルートディレクトリを VS Code で開き、authConfig.js
を開きます。
msalConfig
を定義しているのが3つ(6-8行目)を、以下を参考に入力します。
clientId
: アプリケーション (クライアント) IDauthority
:https://login.microsoftonline.com/
+ ディレクトリ (テナント) ID の値。例としてテナントIDがa1234567-abcd-1234-11aa-b515ea8541d4
なら入力する値はhttps://login.microsoftonline.com/a1234567-abcd-1234-11aa-b515ea8541d4
redirectUri
: 前述で設定したリダイレクト URI と同じ値:http://localhost:3000
サンプルコードの実行
VS Code のターミナルで npm install
して npm start
をしましょう。で私は...エラー?port の 3000 を使ってるだと?となりました。
curl localhost:3000
叩いたら...なんかいるやん...
日頃の行いが悪いようです💀... ぶっころす。
気を取り直して npm start
...👍。
Chrome で http://localhost:3000
を開きます。とりあえず F12
キーを押してデベロッパーツールを開いておきましょう。
で、Sign In ボタンをクリックしてサインインしましょう。
💉 エラーが起きてしまったらデベロッパーツールの Console タブ見てエラーを確認しましょう。
- CORS のエラーなら、前述の プラットフォームの追加で シングルページアプリケーション以外を選んで死んでます、たぶん。
- その他のエラーは、後述の Azure AD の "サポートされているアカウントの種類" とプログラム内の "Authority" の関係 を見ると問題解決をブーストできるかもしれません。
設定に問題なければこんな感じで名前が表示されます。
デベロッパーツールを見てみましょう。トークンが保存されているのは、Application タブ > Session Storage の http://localhost:300
の中にある {authority....
で始まる行です。クリックすると、各種トークンが見えます。
idToken の値をコピペして jwt.io のサイトでデコードしてみましょう。設定したロールが含まれています👌。
このトークンを使って ASP.NET Core の Web API で良い感じに認可の仕組みを構築できます。
その話に入る前に、Azure AD を設定してうまく認証できない要因と感じているポイントについて プチ Deep Dive ? メモです。
Azure AD の "サポートされているアカウントの種類" とプログラム内の "Authority" の関係
この2つを理解しておかないと、場合によってはエラーの闇に飲み込まれて心がダークサイドに落ちます(意味不明)。
以下の構成になっていることを前提に話を進めましょう。
- 今回 AppRoles とか今回のシリーズで設定している Azure AD は Beachside-Sandbox-AAD です。Other-AAD で AppRoles の設定はしてません。
- フロントエンドのアプリは Beachside-Sandbox-AAD の情報を authConfig に書いてます(前述で設定した内容のことです)。
- Other-AAD のユーザー: user-A を Beachside-Sandbox-AAD にゲストユーザーとして追加しています。
- Other-AAD のユーザー: user-B は Beachside-Sandbox-AAD に招待していません。
サポートされているアカウントの種類
"サポートされているアカウントの種類" の設定は、Azure ポータルで Azure AD を開く > アプリの登録 で今回のアプリをクリック > 認証 をクリックして設定できます。
設定できるのは上図の通り2択です。シングルテナント(上の方)かマルチテナント(下の方)。
- シングルテナントを選ぶと、Beachside-Sandbox-AAD に存在するユーザーしか認証できません(そりゃそうだ)。user-A はログインできる権利を得ます。use-B はログインできません。
- マルチテナントを選ぶと、user-A だけでなく Beachside-Sandbox-AAD に存在しない user-B もログインできる権利があります(え?マジ?ほんとです)。
ここで "ログインできる権利" と書きました。最終的にログインできるかどうかは、シングルテナント と マルチテナントのどちらを設定したかと Authority の設定次第になります。
Authority の設定
Authority は、今回のサンプルアプリだと authConfig.js の中でmsalConfig オブジェクトの中で設定しています。
Authority の値は https://login.microsoftonline.com/???
です。??? に何を入れるとどうなるかを説明していきましょう。
シングルテナントの場合
??? に Beachside-Sandbox-AAD のテナントID を設定:
今回設定したのがこれです。トークンは、Beachside-Sandbox-AAD の情報です。Beachside-Sandbox-AAD で AppRoles を定義してるので、user-A に割り当てた AppRoles の情報が出力されます。トークンをデコードした時に確認できる oid (オブジェクト ID) や name は、Beachside-Sandbox-AAD で付与されたオブジェクト ID や name になります。??? に "organizations" を設定:
ユーザーが所属する大元の AAD の情報がトークンに入ります。つまり Other-AAD の情報です。user-A でログインしてトークンをデコードして確認すると、oid や name が Other-AAD のユーザーの情報であることが確認できます。この設定だと Beachside-Sandbox-AAD で AppRoles をどんだけ設定しても、トークンの情報は Other-AAD の内容なので、AppRoles は常に空っぽです。
シングルテナントの設定をしていると、Authority でどんな設定をしても Beachside-Sandbox-AAD に存在しない user-B はログインできません。
マルチテナントの場合
マルチテナントを設定をすると user-A はもちろんログインできます。そして Beachside-Sandbox-AAD に存在しないユーザー、例えば Other-AAD の user-B もログインする権利を得ます。
先ほど同様に https://login.microsoftonline.com/???
の "???" に何を入れるかについては、
??? に Beachside-Sandbox-AAD のテナントID を設定:
トークンには Beachside-Sandbox-AAD の情報が入ります。Beachside-Sandbox-AAD に存在する user-A は先ほど同様にログインで、AppRoles の情報もあります。user-B は Beachside-Sandbox-AAD に存在しないためトークンを取得することができません。ログインする権利はあるけどこの設定ではログインできないのです。??? に "organizations" を設定:
user-A でログインすると、シングルテナントの時同様でトークンは Other-AAD の情報になります。つまり AppRoles の情報はありません。そして Other-AAD に存在する user-B でのログインが可能になります。この設定では user-A でも user-B でも Beachside-Sandbox-AAD で設定した AppRoles は使えません。
設定したのに認証できなかったり期待するトークンが取れない場合、ここを理解しておけば OK でしょうかね。
さっきも触れましたが、エラーが起きたときは Chrome のデベロッパーツールにエラーが表示されます。Authority でなんかおかしいって表示がでた場合は、そのテナントIDがどの Azure AD をさしてるかを確認して(ゲストで招待した AAD か大元の AAD かでしょう)、設定を確認しましょう。
Authority の設定では、他にcommon や consumers も設定できますが似たような話なのでここでは触れません。ここを理解すれば、後述の参考ドキュメントをみるとすぐわかります。
おわりに
AppRoles が含まれたトークンを取得できることがやりたいことなので、サンプルコードのチュートリアルにある graph API へのアクセスとかはここでは触れません。
今回は、Authorization Code grant flow の話ですが、Implicit grant flow だと若干設定が異なるので Implicit flow のドキュメントをチェックしましょう。
次回は ASP.NET Core の Web API を作成して認証・認可をします。