Microsoft Entra IDをWebアプリケーションに統合

.NET
Microsoft Entra ID

By Daniel Laufenberg on 08/05/2024

By Daniel Laufenberg on 08/05/2024

webapp_and_entra_id.png

Microsoft Entra ID(以前の名前はAzure Active Directory)はIT業界で最も人気のあるIDaaS(Identity as a Service)製品の1つです。Entra IDを使ったことがない人でも、以下のページを一度は見たことがあるかもしれません。

Integrating Microsoft Entra ID into a Web App (Razor Pages) image 1

Microsoft Entra IDは、ユーザーのアイデンティティを管理し、企業のリソースを保護するために必要なすべてのツールを提供するクラウドベースのアイデンティティおよびアクセス管理サービスです。社内アプリにアクセスする前に表示されるこのログイン画面は、Entra IDがユーザーにアプリのアクセス権利があるかを確認していることを示しています。詳しい情報はMicrosoftの公式ドキュメントをご覧ください。

Microsoft Entra IDは単にアプリケーションの前に立つ「門番」見たいな物と思う方もいるでしょう。その考えは、一図として間違ってはありませんが、Microsoft Entra IDの機能性はそれにとどまりません。Entra IDは最前線のセキュリティとしてだけでなく、アプリケーションと直接統合し、各機能に対して細かなアクセス制御をする事も可能なんです。 

今回はその作法をお見せしたいと思います。

当デモではRazor Pagesを使用し、各ページにて、ユーザー所有のアクセス権に応じて異なる機能を提供するウェブアプリケーションを作成します。アプリケーションのコードを書く前に、使用するEntra IDテナント内でアプリケーション登録を作成する必要があります。

事前に知っておくべきコンセプト

サービスプリンシパル(Service Principal)

サービスプリンシパルは、アプリケーションのセキュリティポリシーを担う認証エンティティです。Entra IDテナント内のリソースに対して、サービスプリンシパルに特定のアクセス権限を割り当てることができます。サービスプリンシパルはアクセスポリシーを人間のユーザーではなく、アプリケーションに適用させると考えるとわかりやすいでしょう。

アプリケーション登録 (Application Registration)

これは、テナント内でグローバルなアプリケーションインスタンスを作成するプロセスを指しています。新しいアプリケーションインスタンスを作成する際に、そのアプリケーションインスタンスに付属されるサービスプリンシパルが同時に作成されます。

「すでにサービスプリンシパルがあるのに、なぜアプリケーション登録が必要なのか?」と疑問に思う方も多いでしょう。アプリケーション登録は関連するテナント間で共有されますが、サービスプリンシパルは各テナントに個別に作成されます。つまり、マルチテナント環境でアプリケーションが作成された場合、各テナントごとに独自のサービスプリンシパルが必要となるのです。

当デモでは寿司屋のウェブアプリケーションを作成します

  • ホーム (Home):すべてのユーザーが利用可能

  • キッチン (Kitchen):従業員のみ利用可能(Entraテナントのユーザー)

  • 在庫ルーム (StockRoom):ヘッドシェフのみ利用可能。

必要な開発ツール

  • Azure CLI

  • Dotnet CLI

  • テキストエディター(このデモではVisual Studio Codeを使用しましたが、お好きなエディターで大丈夫です)

アプリケーションの登録

1. CLIでAzureにログイン

az login 

2.アプリケーションの作成

#寿司レストランのアプリケーションを作成
az ad app create --display-name "sushi-restaurant"

#作成されたアプリケーションApp Idを取得
az ad app list --display-name "sushi-restaurant" --query "[0].appId"  -o tsv

#アプリケーションの応答 URLの設定とトーケン発行を有効化 
az ad app update --id {先ほどのappId} --web-redirect-uris=index
--enable-id-token-issuance

#設定変更が反映されたかを確認
az ad app list --display-name "sushi-restaurant" --query "[0].appId"  -o tsv

#アプリケーションのパスワードを作成。パスワードは安全な場所に保管してください
az ad app credential reset --id {先ほどのappId}  --append --query password


ウェブアプリケーションの設定

ウェブアプリケーションのコードは下記のリンクからダウンロードしてください。

ほとんどのコードはMicrosoftの公式ドキュメントを参考にしています。 https://learn.microsoft.com/en-us/entra/identity-platform/scenario-web-app-sign-user-app-configuration?tabs=aspnetcore

1. コードをエディターで開き 「appSetting.json」を下記のように設定する

