Azure AD で AppRoles を使って認証・認可をするのも、ようやく今回 ASP.NET Core (3.1)で Web API を作り、認証・認可を実現するターンです。 過去2つのブログでは
をしましたねーやることは少ないのにブログで書くと長かった。
今回作る Web API は UI を持たない Web API を想定しています。UI は React とか Vue とかで作るイメージです。
ASP.NET Core の実装
プロジェクトの作成
Visual Studio 2019 にて ASP.NET Core のプロジェクトを作りましょう。GUI で作成すると途中で以下のような画面になりますね。
今回は、以下の感じで進めます。
認証 は 「認証なし」で進めて自分でコード書きます。今回作るやつに UI はないし Azure AD の"アプリの登録" も設定済みなので、ここで設定して余計なものが自動生成されたくないってわけです。
ちなみに前提が異なる場合は、上図の認証を選択してやるとさくっと認証ができたりします。
appsettings.json
まずは環境変数の設定からしましょうか。
appsettings.json を開いて以下のように AzureAd
のオブジェクトを追加します。
よくあるサンプルだと TenantId
や Instance
がありますが、あれを元にAuthority を構成するだけだしそもそも Authority の値が何かを理解してないとやってられないと思ってるので、今回は実際に必要な Authority
と ClientId
だけの構成にしました。
{ "AzureAd": { "Authority": "", "ClientId": "" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" }
Authority
と ClientId
の値を入れましょう。
- Authority: 前回ブログでクライアント側の実装時に
msalConfig
に設定した Authority の後ろに/v2.0
をつけた値になります。msalConfig
に設定した値がhttps://login.microsoftonline.com/a1234567-abcd-1234-11aa-b515ea8541d4
なら今回入力する値は、https://login.microsoftonline.com/a1234567-abcd-1234-11aa-b515ea8541d4/v2.0
になります。 - ClientId: 前回ブログでクライアント側の実装時に
msalConfig
に設定した ClientId の値と一緒です。
Authority に "v2.0" と付けてますが、クライアント側は Msal.js がつけてくれてるだけで、クライアント/サーバーサイドの実際の値は同一です。
今回は雑に appsettings.json に書きましたが、場合に応じてにちゃんとやりましょう(WebApps にホストするならこんな感じとか...)。
Startup.cs
次は、Startup.cs を開いて以下のようにします。
恒例(?)のざっくりな解説いきましょう。
コードを追加したところには HACK:
から始まるコメントをつけています(using のどこを追加/削除したかはめんどくて書いてません)。
いくつかピックアップすると...
- 28行目: 今回追加する DI 絡みの内容のメソッドを呼んでます。
- 53-76行目 今回のポイントのひとつで、認証関連の設定です。いうてもシンプルなものですね。
- 58-59行目で appsettings に設定した値を取ってきてセットしてます。
- 64-67行目: トークンの validation をカスタマイズできます。
jwtOptions.TokenValidationParameters
は初期値がインスタンス化されているので、今回のようにインスタンスを new せずjwtOptions.TokenValidationParameters
のプロパティを直接操作しても問題ないです。後述の TokenValidationParameters のメモ にもうちょい役立つ情報を書いてます。
- 72-75行目: 認証エラーに時のイベントをカスタマイズしたときにはこんな感じで。この Events のカスタマイズは、デバッグ用途でプロダクションで使うものじゃないってイメージを持ってます。なので 63 行目でDev環境の時のみ設定するようにしました。
TokenValidationParameters のメモ
トークンの Validation をカスタマイズしたければ TokenValidationParameters
を設定をするって例で64-67行目で書いてみました。いたずらにトークンの有効期限チェックを無効にしてますのでうかつに真似しちゃあかんです。
トークンの Validation のデフォルトは以下の通りですので、自分で設定したプロパティがオーバーライドされます。
public TokenValidationParameters() { RequireExpirationTime = true; RequireSignedTokens = true; RequireAudience = true; SaveSigninToken = false; ValidateActor = false; ValidateAudience = true; ValidateIssuer = true; ValidateIssuerSigningKey = false; ValidateLifetime = true; ValidateTokenReplay = false; }
Controller で認証・認可
Controller をいじる前に、Azure AD の AppRoles で定義したやつらを定義しておきますか。前々回に設定した AppRoles の中で value
の値です。コードは以下になります。ブログに書いてなかったんですが、"Admin" は認可が通らないのを確認するためのおまけです。
本題の AppRoles を使った AuthZ です。前述の Startup.cs のようにしたことで、AuthN・AuthZ ができるようになります。SampleController
ってコントローラーを追加して以下のように実装しました。
コードにさらっとコメントを書いてるのでここで説明する要素があまりない...。
今回は、このコントローラー全体に認証はかけつつ、認可の設定をメソッド毎に書いてます。
今回のサンプルのような書き方のドキュメントは以下にあります。
今回くらいシンプルなコードならいいんですが...ロールの組み合わせに複雑さが出てくるとしんどくなるので、今回は触れませんがポリシーベースの認可を実装するのが実用的だと思っています。その辺のドキュメントはこちら。
ポリシーベースとか Requirement handlers とか、かなり前に下書きでブログ書きかけたけど公開せずに終わってるなぁ...😴
動作確認
動作確認は、雑にローカルデバッグだけを触れておきます。
API を投げるのに JS のサンプルコードいじるのもめんどかったので、VS Code の Rest Client で動かしてみましょう。
ID トークンを HTTP リクエストのヘッダーにセットする必要があります。ID トークンは前回のブログ でちょっと触れましたが、フロント側のサンプルコードを Chrome で実行して認証したらデベロッパーツールを起動して Application タブ > Session Storage から取得できます。あとは VS Code の Rest Client でドーン。
@id_token = IDトークンをセットする!!! GET https://localhost:5001/sample/b Authorization: Bearer {{id_token}}
実行すると、こんな感じで成功したり、
認可が通らないところは 403 が返ってきたり。
おわりに
ということで簡単に認証・認可ができました。
Azure AD の AppRoles を使わずに完全に独自実装で認可を実現する場合とどっちがいいかなー(ケースバイケースでしょうけど)。
自前でロールの管理する実装くらいは容易だしねー。認証はIDトークンで検証、認可は自作の Store をもとに検証って煩わしさ?はある?(今までずっとやってて困ったこともないけど)。
Azure AD の AppRoles 使えば、認証・認可をIDトークンのみで制御できるのはうれしい気がする。けど、IDトークンにロールが含まれるのでトークンをリフレッシュしないと反映されないとか、AAD の操作の実装もしないとならん(手作業で AAD の AppRoles の設定や権限付与をするとかやだー)。ということで一概に実装コストが減るわけでもなさそう。
MSAL.js でのトークンの ForceReflesh は Authorization Code grant と Implicit grant でちょっとだけコードが変わる(scope の設定)ので気づかないとハマるしね。
まーどっかでガチ運用してみて試せたらいいなと思います。
参考
Identity Platform 関連
認証・認可については理解しておいた方がよい...
docs.microsoft.com認証フローの理解は必要...
docs.microsoft.com
ASP.NET Core 関連
ASP.NET Core での認可の実装
ASP.NET Core でのロールベースの承認 | Microsoft Docs
ASP.NET Core でのポリシーベースの承認 | Microsoft Docs今回は全く参考にしてないけど、Azure AD / Azure AD B2C の公式サンプル集
github.com