注
これは、この記事の最新バージョンではありません。 現在のリリースについては、 この記事の .NET 9 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポートされなくなりました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、 この記事の .NET 9 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、 この記事の .NET 9 バージョンを参照してください。
この記事では、Blazor アプリのセキュリティの構成と管理に関する ASP.NET Core のサポートについて説明します。
Blazor は、既存の ASP.NET Core 認証メカニズムを使用してユーザーの ID を特定します。 厳密なメカニズムは、Blazor アプリがどのようにホストされているか (サーバー側かクライアント側か) によって異なります。
セキュリティのシナリオは、Blazor アプリで承認コードがサーバー側で実行される場合とクライアント側で実行される場合とで異なります。 承認コードがサーバー上で実行される場合、承認チェックでは、アプリの領域とコンポーネントに対してアクセス規則を適用できます。 クライアント側で実行されるコードには改ざんの可能性があるため、クライアントで実行される承認コードを信頼してアクセス規則を無条件に適用したり、クライアント側のコンテンツの表示を制御したりすることはできません。
承認規則の適用を保証する必要がある場合は、クライアント側のコードで承認チェックを実装しないでください。 承認チェックと規則の適用をサーバー側レンダリング (SSR) のみに依存する Blazor Web App を作成します。
承認規則の適用と、データとコードのセキュリティを保証する必要がある場合は、クライアント側アプリを開発しないでください。 Blazor Server アプリを作成します。
Razor Pages 承認規則 は、ルーティング可能な Razor コンポーネントには適用されません。 ルーティング不可能な
ASP.NET Core Identity は、要求と応答の HTTP 通信のコンテキストで動作するように設計されています。これは一般に、Blazor アプリのクライアント/サーバー通信モデルではありません。 ユーザー管理に ASP.NET Core Identity を使用する ASP.NET Core アプリでは、ユーザー登録、ログイン、ログアウト、その他のユーザー管理タスクなど、Razor 関連の UI 用に、Razor コンポーネントではなく Identity Pages を使用する必要があります。 Razor タスクを直接処理する Identity コンポーネントを構築することは、一部のシナリオでは可能ですが、Microsoft は推奨またはサポートしていません。
SignInManager<TUser>、UserManager<TUser> など、ASP.NET Core 抽象化は、Razor コンポーネントではサポートされていません。 Identityで ASP.NET Core Blazor を使用する方法の詳細については、「ASP.NET Core Identityをサーバー側のBlazor アプリにスキャフォールディングする」を参照してください。
注
この記事のコード例では 、null 許容参照型 (NRT) と .NET コンパイラの null 状態静的分析を採用しています。これは、.NET 6 以降の ASP.NET Core でサポートされています。 .NET 5 以前を対象とする場合は、この記事の例から null 型の指定 (?
) を削除します。
機密データと資格情報を安全に維持する
アプリ シークレット、接続文字列、資格情報、パスワード、個人識別番号 (PIN)、プライベート .NET/C# コード、秘密キー/トークンをクライアント側コードに格納しないでください。これは 常に安全ではありません。 クライアント側の Blazor コードでは、自社が制御する安全な Web API を介して、安全なサービスとデータベースにアクセスする必要があります。
テスト/ステージング環境と運用環境では、サーバー側の Blazor コードと Web API で安全な認証フローを使用して、プロジェクト コードまたは構成ファイル内に資格情報を保持しないようにする必要があります。 ローカルの開発テスト以外では、環境変数は最も安全なアプローチとは言えないため、機密データを格納するのに環境変数を使用しないことをお勧めします。 ローカル開発テストでは、機密データをセキュリティで保護するために Secret Manager ツール を使用することをお勧めします。 詳細については、次のリソースを参照してください。
クライアント側およびサーバー側のローカル開発とテストでは、 シークレット マネージャー ツール を使用して機密性の高い資格情報をセキュリティで保護します。
Microsoft Azure サービスのマネージド ID
Microsoft Azure サービスの場合は、 マネージド ID を使用することをお勧めします。 マネージド ID を使用すると、アプリ コードに資格情報を保存せずに、Azure サービスに対して安全に認証することができます。 詳細については、次のリソースを参照してください。
- Azure リソースのマネージド ID とは (Microsoft Entra のドキュメント)
- Azure サービスのドキュメント
偽造防止のサポート
Blazor テンプレート:
-
AddRazorComponents ファイルで
Program
が呼び出されると、偽造防止サービスが自動的に追加されます。 -
UseAntiforgery ファイル内の要求処理パイプラインで
Program
を呼び出すことによって偽造防止ミドルウェアを追加し、クロスサイト リクエスト フォージェリ (CSRF/XSRF) の脅威を軽減するためにエンドポイントの偽造防止保護を必要とします。 UseAntiforgery は、UseHttpsRedirection の後に呼び出されます。 UseAntiforgery の呼び出しは、UseAuthentication および UseAuthorization の呼び出しがある場合、その後に配置する必要があります。
AntiforgeryToken コンポーネントは、偽造防止トークンを非表示フィールドとしてレンダリングします。このコンポーネントは、フォーム (EditForm) インスタンスに自動的に追加されます。 詳細については、「 ASP.NET Core Blazor フォームの概要」を参照してください。
AntiforgeryStateProvider サービスは、現在のセッションに関連付けられた偽造防止トークンへのアクセスを提供します。 サービスを挿入し、その GetAntiforgeryToken() メソッドを呼び出して、現在の AntiforgeryRequestToken を取得します。 詳細については、「 ASP.NET Core Blazor アプリから Web API を呼び出す」を参照してください。
Blazor は、要求トークンをコンポーネントの状態に保存します。これにより、対話型コンポーネントが要求にアクセスできない場合でも、偽造防止トークンを使用できることが保証されます。
注
偽造防止 は、フォーム データを application/x-www-form-urlencoded
、 multipart/form-data
、または text/plain
としてエンコードされたサーバーに送信する場合にのみ必要です。これは、フォーム の enctype が唯一の有効な形式であるためです。
詳細については、次のリソースを参照してください。
- ASP.NET Core でのクロスサイト リクエスト フォージェリ (XSRF/CSRF) 攻撃の防止: この記事は、サーバー側のBlazor Server、Blazor Web Appのサーバー プロジェクト、MVC/Blazor Pages とのRazor統合に適用される、主題に関する主要な ASP.NET Core 記事です。
- ASP.NET Core Blazor フォームの概要: この記事の 「偽造防止サポート 」セクションは、 Blazor フォームの偽造防止サポートに関連します。
サーバー側の Blazor の認証
サーバー側 Blazor アプリは、ASP.NET Core アプリと同じ方法でセキュリティ用に構成されています。 詳細については、「 ASP.NET Core セキュリティ トピック」の記事を参照してください。
認証コンテキストは、アプリの起動時にのみ確立されます。これは、アプリが最初にクライアントとのSignalR接続経由で WebSocket に接続したときです。 認証は、 cookie またはその他のベアラー トークンに基づいて行うことができますが、認証は SignalR ハブを介して、完全に 回線内で管理されます。 認証コンテキストは、回線の有効期間を通して維持されます。 アプリは、ユーザーの認証状態を 30 分ごとに定期的に再検証します。
アプリでカスタム サービスのユーザーをキャプチャする必要がある場合、またはユーザーの更新に対応する必要がある場合は、ASP.NET Core サーバー側と追加のセキュリティ シナリオBlazor Web App参照してください。
Blazor は、すべてのページ ナビゲーションで Cookie を使用して新しい HTTP 要求を行う従来のサーバーレンダリング Web アプリとは異なります。 ナビゲーション イベントの間に認証がチェックされます。 ただし、Cookie は関係しません。 Cookie は、サーバーに対して HTTP 要求を行うときにだけ送信され、ユーザーが Blazor アプリ内を移動するときには送信されません。 ナビゲーション中に、ユーザーの認証状態が Blazor 回線内でチェックされます。この回線は、 RevalidatingAuthenticationStateProvider
抽象化を使用してサーバー上でいつでも更新できます。
重要
カスタムの NavigationManager
を実装してナビゲーション中に認証を検証することはお勧めしません。 アプリでナビゲーション中にカスタム認証状態ロジックを実行する必要がある場合は、 カスタム AuthenticationStateProvider
を使用します。
注
この記事のコード例では 、null 許容参照型 (NRT) と .NET コンパイラの null 状態静的分析を採用しています。これは、.NET 6 以降の ASP.NET Core でサポートされています。 .NET 5 以前を対象とする場合は、この記事の例から null 型の指定 (?
) を削除します。
組み込みまたはカスタムの AuthenticationStateProvider サービスでは、ASP.NET Core の HttpContext.User から認証状態データが取得されます。 このようにして、認証状態は既存の ASP.NET Core 認証メカニズムと統合されます。
サーバー側認証の詳細については、「 コア Blazor 認証と承認 ASP.NET」を参照してください。
共有状態
サーバー側 Blazor アプリはサーバー メモリ内に存在し、同じプロセス内で複数のアプリ セッションがホストされます。 アプリ セッションごとに、Blazor によってそれ自体の依存関係挿入コンテナー スコープで回線が開始されるため、スコープ サービスは Blazor セッションごとに一意です。
警告
特別な注意を払っていない限り、同じサーバーの共有状態のアプリがシングルトン サービスを使用することはお勧めできません。これにより、回線をまたいだユーザー状態のリークなど、セキュリティ上の脆弱性が生じる可能性があります。
ステートフル シングルトン サービスがそのために特に設計されている場合、Blazor アプリでそれを使用できます。 たとえば、メモリ キャッシュでは特定のエントリにアクセスするためのキーが必要なため、シングルトン メモリ キャッシュの使用が許容されます。 キャッシュで使われるキャッシュ キーをユーザーが制御できないとすると、キャッシュに格納されている状態が回線間でリークすることはありません。
状態管理に関する一般的なガイダンスについては、「 コア Blazor 状態管理 ASP.NET 参照してください。
サーバー側での機密データと資格情報のセキュリティ
テスト/ステージング環境と運用環境では、サーバー側の Blazor コードと Web API で安全な認証フローを使用して、プロジェクト コードまたは構成ファイル内に資格情報を保持しないようにする必要があります。 ローカルの開発テスト以外では、環境変数は最も安全なアプローチとは言えないため、機密データを格納するのに環境変数を使用しないことをお勧めします。 ローカル開発テストでは、機密データをセキュリティで保護するために Secret Manager ツール を使用することをお勧めします。 詳細については、次のリソースを参照してください。
クライアント側およびサーバー側のローカル開発とテストでは、 シークレット マネージャー ツール を使用して機密性の高い資格情報をセキュリティで保護します。
プロジェクト テンプレート
「Blazor」のガイダンスに従って、新しいサーバー側 Blazor アプリを作成します。
サーバー側アプリ テンプレートを選択し、プロジェクトを構成したら、[ 認証の種類] でアプリの認証を選択します。
- なし (既定値): 認証なし。
- 個々のアカウント: ユーザー アカウントは、ASP.NET Core Identityを使用してアプリ内に格納されます。
- なし (既定値): 認証なし。
- 個々のアカウント: ユーザー アカウントは、ASP.NET Core Identityを使用してアプリ内に格納されます。
- Microsoft ID プラットフォーム: 詳細については、「 ASP.NET Core Blazor 認証と承認」を参照してください。
- Windows: Windows 認証を使用します。
Blazor Identity UI (個別のアカウント)
認証オプションに Blazor を選んだ場合、Blazor は、完全な Identity ベースの UI の生成をサポートします。
Blazor Web App テンプレートでは、SQL Server データベース用の Identity コードがスキャフォールディングされます。 コマンド ライン バージョンでは SQLite が使用され、Identity 用の SQLite データベースが含まれます。
このテンプレートの内容は以下のとおりです。
- 認証されたユーザーでの対話型サーバー側レンダリング (対話型 SSR) とクライアント側レンダリング (CSR) のシナリオがサポートされます。
- Identity Razorコンポーネントと、ユーザーのサインインとサインアウトなどの日常的な認証タスクに関連するロジックを追加します。Identity コンポーネントでは、Identity、サード パーティ製アプリを使用した多要素認証など、高度な機能もサポートされています。 Identity コンポーネント自体はインタラクティビティをサポートしていない点に注意してください。
- Identity 関連のパッケージと依存関係を追加します。
-
Identity 内の
_Imports.razor
パッケージを参照します。 - カスタム ユーザー Identity クラス (
ApplicationUser
) を作成します。 -
EF Core データベース コンテキスト (
ApplicationDbContext
) を作成して登録します。 - 組み込みの Identity エンドポイントのルーティングを構成します。
- Identity 検証とビジネス ロジックを含みます。
Blazor フレームワークのIdentity コンポーネントを調べるには、Pages
プロジェクト テンプレート (参照ソース) のShared
フォルダーのAccount
フォルダーとBlazor Web App フォルダーにアクセスします。
対話型 WebAssembly レンダリング モードまたは対話型自動レンダリング モードを選んだ場合、サーバーがすべての認証要求と承認要求を処理し、Identity コンポーネントは、Blazor Web App のメイン プロジェクト内のサーバー上で静的にレンダリングします。
このフレームワークは、ユーザーの認証状態をブラウザーにフローするためのカスタム AuthenticationStateProvider を、サーバーとクライアント (.Client
) の両方のプロジェクトで提供します。 サーバー プロジェクトは AddAuthenticationStateSerialization を呼び出し、クライアント プロジェクトは AddAuthenticationStateDeserialization を呼び出します。 クライアントではなくサーバーで認証を行うと、プリレンダリング中、.NET WebAssembly ランタイムが初期化される前に、アプリが認証状態にアクセスできます。 カスタム AuthenticationStateProvider 実装では 、永続的なコンポーネント状態サービス (PersistentComponentState) を使用して認証状態を HTML コメントにシリアル化し、WebAssembly から読み取って新しい AuthenticationState インスタンスを作成します。 詳細については、「Blazor Web Appでの認証状態の管理」セクションを参照してください。
対話型サーバー ソリューションの場合のみ、 IdentityRevalidatingAuthenticationStateProvider
(参照ソース) は、対話型回線が接続されている 30 分ごとに接続ユーザーのセキュリティ スタンプを再検証するサーバー側の AuthenticationStateProvider です。
対話型 WebAssembly レンダリング モードまたは対話型自動レンダリング モードを選んだ場合、サーバーがすべての認証要求と承認要求を処理し、Identity コンポーネントは、Blazor Web App のメイン プロジェクト内のサーバー上で静的にレンダリングします。 プロジェクト テンプレートには、サーバーとブラウザーの間でユーザーの認証状態を同期するために、PersistentAuthenticationStateProvider
プロジェクト内に が含まれています。 このクラスは、AuthenticationStateProvider のカスタム実装です。 プロバイダーは 、永続的なコンポーネント状態サービス (PersistentComponentState) を使用して認証状態をプリレンダリングし、ページに保持します。
Blazor Web Appのメイン プロジェクトでは、認証状態プロバイダーの名前は IdentityRevalidatingAuthenticationStateProvider
(参照ソース) (サーバーの対話ソリューションのみ) またはPersistingRevalidatingAuthenticationStateProvider
(参照ソース) (WebAssembly または自動対話ソリューション) のいずれかです。
Blazor Identity は、DbContextされたものではない インスタンスに依存します。これは、DbContext では、プロジェクト テンプレートの Identity コンポーネントがインタラクティビティをサポートせずに静的にレンダリングするのには不十分なため、意図的なものです。
グローバル対話型レンダリング モードを非Identity コンポーネントに適用すると同時に、 Identity コンポーネントに静的 SSR を適用する方法については、「 ASP.NET Core Blazor レンダリング モード」を参照してください。
プリレンダリングされた状態の永続化の詳細については、「 Prerender ASP.NET Core Razor コンポーネント」を参照してください。
注
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[ 分岐またはタグの切り替え ] ドロップダウン リストを使用します。 詳細については、「 ASP.NET Core ソース コード (dotnet/AspNetCore.Docs #26205) のバージョン タグを選択する方法」を参照してください。
Blazor Web App で認証状態を管理する
このセクションは、次を採用する Blazor Web Appに適用されます。
- 個別のアカウント
- クライアント側レンダリング (CSR、WebAssembly ベースの対話)。
クライアント側の認証状態プロバイダーは、Blazor 内でのみ使用され、ASP.NET Core 認証システムとは統合されません。 プリレンダリング中、Blazor は、ページで定義されたメタデータを考慮し、ASP.NET Core 認証システムを使用して、ユーザーが認証済みかどうかを判断します。 ユーザーが別のページに移動するときは、クライアント側の認証プロバイダーが使用されます。 ユーザーがページを更新 (ページ全体の再読み込み) するときは、クライアント側の認証状態プロバイダーは、サーバーでの認証の判断に関与しません。 ユーザーの状態はサーバーで保持されないため、クライアント側で保持されていた認証状態は失われます。
これに対処するには、ASP.NET Core 認証システム内で認証を実行するのが最適な方法です。 クライアント側の認証状態プロバイダーは、ユーザーの認証状態の反映のみを処理します。 認証状態プロバイダーでこれを実現する方法の例は Blazor Web App プロジェクト テンプレートで実証されており、以下で説明します。
サーバー プロジェクトのProgram
ファイルで、AddAuthenticationStateSerializationを呼び出します。これは、AuthenticationState (AuthenticationStateProvider) を使用して、サーバー側のによって返されるPersistentComponentStateをシリアル化します。
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization();
この API はがシリアル化するのは、ブラウザーでのアクセス用のサーバー側の名前とロール要求だけです。 すべての要求を含めるには、サーバー側での SerializeAllClaims の呼び出しで true
を AddAuthenticationStateSerialization に設定します。
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization(
options => options.SerializeAllClaims = true);
クライアント (.Client
) プロジェクトの Program
ファイルで、AddAuthenticationStateDeserialization を呼び出します。これにより、AuthenticationStateProvider が追加されます。このとき、AuthenticationState と AuthenticationStateData
() を使用して、PersistentComponentState がサーバーから逆シリアル化されます。 サーバー プロジェクトに、対応する AddAuthenticationStateSerialization の呼び出しが必要です。
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();
PersistingRevalidatingAuthenticationStateProvider
(参照ソース): 対話型のサーバー側レンダリング (対話型 SSR) とクライアント側レンダリング (CSR) を採用する Blazor Web Appの場合。 これはサーバー側 AuthenticationStateProvider であり、対話型回線が接続されているときに、接続済みのユーザーのセキュリティ スタンプを 30 分ごとに再検証します。 また、 永続的なコンポーネント状態サービス を使用して認証状態をクライアントにフローし、CSR の有効期間中は固定されます。PersistingServerAuthenticationStateProvider
(リファレンス ソース):CSR のみを採用する Blazor Web Appの場合。 これは、AuthenticationStateProviderを使用して認証状態をクライアントにフローするサーバー側のであり、CSR の有効期間中は固定されます。PersistentAuthenticationStateProvider
(リファレンス ソース):CSR を採用する Blazor Web Appの場合。 これはクライアント側 AuthenticationStateProvider であり、ページがサーバー上でレンダリングされたときに、ページに保持されているデータを参照してユーザーの認証状態を判断します。 この認証状態は、CSR の有効期間中、固定されます。 ユーザーがログインまたはログアウトする必要がある場合は、ページ全体の再読み込みが必要です。 これにより提供されるのは、表示用のユーザー名とメールのみです。 それ以降の要求を行うときにサーバーに対して認証するトークンは含まれません。これは、サーバーに対する cookie 要求に含まれるHttpClient
を使用して個別に処理されます。
注
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[ 分岐またはタグの切り替え ] ドロップダウン リストを使用します。 詳細については、「 ASP.NET Core ソース コード (dotnet/AspNetCore.Docs #26205) のバージョン タグを選択する方法」を参照してください。
スキャフォールディング Identity
サーバー側のIdentity アプリへのBlazorのスキャフォールディングの詳細については、「ASP.NET Core プロジェクトでのIdentityのスキャフォールディング」を参照してください。
外部プロバイダーからの追加のクレームとトークン
外部プロバイダーからの追加の要求を格納するには、「ASP.NET Core で外部プロバイダーからの追加の要求とトークンを保持する」を参照してください。
Linux 上の Azure App Service で Identity Server を使用
Identity Server を使用して Azure App Service on Linux にデプロイするときに、発行者を明示的に指定します。 詳細については、「Identityを使用して SPA の Web API バックエンドをセキュリティで保護する」を参照してください。
特定のコンポーネントに限定されたサービス用のAuthenticationStateProvider
を挿入する
正しく初期化されていない AuthenticationStateProvider の新しいインスタンスが作成されるため、カスタム スコープ内で AuthenticationStateProvider の解決を試みないでください。
コンポーネントをスコープにしたサービス内の AuthenticationStateProvider にアクセスするには、コンポーネントに AuthenticationStateProvider を挿入し、パラメーターとしてサービスに渡します。 この方法により、AuthenticationStateProvider の正しい初期化されたインスタンスが各ユーザー アプリ インスタンスに確実に使われます。
ExampleService.cs
:
public class ExampleService
{
public async Task<string> ExampleMethod(AuthenticationStateProvider authStateProvider)
{
var authState = await authStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
return $"{user.Identity.Name} is authenticated.";
}
else
{
return "The user is NOT authenticated.";
}
}
}
サービスをスコープとして登録します。 サーバー側の Blazor アプリでは、スコープ指定されたサービスの有効期間はクライアント接続 回線の期間と同じです。
Program
ファイルで次の操作を行います。
builder.Services.AddScoped<ExampleService>();
Startup.ConfigureServices
の Startup.cs
で:
services.AddScoped<ExampleService>();
次の InjectAuthStateProvider
コンポーネントでは、以下のことを行います。
- コンポーネントは OwningComponentBase を継承します。
-
AuthenticationStateProvider が挿入されて、
ExampleService.ExampleMethod
に渡されます。 -
ExampleService
は、OwningComponentBase.ScopedServices と GetRequiredService を使用して解決されます。これにより、ExampleService
の正しい初期化済みインスタンスが返され、ユーザーの回線の有効期間を通して維持されます。
InjectAuthStateProvider.razor
:
@page "/inject-auth-state-provider"
@inherits OwningComponentBase
@inject AuthenticationStateProvider AuthenticationStateProvider
<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>
<p>@message</p>
@code {
private string? message;
private ExampleService? ExampleService { get; set; }
protected override async Task OnInitializedAsync()
{
ExampleService = ScopedServices.GetRequiredService<ExampleService>();
message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
}
}
@page "/inject-auth-state-provider"
@inject AuthenticationStateProvider AuthenticationStateProvider
@inherits OwningComponentBase
<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>
<p>@message</p>
@code {
private string? message;
private ExampleService? ExampleService { get; set; }
protected override async Task OnInitializedAsync()
{
ExampleService = ScopedServices.GetRequiredService<ExampleService>();
message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
}
}
詳しくは、「OwningComponentBase」で Blazor についてのガイダンスをご覧ください。
カスタムの AuthenticationStateProvider
によるプリレンダリング中に未承認のコンテンツが表示される
承認されていないコンテンツ (たとえば、AuthorizeView
コンポーネント内のコンテンツ) を表示しないようにするために、カスタム AuthenticationStateProvider
を使用してプリレンダリングを行う場合は、次のいずれかの方法を採用します。
プリレンダリングをサポートするためにカスタムの IHostEnvironmentAuthenticationStateProvider 用に AuthenticationStateProvider を実装する: たとえば、IHostEnvironmentAuthenticationStateProvider の実装については、Blazor で、ServerAuthenticationStateProvider フレームワークの
ServerAuthenticationStateProvider.cs
の実装を参照してください。注
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[ 分岐またはタグの切り替え ] ドロップダウン リストを使用します。 詳細については、「 ASP.NET Core ソース コード (dotnet/AspNetCore.Docs #26205) のバージョン タグを選択する方法」を参照してください。
プリレンダリングを無効にする: アプリのコンポーネント階層の最上位にある、ルート コンポーネントではないコンポーネントで、
prerender
パラメーターをfalse
に設定して、レンダリング モードを指定します。注
App
コンポーネントなどのルート コンポーネントを対話型にすることはサポートされていません。 そのため、App
コンポーネントでプリレンダリングを直接無効にすることはできません。Blazor Web App プロジェクト テンプレートを基にしたアプリの場合、通常は、
Routes
コンポーネント内でApp
コンポーネントが使用されている場所 (Components/App.razor
) でプリレンダリングを無効にします。<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
また、
HeadOutlet
コンポーネントのプリレンダリングを無効にします。<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
Routes
コンポーネント インスタンスに適用されるレンダリング モードを選択的に制御することもできます。 たとえば、ASP.NET Core Blazor のレンダーモード を参照してください。
プリレンダリングを無効にする:
_Host.cshtml
ファイルを開き、render-mode
の 属性を Server に変更します。<component type="typeof(App)" render-mode="Server" />
- アプリが起動する前にサーバーでユーザーを認証する: このアプローチを採用するためには、Identity ベースのサインイン ページまたはビューを使用してアプリでユーザーの初期要求に応答し、ユーザーが認証されるまで Blazor エンドポイントへの要求を防ぐ必要があります。 詳細については、「 承認によって保護されたユーザー データを使用して ASP.NET Core アプリを作成する」を参照してください。 認証後は、プリレンダリングされた Razor コンポーネント内の未承認のコンテンツは、ユーザーのよるそのコンテンツの表示が真に未承認である場合にのみ表示されます。
ユーザー状態の管理
名前には "state" という単語が含まれますが、AuthenticationStateProvider は "一般的なユーザーの状態" を格納するためのものではありません。 AuthenticationStateProvider は、ユーザーの認証状態 (アプリにサインイン済みであるかどうかと、サインインに使用したユーザー) をアプリに示すだけです。
認証には、Identity Pages や MVC アプリと同じ ASP.NET Core Razor 認証が使用されます。 ASP.NET Core Identity に格納されたユーザー状態は、アプリにコードを追加しなくても Blazor に流れます。 アプリの Identity 部分で Identity の機能を有効にするには、ASP.NET Core Blazor の記事とチュートリアルのガイダンスに従ってください。
ASP.NET Core Identityの外部での一般的な状態管理のガイダンスについては、「 ASP.NET Core Blazor 状態管理」を参照してください。
追加のセキュリティ抽象化
認証状態の管理には、さらに 2 つの抽象化が関与します。
ServerAuthenticationStateProvider(参照ソース): AuthenticationStateProvider フレームワークがサーバーから認証状態を取得するために使用するBlazor。
RevalidatingServerAuthenticationStateProvider(参照ソース): ホスト環境から認証状態を受信し、定期的に再検証するために、AuthenticationStateProvider フレームワークによって使用されるBlazor サービスの基本クラス。
既定の 30 分間の再検証間隔は、
RevalidatingIdentityAuthenticationStateProvider
(参照ソース) で調整できます。 次の例では、間隔を 20 分に短縮しています。protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(20);
注
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[ 分岐またはタグの切り替え ] ドロップダウン リストを使用します。 詳細については、「 ASP.NET Core ソース コード (dotnet/AspNetCore.Docs #26205) のバージョン タグを選択する方法」を参照してください。
サインアウト時の認証状態の管理
サーバー側の Blazor は、回線の有効期間中、すべてのブラウザー タブを含め、ユーザーの認証状態を保持します。 いずれかのタブでユーザーがサインアウトしたときに、すべてのブラウザー タブでユーザーをプロアクティブにサインオフするには、短い RevalidatingServerAuthenticationStateProvider を指定して (RevalidationInterval) を実装する必要があります。
注
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[ 分岐またはタグの切り替え ] ドロップダウン リストを使用します。 詳細については、「 ASP.NET Core ソース コード (dotnet/AspNetCore.Docs #26205) のバージョン タグを選択する方法」を参照してください。
一時的なリダイレクト URL の有効期間
このセクションは、 Blazor Web Appに適用されます。
RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration オプションを使用して、Blazor サーバー側レンダリングによって生成された一時的なリダイレクト URL の ASP.NET Core データ保護の有効期間を取得または設定します。 これらは一時的にしか使用されないため、有効期間は、クライアントで URL を受信してナビゲーションを開始するのに必要な長さであれば十分です。 ただし、サーバー間のクロック スキューを許容するのに十分な長さも必要です。 既定値は 5 分です。
次の例では、値は 7 分に延長されています。
builder.Services.AddRazorComponents(options =>
options.TemporaryRedirectionUrlValidityDuration =
TimeSpan.FromMinutes(7));
クライアント側の Blazor 認証
クライアント側のすべてのコードはユーザーによって変更される可能性があるため、クライアント側 Blazor アプリでは、クライアント側の認証チェックがバイパスされる可能性があります。 JavaScript SPA フレームワークや任意のオペレーティング システム用のネイティブ アプリを含め、すべてのクライアント側アプリのテクノロジにも同じことが当てはまります。
以下を追加します。
Microsoft.AspNetCore.Components.Authorization
NuGet パッケージのパッケージ リファレンス。注
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ消費ワークフローでの パッケージのインストールと管理(NuGet ドキュメント)」の記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
アプリのMicrosoft.AspNetCore.Components.Authorizationファイルに
_Imports.razor
名前空間を追加します。
認証を処理するには、組み込みまたはカスタムの AuthenticationStateProvider サービスを使用します。
クライアント側認証の詳細については、「 Secure ASP.NET Core Blazor WebAssembly」を参照してください。
対話型自動レンダリングを使用して Blazor Web Appのデータをセキュリティで保護する
Blazor Web Appがコンポーネントまたは対話型自動レンダリング モードを指定するアプリ全体にサーバー側レンダリング (SSR) とクライアント側レンダリング (CSR) を採用する場合、コンポーネントとデータへのアクセスの承認は 2 か所で適用されます。 コンポーネントは、コンポーネントの定義ファイル (@attribute [Authorize]
) 内の承認属性により、サーバー上にレンダリングされるときに自身 (および取得したデータ) へのアクセスを制限します。 コンポーネントがクライアントにレンダリングされると、クライアントから呼び出されるサーバー Web API エンドポイント経由でデータへのアクセスが制限されます。 不適切なデータ アクセスを防ぐために、両方の場所でデータ アクセスをセキュリティで保護する場合は注意が必要です。
コンポーネントによってセキュリティで保護された気象データが表示される次のシナリオを考えてみましょう。 次のいくつかの方法のデモは、BlazorWebAppEntra
/BlazorWebAppEntraBff
サンプル (.NET 9 以降) または BlazorWebAppOidc
サンプル / (BlazorWebAppOidcBff
) のBlazordotnet/blazor-samples
サンプル (.NET 8 以降) (ダウンロード方法) を使用して評価およびテストできます。
クライアント プロジェクトは、気象データを保持する WeatherForecast
クラスを保持します。
public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary)
{
public DateOnly Date { get; set; } = date;
public int TemperatureC { get; set; } = temperatureC;
public string? Summary { get; set; } = summary;
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
クライアント プロジェクトの IWeatherForecaster
インターフェイスは、気象データを取得するための GetWeatherForecastAsync
メソッドを定義します。
public interface IWeatherForecaster
{
Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync();
}
クライアント プロジェクトの ClientWeatherForecaster
サービスは、 IWeatherForecaster
を実装します。
GetWeatherForecastAsync
メソッドは、気象データの/weather-forecast
エンドポイントにあるサーバー プロジェクトの Web API を呼び出します。
internal sealed class ClientWeatherForecaster(HttpClient httpClient)
: IWeatherForecaster
{
public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync() =>
await httpClient.GetFromJsonAsync<WeatherForecast[]>("/weather-forecast") ??
throw new IOException("No weather forecast!");
}
クライアント プロジェクトは、次の Weather
コンポーネントを保持します。
-
[Authorize]
属性を使用して承認を強制します。 - 永続的なコンポーネント状態サービス (PersistentComponentState) を使用して、サーバー上でコンポーネントが静的から対話型 SSR に移行したときに天気予報データを保持します。 詳細については、「 Prerender ASP.NET Core Razor コンポーネント」を参照してください。
@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@inject IWeatherForecaster WeatherForecaster
<PageTitle>Weather</PageTitle>
<h1>Weather</h1>
<p>This component demonstrates showing data.</p>
@if (Forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th aria-label="Temperature in Celsius">Temp. (C)</th>
<th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in Forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
[SupplyParameterFromPersistentComponentState]
public IEnumerable<WeatherForecast>? Forecasts { get; set; }
protected override async Task OnInitializedAsync()
{
Forecasts ??= await WeatherForecaster.GetWeatherForecastAsync();
}
}
@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@implements IDisposable
@inject PersistentComponentState ApplicationState
@inject IWeatherForecaster WeatherForecaster
<PageTitle>Weather</PageTitle>
<h1>Weather</h1>
<p>This component demonstrates showing data.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th aria-label="Temperature in Celsius">Temp. (C)</th>
<th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private IEnumerable<WeatherForecast>? forecasts;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<IEnumerable<WeatherForecast>>(
nameof(forecasts), out var restoredData))
{
forecasts = await WeatherForecaster.GetWeatherForecastAsync();
}
else
{
forecasts = restoredData!;
}
// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
}
private Task PersistData()
{
ApplicationState.PersistAsJson(nameof(forecasts), forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose() => persistingSubscription.Dispose();
}
サーバー プロジェクトは、IWeatherForecaster
としてServerWeatherForecaster
を実装します。GetWeatherForecastAsync
メソッドを使用して気象データを生成して返します。
internal sealed class ServerWeatherForecaster() : IWeatherForecaster
{
public readonly string[] summaries =
[
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot",
"Sweltering", "Scorching"
];
public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
{
// Simulate asynchronous loading to demonstrate streaming rendering
await Task.Delay(500);
return Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
}
}
アプリで気象データを取得するために外部 Web API を呼び出す必要がある場合は、HTTP クライアント (HttpClient
) を挿入してデータを要求できます。
internal sealed class ServerWeatherForecaster(HttpClient httpClient,
IHttpContextAccessor httpContextAccessor) : IWeatherForecaster
{
public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
{
var httpContext = httpContextAccessor.HttpContext ??
throw new InvalidOperationException("No HttpContext!");
var accessToken = await httpContext.GetTokenAsync("access_token") ??
throw new InvalidOperationException("No access_token was saved");
using var request =
new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
request.Headers.Authorization = new("Bearer", accessToken);
using var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
throw new IOException("No weather forecast!");
}
}
さらに別の方法では、HTTP クライアント ファクトリ (IHttpClientFactory
) を ServerWeatherForecaster
に挿入し、トークン ハンドラーで名前付き HTTP クライアントを使用して外部 Web API を呼び出すことができます。 詳細については、「 ASP.NET Core Blazor アプリから Web API を呼び出す」を参照してください。
アプリで Microsoft Entra ID 用の Microsoft Identity Web パッケージで MicrosoftID プラットフォームを使用する場合 (ASP.NET Core Blazor アプリからの Web API の呼び出しを参照)、次のServerWeatherForecaster
は外部 Web API 呼び出しを行う方法を示しています。 アクセス トークンは、要求に自動的にアタッチされます。
internal sealed class ServerWeatherForecaster(IDownstreamApi downstreamApi) : IWeatherForecaster
{
public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
{
using var response = await downstreamApi.CallApiForUserAsync("DownstreamApi",
options =>
{
options.RelativePath = "/weather-forecast";
});
return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
throw new IOException("No weather forecast!");
}
}
ServerWeatherForecaster
がデータを取得する方法に関係なく、サーバー プロジェクトは、クライアント気象データ呼び出し用のセキュリティで保護された Web API エンドポイントを維持します。 このエンドポイントにより、サーバーで ServerWeatherForecaster.GetWeatherForecastAsync
呼び出しが行われます。
app.MapGet("/weather-forecast", (
[FromServices] IWeatherForecaster WeatherForecaster) =>
{
return WeatherForecaster.GetWeatherForecastAsync();
}).RequireAuthorization();
上記のアプローチを使用して、セキュリティで保護された気象データをユーザーに提供する 2 つのシステムが用意されています。
-
Weather
コンポーネントがサーバーにレンダリングされると、気象データを取得するために、ServerWeatherForecaster
サービスのGetWeatherForecastAsync
メソッドが直接使用されます。 データのセキュリティは、コンポーネントの[Authorize]
属性によって適用されます。 要約すると、気象データのセキュリティはコンポーネントによって適用されます。 -
Weather
コンポーネントがクライアントにレンダリングされると、ClientWeatherForecaster
サービスを使用して、/weather-forecast
拡張メソッドを適用するセキュリティで保護されたRequireAuthorization エンドポイントへの Web API 呼び出しが行われます。 ユーザーが気象データにアクセスする権限を持っている場合、エンドポイントはServerWeatherForecaster
サービスを使用してGetWeatherForecastAsync
を呼び出します。 データがクライアントに返されます。 要約すると、気象データのセキュリティは、サーバー アプリの Web API エンドポイントによって適用されます。
上記の方法は、Web API のセキュリティ要件がコンポーネントのセキュリティ要件と一致する場合に適しています。 たとえば、同じ承認ポリシーを Web API エンドポイントとコンポーネントの両方に適用できます。
複雑なシナリオでは、追加の計画と実装が必要です。 たとえば、異なるアクセス許可を持つ複数の呼び出し元を持つサーバー Web API には、より高度な承認ポリシー、1 つ以上の追加ポリシー、または異なるアクセス要件を持つ追加のエンドポイントが必要です。
対話型自動レンダリングを採用するアプリにセキュリティを組み込む際は、サーバーの Web API エンドポイントに実装されたセキュリティによって、コンポーネントがサーバーにレンダリングされ、サービスを介してデータにアクセスするときに使用されるサーバーのサービス実装がセキュリティで保護されていないことに注意してください。 SSR 中にサーバー上のデータにアクセスすることと、CSR 中にクライアント Web API 要求上のデータにアクセスする場合の違いを慎重に検討してください。 データへの不適切なアクセスを回避するために、戦略的にセキュリティを適用します。
Blazorサンプル GitHub リポジトリ (dotnet/blazor-samples
) の例 (ダウンロード方法) で、このセクションで説明する方法を示します。
BlazorWebAppOidc
BlazorWebAppOidcBff
BlazorWebAppEntra
BlazorWebAppEntraBff
AuthenticationStateProvider
サービス
AuthenticationStateProvider は、ユーザーの認証状態を取得するために AuthorizeView コンポーネントおよびカスケード型の認証サービスで使用される、基盤となるサービスです。
AuthenticationStateProvider は、ユーザーの認証状態を取得するために AuthorizeView コンポーネントおよび CascadingAuthenticationState コンポーネントで使用される、基盤となるサービスです。
通常、AuthenticationStateProvider は直接使用しません。 この記事で後述する AuthorizeView
コンポーネント または Task<AuthenticationState>
アプローチを使用します。
AuthenticationStateProvider を直接使用することの主な欠点は、基となる認証状態データが変更されてもコンポーネントに自動的に通知されないことです。
カスタム AuthenticationStateProviderを実装するには、 ASP.NET Core Blazor 認証状態に関するページを参照してください。これには、ユーザー認証状態変更通知の実装に関するガイダンスが含まれています。
ユーザーのクレームプリンシパル データを取得する
次の例に示すように、AuthenticationStateProvider サービスから現在のユーザーの ClaimsPrincipal データを提供できます。
ClaimsPrincipalData.razor
:
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider
<h1>ClaimsPrincipal Data</h1>
<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
<p>@authMessage</p>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li>@claim.Type: @claim.Value</li>
}
</ul>
}
<p>@surname</p>
@code {
private string? authMessage;
private string? surname;
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider
.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
claims = user.Claims;
surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
}
else
{
authMessage = "The user is NOT authenticated.";
}
}
}
前の例の場合:
-
ClaimsPrincipal.Claims は、UI での表示用にユーザーの要求 (
claims
) を返します。 - ユーザーの姓 (
surname
) を取得する行では、ユーザーの要求をフィルター処理する述語を指定して ClaimsPrincipal.FindAll を呼び出しています。
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider
<h1>ClaimsPrincipal Data</h1>
<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
<p>@authMessage</p>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li>@claim.Type: @claim.Value</li>
}
</ul>
}
<p>@surname</p>
@code {
private string? authMessage;
private string? surname;
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider
.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
claims = user.Claims;
surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
}
else
{
authMessage = "The user is NOT authenticated.";
}
}
}
user.Identity.IsAuthenticated
が true
である場合、ユーザーが ClaimsPrincipal であるため、要求を列挙し、役割のメンバーシップを評価できます。
依存性注入 (DI) とサービスの詳細については、「ASP.NET Core Blazor 依存性注入」および「ASP.NET Core での依存性注入」を参照してください。 カスタム AuthenticationStateProviderを実装する方法については、「 ASP.NET Core Blazor 認証状態」を参照してください。
認証状態をカスケード パラメーターとして公開する
ユーザーによってトリガーされたアクションを実行する場合など、認証状態データが手続き型ロジックに必要な場合は、型 Task<
AuthenticationState の>
を定義して認証状態データを取得します。
CascadeAuthState.razor
:
@page "/cascade-auth-state"
<h1>Cascade Auth State</h1>
<p>@authMessage</p>
@code {
private string authMessage = "The user is NOT authenticated.";
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
protected override async Task OnInitializedAsync()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user?.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
}
}
}
}
@page "/cascade-auth-state"
<h1>Cascade Auth State</h1>
<p>@authMessage</p>
@code {
private string authMessage = "The user is NOT authenticated.";
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
protected override async Task OnInitializedAsync()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user?.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
}
}
}
}
user.Identity.IsAuthenticated
が true
である場合、要求を列挙し、役割のメンバーシップを評価できます。
Task<
およびカスケード認証状態サービスを使用して、AuthenticationState>
AuthorizeRouteViewを設定します。
次の例に示すように、いずれかの Blazor プロジェクト テンプレートを基にして、認証を有効にして Blazor アプリを作成する場合、アプリに AuthorizeRouteView および AddCascadingAuthenticationState の呼び出しが含まれます。 クライアント側 Blazor アプリには、必要なサービス登録も含まれています。 追加情報については、「Router
コンポーネントを使用して承認されていないコンテンツをカスタマイズする」セクションを参照してください。
<Router ...>
<Found ...>
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)" />
...
</Found>
</Router>
Program
ファイルで、カスケード型の認証状態サービスを登録します。
builder.Services.AddCascadingAuthenticationState();
Task<
および AuthenticationState のコンポーネントを使用して、>
AuthorizeRouteViewCascadingAuthenticationStateを設定します。
次の例に示すように、いずれかの Blazor プロジェクト テンプレートを基にして、認証を有効にして Blazor アプリを作成する場合、アプリに AuthorizeRouteView と CascadingAuthenticationState のコンポーネントが含まれます。 クライアント側 Blazor アプリには、必要なサービス登録も含まれています。 追加情報については、「Router
コンポーネントを使用して承認されていないコンテンツをカスタマイズする」セクションを参照してください。
<CascadingAuthenticationState>
<Router ...>
<Found ...>
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(MainLayout)" />
...
</Found>
</Router>
</CascadingAuthenticationState>
注
.NET 5.0.1 のリリースおよび追加の 5.x リリースでは、Router
コンポーネントには、PreferExactMatches
に設定された @true
パラメーターが含まれます。 詳細については、「 ASP.NET Core 3.1 から .NET 5 への移行」を参照してください。
クライアント側 Blazor アプリで、承認サービスを Program
ファイルに追加します。
builder.Services.AddAuthorizationCore();
クライアント側 Blazor アプリで、Program
ファイルにオプションと承認サービスを追加します。
builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();
サーバー側 Blazor アプリでは、オプションと承認のためのサービスが既に存在するため、これ以上の手順は必要ありません。
権限
ユーザーが認証されると、ユーザーが実行できる操作を制御するための 承認 規則が適用されます。
通常、アクセスは以下の条件に基づいて許可または拒否されます。
- ユーザーが認証されている (サインインしている)。
- ユーザーが ロールにいます。
- ユーザーが 要求を持っている。
- ポリシーが満たされています。
これらの各概念は、ASP.NET Core MVC または Razor Pages アプリと同じです。 ASP.NET Core セキュリティの詳細については、「 ASP.NET Core のセキュリティと Identity」の記事を参照してください。
AuthorizeView
コンポーネント
AuthorizeView コンポーネントでは、ユーザーを承認するかどうかに応じて UI コンテンツが選択的に表示されます。 この方法は、ユーザーのデータのみを 表示 する必要があり、手続き型ロジックでユーザーの ID を使用する必要がない場合に便利です。
このコンポーネントでは、型 context
(AuthenticationState 構文の @context
) の Razor 変数が公開されており、これを使って、サインインしたユーザーに関する情報にアクセスできます。
<AuthorizeView>
<p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>
Authorized パラメーターと NotAuthorized パラメーターの組み合わせでユーザーが承認されない場合に、表示用に別のコンテンツを提供することもできます。
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
<p><button @onclick="HandleClick">Authorized Only Button</button></p>
</Authorized>
<NotAuthorized>
<p>You're not authorized.</p>
</NotAuthorized>
</AuthorizeView>
@code {
private void HandleClick() { ... }
}
AuthorizeView コンポーネントは、ユーザーの承認状態に基づいて要素の可視性を制御しますが、イベント ハンドラー自体にはセキュリティを適用しません。 前の例では、HandleClick
メソッドは、承認済みのユーザーに表示されるボタンにのみ関連付けられていますが、他の場所からこのメソッドが呼び出されるのを妨ぐ手立てはありません。 メソッド レベルのセキュリティを確保するには、ハンドラー自体または関連する API に追加の承認ロジックを実装します。
Razor の Blazor Web App コンポーネントは、静的なサーバー側レンダリング (静的 SSR) 中にサーバー側で承認が失敗した場合に、<NotAuthorized>
コンテンツを表示しません。 サーバー側 ASP.NET Core パイプラインは、サーバー上で承認を処理します。 未承認の要求については、サーバー側の手法を使用して処理します。 詳細については、「 コア Blazor レンダリング モード ASP.NET」を参照してください。
警告
AuthorizeView に関連付けられたクライアント側のマークアップとメソッドは、クライアント側 アプリに での表示と実行についてのみ保護されています。 クライアント側 Blazor アプリで承認済みのコンテンツと安全なメソッドを保護するために、コンテンツは通常、サーバー API に対する安全な承認済み Web API 呼び出しによって提供され、アプリに保存されることはありません。 詳細については、「 ASP.NET Core Blazor アプリから Web API を呼び出す 」および「 ASP.NET Core Blazor WebAssembly 追加のセキュリティ シナリオ」を参照してください。
Authorized と NotAuthorized のコンテンツには、他の対話型コンポーネントなど、任意の項目を含めることができます。
UI オプションやアクセスを制御するロールやポリシーなどの承認条件については、「 承認 」セクションで説明します。
認可条件が指定されていない場合、AuthorizeView では既定のポリシーが使われます。
- 認証された (サインインした) ユーザーが認可されます。
- 認証されていない (サインアウトした) ユーザーは認可されません。
AuthorizeView コンポーネントは、NavMenu
コンポーネント (Shared/NavMenu.razor
) で使用してNavLink
コンポーネント (NavLink) を表示できますが、この方法では、レンダリングされた出力からリスト アイテムのみが削除されることに注意してください。 ユーザーがコンポーネントに移動するのを防ぐことはできません。 宛先コンポーネントで認可を個別に実装します。
ロールベースとリソースベースの承認
AuthorizeView コンポーネントは、ロールベースまたはポリシーベースの承認をサポートします。
ロールベースの承認の場合は、Roles パラメーターを使用します。 次の例では、ユーザーには Admin
または Superuser
ロールのいずれかのロール要求が必要です。
<AuthorizeView Roles="Admin, Superuser">
<p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>
ユーザーが Admin
と Superuser
の両方のロールクレームを必須とするには、AuthorizeView コンポーネントをネストします。
<AuthorizeView Roles="Admin">
<p>User: @context.User</p>
<p>You have the 'Admin' role claim.</p>
<AuthorizeView Roles="Superuser" Context="innerContext">
<p>User: @innerContext.User</p>
<p>You have both 'Admin' and 'Superuser' role claims.</p>
</AuthorizeView>
</AuthorizeView>
上記のコードは、Context
を確立して、AuthorizeView コンテキストの競合を防ぐための内部 AuthenticationState コンポーネントを作成します。
AuthenticationState コンテキストは、コンテキストにアクセスするための標準的なアプローチ (AuthorizeView) を使用して、外部 @context.User
でアクセスされます。 内部 AuthorizeView で、名前付き innerContext
コンテキスト (@innerContext.User
) を使用してコンテキストにアクセスします。
構成ガイダンスを含む詳細については、「 ASP.NET Core でのロールベースの承認」を参照してください。
ポリシーベースの承認の場合、単一のポリシー名で Policy パラメーターを使用します。
<AuthorizeView Policy="Over21">
<p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>
ユーザーが複数のポリシーのいずれかを満たす必要がある場合に対応するには、ユーザーが他のポリシーを満たしていることを確認するポリシーを作成します。
ユーザーが複数のポリシーを同時に満たす必要がある場合に対応するには、次の方法の "いずれか" を採用します。
AuthorizeView に対して、ユーザーが他の複数のポリシーを満たしていることを確認するポリシーを作成します。
複数の AuthorizeView コンポーネントでポリシーを入れ子にします。
<AuthorizeView Policy="Over21"> <AuthorizeView Policy="LivesInCalifornia"> <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p> </AuthorizeView> </AuthorizeView>
要求ベースの承認は、ポリシーベースの承認の特殊なケースです。 たとえば、ユーザーが特定の要求持つことを必須にするポリシーを定義できます。 詳細については、「 ASP.NET Core でのポリシーベースの承認」を参照してください。
RolesとPolicyの両方が設定されている場合、両方の条件が満たされている場合にのみ承認が成功します。 つまり、ユーザーは、指定されたロールの少なくとも 1 つに属 し、 ポリシーで定義されている要件を満たしている必要があります。
Roles も Policy も指定されていない場合、AuthorizeView には既定のポリシーが使われます。
- 認証された (サインインした) ユーザーが認可されます。
- 認証されていない (サインアウトした) ユーザーは認可されません。
.NET 文字列の比較では大文字と小文字が区別されるため、ロール名とポリシー名の照合でも大文字と小文字が区別されます。 たとえば、Admin
(大文字 A
) は、admin
(小文字 a
) と同じロールとして扱われません。
通常、パスカル ケースはロール名とポリシー名に使用されますが (例: BillingAdministrator
)、パスカル ケースの使用は厳密な要件ではありません。 キャメル ケース、ケバブ ケース、スネーク ケースなど、さまざまなケース スキームが許可されています。 ロールとポリシーの名前にスペースを使うことは一般的ではありませんが、フレームワークでは許可されています。 たとえば、billing administrator
は .NET アプリでは一般的ではないロールまたはポリシーの名前の形式ですが、有効なロールまたはポリシーの名前です。
非同期認証中に表示されるコンテンツ
Blazor では、認証状態を 非同期的に決定できます。 このアプローチの主なシナリオは、認証のために外部エンドポイントに要求を送信するクライアント側 Blazor アプリです。
認証の処理中は、AuthorizeView にはコンテンツが表示されません。 認証の処理中にコンテンツを表示するには、Authorizing パラメーターにコンテンツを割り当てます。
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
</Authorized>
<Authorizing>
<p>You can only see this content while authentication is in progress.</p>
</Authorizing>
</AuthorizeView>
このアプローチは通常、サーバー側 Blazor アプリには適用されません。 サーバー側 Blazor アプリでは、状態が確立されるとすぐに認証状態が認識されます。 Authorizing コンテンツをアプリの AuthorizeView コンポーネントで提供することはできますが、このコンテンツが表示されることはありません。
[Authorize]
属性
[Authorize]
属性は、Razor コンポーネントで使用できます。
@page "/"
@attribute [Authorize]
You can only see this if you're signed in.
重要
[Authorize]
は、@page
ルーター経由で到達した Blazor コンポーネントでのみ使用します。 ルーティングの側面としてのみ認可が実行され、ページ内にレンダリングされた子コンポーネントには実行されません。 ページ内の特定部分の表示を承認するには、代わりに AuthorizeView を使用します。
[Authorize]
属性は、ロールベースまたはポリシーベースの承認もサポートしています。 ロールベースの承認の場合は、Roles パラメーターを使用します。
@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]
<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>
ポリシーベースの承認の場合は、Policy パラメーターを使用します。
@page "/"
@attribute [Authorize(Policy = "Over21")]
<p>You can only see this if you satisfy the 'Over21' policy.</p>
Roles も Policy も指定されていない場合、[Authorize]
には既定のポリシーが使われます。
- 認証された (サインインした) ユーザーが認可されます。
- 認証されていない (サインアウトした) ユーザーは認可されません。
ユーザーが承認されておらず、アプリがRouter
コンポーネントを使用して承認されていないコンテンツをカスタマイズしない場合、フレームワークは自動的に次のフォールバック メッセージを表示します。
Not authorized.
リソース承認
リソースのユーザーを承認するには、要求のルート データを Resource の AuthorizeRouteView パラメーターに渡します。
要求されたルートの Router.Found コンテンツで、次のようにします。
<AuthorizeRouteView Resource="routeData" RouteData="routeData"
DefaultLayout="typeof(MainLayout)" />
手続き型ロジックで承認状態データを渡して使用する方法の詳細については、「 カスケード パラメーターとして認証状態を公開する 」セクションを参照してください。
AuthorizeRouteView がリソースのルート データを受け取ると、承認ポリシーから RouteData.PageType と RouteData.RouteValues へのアクセスが可能になり、カスタム ロジックで承認決定ができるようになります。
次の例では、アプリの承認サービス構成 (EditUser
) の AuthorizationOptions で、次のロジックを使用して AddAuthorizationCore ポリシーが作成されます。
-
id
のキーを持つルート値が存在するかどうかを確認します。 そのキーが存在する場合、ルート値をvalue
に格納します。 -
id
という名前の変数内に、value
を文字列として格納するか、空の文字列値 (string.Empty
) を設定します。 -
id
が空の文字列でないとき、文字列の値がtrue
で始まる場合は、ポリシーが満たされていることをアサートします (EMP
を返します)。 それ以外の場合は、ポリシーが失敗したことをアサートします (false
を返します)。
Program
ファイルで次の操作を行います。
Microsoft.AspNetCore.Components と System.Linq の名前空間を追加します。
using Microsoft.AspNetCore.Components; using System.Linq;
ポリシーを追加します。
options.AddPolicy("EditUser", policy => policy.RequireAssertion(context => { if (context.Resource is RouteData rd) { var routeValue = rd.RouteValues.TryGetValue("id", out var value); var id = Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty; if (!string.IsNullOrEmpty(id)) { return id.StartsWith("EMP", StringComparison.InvariantCulture); } } return false; }) );
上記の例は、過度に単純化された承認ポリシーであり、実施例で概念を示すためだけに使用されています。 承認ポリシーの作成と構成の詳細については、 ASP.NET Core でのポリシー ベースの承認に関するページを参照してください。
次の EditUser
コンポーネントでは、/users/{id}/edit
のリソースにユーザーの識別子 ({id}
) のルート パラメーターが含まれています。 コンポーネントで前述の EditUser
承認ポリシーを使用して、id
のルート値が EMP
で始まるかどうかを判断します。
id
が EMP
で始まる場合、ポリシーは成功し、コンポーネントへのアクセスが承認されます。
id
が EMP
以外の値で始まり、id
が空の文字列である場合、ポリシーは失敗し、コンポーネントは読み込まれません。
EditUser.razor
:
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]
<h1>Edit User</h1>
<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>
@code {
[Parameter]
public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]
<h1>Edit User</h1>
<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>
@code {
[Parameter]
public string? Id { get; set; }
}
Router
コンポーネントを使用して未承認コンテンツをカスタマイズする
Router コンポーネントを AuthorizeRouteView コンポーネントとともに使用すると、以下の場合にアプリがカスタム コンテンツを指定できます。
- ユーザーはコンポーネントに適用されている
[Authorize]
条件に失敗します。<NotAuthorized>
要素のマークアップが表示されます。[Authorize]
属性については、「[Authorize]
属性」セクションを参照してください。 - 非同期の認可が進行中です。これは通常、ユーザーの認証プロセスが進行中であることを意味します。
<Authorizing>
要素のマークアップが表示されます。
重要
Blazor および <NotAuthorized>
コンテンツを表示する <NotFound>
ルーター機能は、静的なサーバー側レンダリング (静的 SSR) 中は動作しません。これは、要求処理は完全に ASP.NET Core ミドルウェア パイプライン要求処理によって処理され、未承認の要求または不正な要求については Razor コンポーネントは一切表示されないためです。 静的 SSR 中の未承認の要求と不正な要求は、サーバー側の手法を使用して処理します。 詳細については、「 コア Blazor レンダリング モード ASP.NET」を参照してください。
<Router ...>
<Found ...>
<AuthorizeRouteView ...>
<NotAuthorized>
...
</NotAuthorized>
<Authorizing>
...
</Authorizing>
</AuthorizeRouteView>
</Found>
</Router>
Authorized と NotAuthorized のコンテンツには、他の対話型コンポーネントなど、任意の項目を含めることができます。
注
前述の例では、アプリの Program
ファイルにカスケード型の認証状態サービスを登録する必要があります。
builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
<Router ...>
<Found ...>
<AuthorizeRouteView ...>
<NotAuthorized>
...
</NotAuthorized>
<Authorizing>
...
</Authorizing>
</AuthorizeRouteView>
</Found>
</Router>
</CascadingAuthenticationState>
NotFound、Authorized、および NotAuthorized のコンテンツには、他の対話型コンポーネントなど、任意の項目を含めることができます。
NotAuthorized コンテンツが指定されていない場合、AuthorizeRouteView は次のフォールバック メッセージを使用します。
Not authorized.
Blazor WebAssembly プロジェクト テンプレートを基にして、認証を有効にして作成されたアプリには、RedirectToLogin
コンポーネントが含まれます。これは、<NotAuthorized>
コンポーネントの Router コンテンツに配置されています。 ユーザーが認証されていない場合 (context.User.Identity?.IsAuthenticated != true
)、RedirectToLogin
コンポーネントはブラウザーを authentication/login
エンドポイントにリダイレクトし、認証を行います。 ユーザーは ID プロバイダーで認証された後、要求された URL に戻ります。
手続き型ロジック
手続き型ロジックの一部としてアプリで承認規則をチェックする必要がある場合、型 Task<
AuthenticationState>
のカスケード パラメーターを使用してユーザーの ClaimsPrincipal を取得します。 ポリシーを評価するために、Task<
AuthenticationState>
を IAuthorizationService
などの他のサービスと組み合わせることができます。
次に例を示します。
-
user.Identity.IsAuthenticated
は、認証された (サインインした) ユーザーのコードを実行します。 -
user.IsInRole("admin")
は、'管理者' ロールのユーザーに対してコードを実行します。 -
(await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded
は、'content-editor' ポリシーを満たすユーザーに対してコードを実行します。
プロジェクト テンプレートから作成されたサーバー側 Blazor アプリには、適切な名前空間が含まれます。 クライアント側 Blazor アプリで、コンポーネント内またはアプリの Microsoft.AspNetCore.Authorization ファイル内に Microsoft.AspNetCore.Components.Authorization および _Imports.razor
の名前空間があることを確認します。
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
ProceduralLogic.razor
:
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService
<h1>Procedural Logic Example</h1>
<button @onclick="@DoSomething">Do something important</button>
@code {
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
private async Task DoSomething()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user is not null)
{
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
// ...
}
if (user.IsInRole("Admin"))
{
// ...
}
if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
.Succeeded)
{
// ...
}
}
}
}
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService
<h1>Procedural Logic Example</h1>
<button @onclick="@DoSomething">Do something important</button>
@code {
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
private async Task DoSomething()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user is not null)
{
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
// ...
}
if (user.IsInRole("Admin"))
{
// ...
}
if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
.Succeeded)
{
// ...
}
}
}
}
}
エラーのトラブルシューティング
一般的なエラー:
承認には、型
Task<AuthenticationState>
のカスケード パラメーターが必要です。 これを指定するにはCascadingAuthenticationState
の使用を検討してください。null
のauthenticationStateTask
値を受け取る
このプロジェクトは、サーバー側 Blazor テンプレートを使用し、認証を有効にして作成されなかった可能性があります。
.NET 7 以前では、UI ツリーの一部を <CascadingAuthenticationState>
でラップします (例: Blazor ルーターの周囲)。
<CascadingAuthenticationState>
<Router ...>
...
</Router>
</CascadingAuthenticationState>
.NET 8 以降では、CascadingAuthenticationState コンポーネントを使用しないでください。
- <CascadingAuthenticationState>
<Router ...>
...
</Router>
- </CascadingAuthenticationState>
代わりに、Program
ファイル内のサービス コレクションにカスケード型の認証状態サービスを追加します。
builder.Services.AddCascadingAuthenticationState();
CascadingAuthenticationState コンポーネント (.NET 7 以前) または AddCascadingAuthenticationState によって提供されるサービス (.NET 8 以降) によって、Task<
AuthenticationState>
カスケード型パラメーターが提供されます。このパラメーターは、基盤となる AuthenticationStateProvider 依存関係の挿入サービスから値を受け取ります。
個人を特定できる情報 (PII)
Microsoft は、ドキュメントで個人を特定できる情報 (PII) について説明する場合、 "個人データ" (GDPR 4.1) に GDPR 定義 を使用します。
PII とは、識別された、または識別可能な自然人に関連する情報を指します。 識別可能な自然人とは、以下のいずれかにより、直接または間接的に特定できる自然人を指します。
- 名前
- 識別番号
- 所在地の座標
- オンライン識別子
- その他の特定の要素
- 物理
- 生理学的
- 遺伝的
- 精神的 (心理的)
- 経済的
- 文化
- 社会的アイデンティティ
その他のリソース
- サーバー側とBlazor Web Appに関するリソース
- クイック スタート: microsoft によるサインインを ASP.NET Core Web アプリに追加する
- クイック スタート: Microsoft ID プラットフォームを使用して ASP.NET Core Web API を保護する
-
プロキシ サーバーとロード バランサーを操作するように ASP.NET Core を構成する: 次のガイダンスが含まれています。
- 転送されたヘッダー ミドルウェアを使用した、プロキシ サーバーと内部ネットワークの間での HTTPS スキーム情報の保持。
- 追加のシナリオとユース ケース (手動スキーム構成を含む)、正しい要求ルーティングのための要求パスの変更、Linux および IIS 以外のリバース プロキシのための要求スキームの転送。
- Microsoft ID プラットフォームのドキュメント
- ASP.NET の主要なセキュリティ に関するトピック
- ASP.NET Core で Windows 認証を構成する
- ASP.NET Core Blazor アプリでの IHttpContextAccessor/HttpContext
- Authentication.MSAL JavaScript ライブラリのカスタム バージョンをビルドする
- Awesome Blazor: 認証 コミュニティのサンプル リンク
- ASP.NET Core Blazor Hybrid の認証と承認
- サーバー側 Blazor に関するリソース
- クイック スタート: microsoft によるサインインを ASP.NET Core Web アプリに追加する
- クイック スタート: Microsoft ID プラットフォームを使用して ASP.NET Core Web API を保護する
-
プロキシ サーバーとロード バランサーを操作するように ASP.NET Core を構成する: 次のガイダンスが含まれています。
- 転送されたヘッダー ミドルウェアを使用した、プロキシ サーバーと内部ネットワークの間での HTTPS スキーム情報の保持。
- 追加のシナリオとユース ケース (手動スキーム構成を含む)、正しい要求ルーティングのための要求パスの変更、Linux および IIS 以外のリバース プロキシのための要求スキームの転送。
- Microsoft ID プラットフォームのドキュメント
- ASP.NET の主要なセキュリティ に関するトピック
- ASP.NET Core Blazor アプリでの IHttpContextAccessor/HttpContext
- ASP.NET Core で Windows 認証を構成する
- Authentication.MSAL JavaScript ライブラリのカスタム バージョンをビルドする
- Awesome Blazor: 認証 コミュニティのサンプル リンク
ASP.NET Core