{
  "Logging": {
	"LogLevel": {
  	"Default": "Information",
  	"Microsoft.AspNetCore": "Warning"
	}
  },
  "AzureAd": {
	"Instance": "https://login.microsoftonline.com/",
	"TenantId": "{テナントID}",
	"ClientId": "{アプリケーションのappId}",
	"CallbackPath": "/index",
	"ClientSecret":  "先ほど作成したパスワード"
  },
  "AllowedHosts": "*"
}

2. 「program.cs」に下記のコードを加える。これによりMicrosoft Entra IDが認証に使われます。

builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd");
builder.Services.AddRazorPages()
	.AddMvcOptions(options =>
{
	var policy = new AuthorizationPolicyBuilder()
              	.RequireAuthenticatedUser()
              	.Build();
	options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();

このウェブアプリケーションには3つのページがあります。 

Integrating Microsoft Entra ID into a Web App (Razor Pages) Image 2

アプリケーションをスタート

早速アプリケーションをスタートしましょう。コマンドdotnet runでスタートができます.

ホームページはどのユーザーでもアクセスができます. Index.cshtml.cs をご覧いただくと[AllowAnonymous] (匿名を許可する)のアノテーションが使われております。

[AllowAnonymous]
public class IndexModel : PageModel
{
	private readonly ILogger<IndexModel> _logger;
Integrating Microsoft Entra ID into a Web App (Razor Pages) Image 3

キッチンページはEntra IDで保護されています。このページにアクセスすると、既存の認証セッションを確認され、存在しない場合はユーザーをログイン画面にリダイレクトされます。

Integrating Microsoft Entra ID into a Web App (Razor Pages) 4

テナント既存のアカウントでログインすると、ページが表示されます

Integrating Microsoft Entra ID into a Web App (Razor Pages) 5

次に、ヘッドシェフのみがアクセスできる在庫ルームページにアクセスします

Integrating Microsoft Entra ID into a Web App (Razor Pages) 6

アクセス不可!

在庫ルームのコードを見ると、ヘッドシェフ(head chef) Roleのアクセス権限が設定されています。

[Authorize(Roles ="HeadChef")]
public class StockRoomModel : PageModel
{

ログインしたユーザーにはこのRoleが割り当てられていないため、アプリケーションはページ表示のリクエストを拒否しました。

ではこのヘッドシェフ(head chef) Roleを作成し、ユーザーにアサインしましょう。

#「head chef」app roleを作成
az ad app update --id {先ほどのapp Id} --app-roles '[{ "allowedMemberTypes": [ "User" ], "description": "Only Head Chef has access to the stockroom.", "displayName": "Head Chef", "isEnabled": true, "value": "HeadChef" }]'
#app roleが作成された事を確認
az ad app show --id {先ほどのapp Id} --query "appRoles[?value=='HeadChef'].id" -o tsv
注目点

MicrosoftプラットフォームにはAzureロール, Entra ロール, またはApp ロールと様々なロールが存在します。当記事ではその違いついての説明するとかなり長文になってしまうので、ご興味ある方はこちらの投稿をご覧ください。今作成したロールはアプリケーション登録に関与している、Appロールだという事を知って頂ければ十分です。

次に、このロールをユーザーにアサインする必要があります。このApp ロールはAzure系統の物ではないため、残念ながらAzure CLIではアサインできません。Microsoft Graph APIを使用する必要があります。

このチュートリアルに従うのが最も簡単な方法です。

もっと挑戦したい方

Graph APIエンドポイントで同じことを行うこともできます。

ユーザーに必要なロールが割り当てられたので、ページに移動しましょう(ここでセッションをクリアする必要があるかもしれません)。

Integrating Microsoft Entra ID into a Web App (Razor Pages) 7

在庫ルームにアクセスできました!

まとめ

当記事では、Microsoft Entra IDをRazor Pagesのウェブアプリケーションに統合し、細かなアクセス制御を実装しました。サービスプリンシパルやアプリケーション登録といった主要な概念を説明し、アクセス制御されたページを含む寿司屋アプリを作成しました。最後に、ロールで制限されたページにアクセスするための「Head Chef」Roleの作成とアサインをしました。

関連投稿


clouds-connected-RBAC

Microsoftプラットフォームにおける様々なRBACシステムの違いを解説

Microsoftプラットフォームで使用されるEntra IDロール、Microsoft 365ロール、Azureロール、Appロールの違いについて説明します。