次の方法で共有


ASP.NET Core Blazor の認証と承認

注意

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

警告

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 9 バージョンを参照してください。

この記事では、Blazor アプリのセキュリティの構成と管理に関する ASP.NET Core のサポートについて説明します。

Blazor は、既存の ASP.NET Core 認証メカニズムを使用してユーザーの identity を確認します。 詳細なメカニズムは、Blazor アプリのホスティング方法、サーバー側またはクライアント側かによって異なります。

セキュリティ シナリオは、Blazor アプリでサーバー側とクライアント側で実行される承認コードによって異なります。 サーバー上で実行される承認コードの場合、承認チェックでは、アプリとコンポーネントの領域に対してアクセス規則を適用できます。 クライアント側のコード実行は改ざんされるおそれがあるため、クライアントで実行される承認コードを信頼して、アクセス規則を無条件に強勢したり、クライアント側のコンテンツの表示を制御したりすることはできません。

認可規則の適用を保証する必要がある場合は、クライアント側コードで承認チェックを実装しないでください。 認可チェックとルールの適用に、サーバー側レンダリング (SSR) のみに依存する Blazor Web App を構築します。

認可規則の適用とデータとコードのセキュリティを保証する必要がある場合は、クライアント側アプリを開発しないでください。 Blazor Server アプリを構築します。

Razor Pages の承認規則は、ルーティング可能な Razor コンポーネントには適用されません。 ルーティング不可能な Razor コンポーネントが Razor Pages アプリのページに埋め込まれている場合、ページの認可規則は、Razor コンポーネントと、ページのコンテンツの rest の部分に間接的に影響します。

ASP.NET Core Identity は、要求と応答の HTTP 通信のコンテキストで動作するように設計されています。これは一般に、Blazor アプリのクライアント/サーバー通信モデルではありません。 ユーザー管理に ASP.NET Core Identity を使用する ASP.NET Core アプリでは、ユーザー登録、ログイン、ログアウト、その他のユーザー管理タスクなど、Identity 関連の UI 用に、Razor コンポーネントではなく Razor Pages を使用する必要があります。 Identity タスクを直接処理する Razor コンポーネントを構築することは、一部のシナリオでは可能ですが、Microsoft は推奨またはサポートしていません。

SignInManager<TUser>UserManager<TUser> など、ASP.NET Core 抽象化は、Razor コンポーネントではサポートされていません。 ASP.NET Core Identity を Blazor と共に使用する方法について詳しくは、「サーバー側 Blazor アプリへの ASP.NET Core Identity のスキャフォールディング」を参照してください。

Note

この記事のコード例では、null 許容参照型 (NRT) と .NET コンパイラの null 状態スタティック分析を採用しています。これは、.NET 6 以降の ASP.NET Core でサポートされています。 ASP.NET Core 5.0 以前をターゲットとする場合は、この記事の例から null 型の指定 (?) を削除してください。

機密データと資格情報を安全に維持する

アプリ シークレット、接続文字列、資格情報、パスワード、個人識別番号 (PIN)、プライベート .NET/C# コード、秘密キー/トークンをクライアント側コードに格納しないでください。これは安全ではありません。 クライアント側の Blazor コードでは、制御するセキュリティで保護された Web API を使用して、セキュリティで保護されたサービスとデータベースにアクセスする必要があります。

テスト/ステージング環境と運用環境では、サーバー側の Blazor コードと Web API は、プロジェクト コードまたは構成ファイル内で資格情報を維持しないように、セキュリティで保護された認証フローを使用する必要があります。 ローカル開発テスト以外では、環境変数が最も安全なアプローチではないため、環境変数を使用して機密データを格納しないようにすることをお勧めします。 ローカル開発テストでは、機密データをセキュリティで保護するために、 Secret Manager ツール をお勧めします。 詳細については、次のリソースを参照してください。

クライアント側およびサーバー側のローカル開発とテストの場合は、 Secret Manager ツール を使用して機密性の高い資格情報をセキュリティで保護します。

Microsoft Azure サービスのマネージド ID

Microsoft Azure サービスの場合は、マネージド ID を使用することをお勧めします。 マネージド ID を使用すると、アプリ コードに資格情報を保存せずに、Azure サービスに対して安全に認証を行うことができます。 詳細については、次のリソースを参照してください。

偽造防止サポート

Blazor テンプレート:

  • Program ファイルで AddRazorComponents が呼び出されると、偽造防止サービスが自動的に追加されます。
  • Program ファイル内の要求処理パイプラインで UseAntiforgery を呼び出して偽造防止ミドルウェアを追加し、クロスサイト リクエスト フォージェリ (CSRF/XSRF) の脅威を軽減するためにエンドポイントの偽造防止保護を必要とします。 UseAntiforgery は、 UseHttpsRedirection後に呼び出されます。 UseAntiforgeryへの呼び出しは、呼び出しが存在する場合は、UseAuthenticationしてUseAuthorizationした後に行う必要があります。

AntiforgeryToken コンポーネントが偽造防止トークンを非表示フィールドとしてレンダリングします。このコンポーネントはフォーム (EditForm) インスタンスに自動的に追加されます。 詳細については、「ASP.NET Core Blazor のフォームの概要」を参照してください。

AntiforgeryStateProvider サービスは、現在のセッションに関連付けられている偽造防止トークンへのアクセスを提供します。 サービスを挿入し、その GetAntiforgeryToken() メソッドを呼び出して、現在の AntiforgeryRequestTokenを取得します。 詳しくは、「ASP.NET Core Blazor アプリから Web API を呼び出す」をご覧ください。

Blazor は、要求トークンをコンポーネントの状態に保存します。これにより、対話型コンポーネントが要求にアクセスできない場合でも、偽造防止トークンを使用できるようになります。

Note

偽造防止のための軽減策が要求されるのは、フォーム データを application/x-www-form-urlencodedmultipart/form-data、または text/plain としてエンコードしてサーバーに送信したときだけです。その理由は、有効なフォームのエンコードタイプはこれらだけであるからです。

詳細については、次のリソースを参照してください。

サーバー側の Blazor の認証

サーバー側の Blazor アプリは、セキュリティについて ASP.NET Core アプリと同じ方法で構成されています。 詳細については、「ASP.NET Core Security の概要」を参照してください。

認証コンテキストは、アプリの起動時にのみ確立されます。これは、アプリが最初にクライアントとのSignalR接続経由で WebSocket に接続場合です。 認証は、cookie または他の何らかのベアラー トークンに基づいて行うことができますが、SignalR ハブを経由し、回線内で完全に管理されます。 認証コンテキストは、回線の有効期間を通して維持されます。 アプリは、ユーザーの認証状態を定期的 (30 分ごと) に再検証します。

アプリでカスタム サービスのユーザーをキャプチャする必要がある場合、またはユーザーに対する更新に対応する必要がある場合は、コア サーバー側 ASP.NET および追加のセキュリティ シナリオ Blazor Web App 参照してください

Blazor は、すべてのページ ナビゲーションで Cookie を使って新しい HTTP 要求を行う従来のサーバーでレンダリングされる Web アプリとは異なるものです。 ナビゲーション イベントの間に認証がチェックされます。 ただし、Cookie は関係しません。 Cookie は、サーバーに対して HTTP 要求を行うときにのみ送信され、ユーザーが Blazor アプリ内を移動したときには行われません。 ナビゲーションの間に、ユーザーの認証状態が Blazor 回線内でチェックされ、ユーザーは RevalidatingAuthenticationStateProvider 抽象化を使ってサーバー上でいつでもこれを更新できます。

重要

カスタム NavigationManager を実装してナビゲーションの間に認証の検証を行うことは推奨されません。 ナビゲーションの間にアプリでカスタム認証状態ロジックを実行する必要がある場合は、カスタム AuthenticationStateProvider を使います。

Note

この記事のコード例では、null 許容参照型 (NRT) と .NET コンパイラの null 状態スタティック分析を採用しています。これは、.NET 6 以降の ASP.NET Core でサポートされています。 ASP.NET Core 5.0 以前をターゲットとする場合は、この記事の例から null 型の指定 (?) を削除してください。

組み込み、またはカスタムの AuthenticationStateProvider サービスでは、ASP.NET Core の HttpContext.User から認証状態データが取得されます。 このようにして、認証状態は既存の ASP.NET Core 認証メカニズムと統合されます。

サーバー側認証の詳細については、「 ASP.NET Core Blazor 認証と承認を参照してください。

Razor コンポーネント内の IHttpContextAccessor/HttpContext

有効な HttpContext が使用できないため、対話型レンダリングでは IHttpContextAccessor を避ける必要があります。

IHttpContextAccessor は、サーバー上で静的にレンダリングされるコンポーネントに対して使用することができます。 ただし、可能であれば使用を避けることをお勧めします。

HttpContext は、App コンポーネント (Components/App.razor) 内のヘッダーやその他のプロパティの検査や変更などの一般的なタスク用に、"静的にレンダリングされたルート コンポーネント" 内でのみ、カスケード パラメーターとして使用できます。 対話型レンダリングの場合、この値は常に null です。

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

対話型コンポーネント内で HttpContext が必要なシナリオの場合は、サーバーから永続的なコンポーネントの状態を介してデータを取り込むことをお勧めします。 詳細については、コア サーバー側 ASP.NET および追加のセキュリティ シナリオ Blazor Web App 参照してください

サーバー側 Blazor アプリの Razor コンポーネントでは、IHttpContextAccessor/HttpContext を、直接にも間接的にも使用しないでください。 Blazor アプリは、ASP.NET Core パイプラインのコンテキストの外部で実行されます。 HttpContext は、IHttpContextAccessor 内で使用できるとは限りません。また、HttpContext は、Blazor アプリを開始したコンテキストが保持されることも保証されません。

アプリの初期レンダリング中にルート コンポーネント パラメーターを使って要求の状態を Blazor アプリに渡すことをお勧めします。 または、ルート コンポーネントの初期化ライフサイクル イベントにおいてアプリでスコープ サービスにデータをコピーすることで、アプリ全体で使用することもできます。 詳細については、コア サーバー側 ASP.NET および追加のセキュリティ シナリオ Blazor Web App 参照してください

サーバー側 Blazor のセキュリティでの重要な側面は、特定の回線に接続されているユーザーは Blazor 回線が確立された後のある時点で更新される可能性がありますが、IHttpContextAccessor は "更新されない" ということです。 カスタム サービスを使用してこのような状況に対処する方法の詳細については、「コア サーバー側ASP.NET および追加のセキュリティ シナリオBlazor Web Appを参照してください。

共有状態

サーバー側 Blazor アプリはサーバー メモリ内に存在し、アプリの複数のセッションが同じプロセス内でホストされます。 アプリ セッションごとに、Blazor によってそれ自体の依存関係挿入コンテナー スコープで回線が開始されるため、スコープ サービスは Blazor セッションごとに一意です。

警告

特別な注意を払っていない限り、同じサーバーの共有状態のアプリがシングルトン サービスを使用することはお勧めできません。これにより、回線をまたいだユーザー状態のリークなど、セキュリティ上の脆弱性が生じる可能性があります。

ステートフル シングルトン サービスがそのために特に設計されている場合、Blazor アプリでそれを使用できます。 たとえば、メモリ キャッシュでは特定のエントリにアクセスするためのキーが必要なため、シングルトン メモリ キャッシュの使用が許容されます。 キャッシュで使われるキャッシュ キーをユーザーが制御できないとすると、キャッシュに格納されている状態が回線間でリークすることはありません。

状態管理に関する一般的なガイダンスについては、「ASP.NET Core Blazor 状態管理」をご覧ください。

機密データと資格情報のサーバー側セキュリティ

テスト/ステージング環境と運用環境では、サーバー側の Blazor コードと Web API は、プロジェクト コードまたは構成ファイル内で資格情報を維持しないように、セキュリティで保護された認証フローを使用する必要があります。 ローカル開発テスト以外では、環境変数が最も安全なアプローチではないため、環境変数を使用して機密データを格納しないようにすることをお勧めします。 ローカル開発テストでは、機密データをセキュリティで保護するために、 Secret Manager ツール をお勧めします。 詳細については、次のリソースを参照してください。

クライアント側およびサーバー側のローカル開発とテストの場合は、 Secret Manager ツール を使用して機密性の高い資格情報をセキュリティで保護します。

プロジェクト テンプレート

ASP.NET Core Blazor 用のツール」のガイダンスに従って、新しいサーバー側の Blazor アプリを作成します。

サーバー側のアプリ テンプレートを選択し、プロジェクトを構成したら、[認証の種類] でアプリの認証を選択します。

  • なし (既定値): 認証なし。
  • [個別のアカウント]: ユーザー アカウントは、ASP.NET Core Identity を使用してアプリ内に格納されます。
  • なし (既定値): 認証なし。
  • [個別のアカウント]: ユーザー アカウントは、ASP.NET Core Identity を使用してアプリ内に格納されます。
  • Microsoft identity プラットフォーム: 詳細については、「ASP.NET Core Blazor の認証と認可」をご覧ください。
  • [Windows]: Windows 認証を使用します。

BlazorIdentity UI (個人アカウント)

Blazor では、[個人アカウント] の認証オプションを選んだ場合の、完全な Blazor ベースの Identity UI の生成がサポートされます。

Blazor Web App テンプレートで SQL Server データベースの Identity コードがスキャフォールディングされます。 コマンド ライン バージョンでは、SQLite が使用され、Identity の SQLite データベースが含まれています。

テンプレート:

  • 認証されたユーザーでの対話型サーバー側レンダリング (対話型 SSR) とクライアント側レンダリング (CSR) のシナリオがサポートされています。
  • IdentityRazor コンポーネントと、ユーザーのサインインとサインアウトなどの日常的な認証タスクに関連するロジックを追加します。また、Identity コンポーネントでは、サードパーティ製アプリを使用したアカウントの確認やパスワードの回復多要素認証などの高度な Identity 機能もサポートされています。 なお、Identity コンポーネント自体は対話機能をサポートしていません。
  • Identity 関連のパッケージと依存関係を追加する。
  • _Imports.razor の Identity パッケージを参照する。
  • カスタム ユーザー Identity クラス (ApplicationUser) を作成します。
  • EF Core データベース コンテキスト (ApplicationDbContext) を作成して登録します。
  • 組み込み Identity エンドポイントのルーティングを構成します。
  • Identity 検証とビジネス ロジックを含める。

Blazor フレームワークの Identity コンポーネントを調べるには、Blazor Web App プロジェクト テンプレート内の Account フォルダー (参照ソース)Pages および Shared フォルダー内でそれらにアクセスします。

対話型 WebAssembly または対話型自動レンダリング モードを選択すると、サーバーはすべての認証要求と認可要求を処理し、Identity コンポーネントは Blazor Web App のメイン プロジェクト内のサーバー上で静的にレンダリングします。

このフレームワークは、ユーザーの認証状態をブラウザーにフローするためのカスタム AuthenticationStateProvider をサーバー プロジェクトとクライアント (.Client) プロジェクトの両方で提供します。 サーバー プロジェクトは AddAuthenticationStateSerialization を呼び出し、クライアント プロジェクトは AddAuthenticationStateDeserialization を呼び出します。 クライアントではなくサーバーで認証を行う場合、アプリは、プリレンダリング中、.NET WebAssembly ランタイムが初期化される前に認証状態にアクセスできます。 カスタムの AuthenticationStateProvider の実装は、Persistent Component State サービス (PersistentComponentState) を使用して認証状態を HTML コメントにシリアル化し、その後に WebAssembly からそれを再度読み取って新しい AuthenticationState インスタンスを作成します。 詳細については、「Blazor Web App での認証状態の管理」セクションをご覧ください。

対話型サーバー ソリューションの場合にのみ、IdentityRevalidatingAuthenticationStateProvider (参照ソース) は、対話型回線が接続されてから 30 分ごとに接続されたユーザーのセキュリティ スタンプを再検証するサーバー側 AuthenticationStateProvider となります。

対話型 WebAssembly または対話型自動レンダリング モードを選択すると、サーバーはすべての認証要求と認可要求を処理し、Identity コンポーネントは Blazor Web App のメイン プロジェクト内のサーバー上で静的にレンダリングします。 プロジェクト テンプレートには、.Client プロジェクトに PersistentAuthenticationStateProvider クラス (参照ソース) が含まれており、サーバーとブラウザーの間でユーザーの認証状態を同期します。 このクラスは、AuthenticationStateProvider のカスタム実装です。 このプロバイダーは、Persistent Component State サービス (PersistentComponentState) を使用して認証状態をプリレンダリングし、それをページに保持します。

Blazor Web App のメイン プロジェクトでは、認証状態プロバイダーの名前は IdentityRevalidatingAuthenticationStateProvider (参照ソース) (サーバーのインタラクティビティ ソリューションのみ) または PersistingRevalidatingAuthenticationStateProvider (参照ソース) (WebAssembly または自動インタラクティビティ ソリューション) です。

BlazorIdentity は、ファクトリで作成されていない DbContext インスタンスに依存します。これは、プロジェクト テンプレートの Identity コンポーネントが対話機能をサポートせずに静的にレンダリングするには DbContext で十分であるため、意図的なものです。

Identity コンポーネントに対して同時に静的 SSR を適用しているときに、グローバル インタラクティブレンダリング モードがどのように非 Identity コンポーネントに適用されるかについては、「ASP.NET Core の Blazor レンダリング モード」を参照してください。

プリレンダリングされた状態の永続化の詳細については、「ASP.NET Core Razor コンポーネントのプリレンダリング」を参照してください。

Blazor Identity UI の詳細と、ソーシャル Web サイトを介した外部ログインの統合に関するガイダンスについては、「.NET 8 の identity の新機能」をご覧ください。

Note

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

Blazor Web App で認証状態を管理する

このセクションは、以下を採用する Blazor Web App に適用されます。

  • 個人アカウント
  • クライアント側レンダリング (CSR、WebAssembly ベースの対話性)。

クライアント側認証状態プロバイダーは、Blazor でのみ使用され、ASP.NET Core 認証システムと統合されません。 プリレンダリング中、Blazor によりページで定義されたメタデータが考慮され、ASP.NET Core 認証システムを使用して、ユーザーが認証されているかどうかが判断されます。 ユーザーが 1 つのページから別のページに移動すると、クライアント側の認証プロバイダーが使用されます。 ユーザーがページを更新すると (ページ全体の再読み込み)、クライアント側の認証状態プロバイダーはサーバーでの認証の決定に関与しません。 ユーザーの状態はサーバーによって保持されないため、クライアント側で維持されていた認証状態は失われます。

これに対処するには、ASP.NET Core 認証システム内で認証を実行するのが最適な方法です。 クライアント側の認証状態プロバイダーでは、ユーザーの認証状態の反映のみが処理されます。 認証状態プロバイダーでこれを実現する方法の例は、Blazor Web App プロジェクト テンプレートによって以下に示されています。

以下のように、サーバー プロジェクトの Program ファイル内で AddAuthenticationStateSerialization を呼び出します。これによって Persistent Component State サービス (PersistentComponentState) を使用してサーバー側 AuthenticationStateProvider によって返された AuthenticationState がシリアル化されます。

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization();

この API がシリアル化するのは、ブラウザーでアクセスするためのサーバー側の名前とロールの要求だけです。 すべての要求を含めるには、以下のように、サーバー側の AddAuthenticationStateSerialization の呼び出しで SerializeAllClaimstrue に設定します。

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization(
        options => options.SerializeAllClaims = true);

クライアント (.Client) プロジェクトの Program ファイル内で、AddAuthenticationStateDeserialization を呼び出します。これによって AuthenticationStateData および Persistent Component State サービス (PersistentComponentState) を使用してサーバーから逆シリアル化された AuthenticationState の状態で AuthenticationStateProvider が追加されます。 サーバー プロジェクトには、対応する AddAuthenticationStateSerialization の呼び出しが必要です。

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();

Note

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

スキャフォールディング Identity

サーバー側の Blazor アプリへの Identity のスキャフォールディングについて詳しくは、「ASP.NET Core プロジェクトでの Identity のスキャフォールディング」をご覧ください。

サーバー側の Blazor アプリに Identity をスキャフォールディングします。

外部プロバイダーからの追加のクレームとトークン

外部プロバイダーからの追加の要求を格納するには、「ASP.NET Core で外部プロバイダーからの追加の要求とトークンを保持する」を参照してください。

Identity Server を使用した Azure App Service on Linux

Identity Server を使用して Azure App Service on Linux にデプロイするときに、発行者を明示的に指定します。 詳しくは、「Identity を使用して SPA の Web API バックエンドをセキュリティで保護する方法」を参照してください。

コンポーネントにスコープ設定されたサービス用の AuthenticationStateProvider を挿入する

正しく初期化されていない AuthenticationStateProvider の新しいインスタンスが作成されるため、カスタム スコープ内で AuthenticationStateProvider の解決を試みないでください。

コンポーネントにスコープ設定されたサービス内の AuthenticationStateProvider にアクセスするには、@inject ディレクティブまたは [Inject]属性を使用して 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.csStartup.ConfigureServices で:

services.AddScoped<ExampleService>();

次の InjectAuthStateProvider コンポーネントでは、以下のことを行います。

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);
    }
}

詳しくは、「ASP.NET Core Blazor 依存関係の挿入」で OwningComponentBase についてのガイダンスをご覧ください。

カスタム AuthenticationStateProvider を使用したプリレンダリング中に未承認のコンテンツが表示される

カスタムの AuthenticationStateProvider を使ってプリレンダリング中に、認可されていないコンテンツ (たとえば、AuthorizeView コンポーネント内のコンテンツ) が表示されないようにするには、次のいずれかの方法を採用します。

  • プリレンダリングを無効にする: ルート コンポーネントではないアプリのコンポーネント階層の最上位コンポーネントで、prerender パラメーターを false に設定してレンダリング モードを指定します。

    Note

    ルート コンポーネントを対話型にすること (App コンポーネントなど) はサポートされていません。 そのため、プリレンダリングを App コンポーネントで直接無効にすることはできません。

    Blazor Web App プロジェクト テンプレートに基づくアプリの場合、プリレンダリングの無効化は通常、App コンポーネント内で Routes コンポーネントが使用されている場所 (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 は、ユーザーの認証状態 (アプリにサインインしているかどうか、サインインに使われているユーザー) をアプリに示すだけです。

認証は、Razor Pages および MVC アプリと同じ ASP.NET Core Identity 認証を使用します。 ASP.NET Core Identity に格納されたユーザー状態は、アプリにコードを追加しなくても Blazor に流れます。 アプリの Blazor 部分で Identity の機能を有効にするには、ASP.NET Core Identity の記事とチュートリアルのガイダンスに従ってください。

ASP.NET Core Identity の外部での一般的な状態管理のガイダンスについては、「ASP.NET Core Blazor 状態管理」をご覧ください。

追加のセキュリティ抽象化

認証状態の管理には、さらに 2 つの抽象化が関与します。

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

サインアウト時の認証状態管理

サーバー側の Blazor は、すべてのブラウザー タブを含め、回線の有効期間中、ユーザーの認証状態を保持します。 ユーザーが 1 つのタブでサインアウトしたときにすべての [ブラウザー] タブでユーザーをプロアクティブにサインオフするには、短い RevalidationIntervalRevalidatingServerAuthenticationStateProvider (参照ソース) を実装する必要があります。

Note

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「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 フレームワークや任意のオペレーティング システム用のネイティブ アプリを含め、すべてのクライアント側アプリのテクノロジにも同じことが当てはまります。

以下を追加します。

認証を処理するには、組み込み、またはカスタムの AuthenticationStateProvider サービスを使用します。

クライアント側認証の詳細については、「ASP.NET Core Blazor WebAssembly をセキュリティで保護する」をご覧ください。

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.IsAuthenticatedtrue である場合、ユーザーが 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.IsAuthenticatedtrue である場合、要求を列挙し、役割のメンバーシップを評価できます。

AuthorizeRouteView とカスケード認証状態サービスを使用して、Task<AuthenticationState> カスケード パラメーター を設定します。

認証を有効にした Blazor プロジェクト テンプレートから Blazor アプリを作成すると、アプリには次の例に示す AuthorizeRouteViewAddCascadingAuthenticationState の呼び出しが含まれます。 クライアント側 Blazor アプリには、必要なサービス登録も含まれています。 詳細については、「Router コンポーネントを使用して承認されていないコンテンツをカスタマイズする」セクションをご覧ください。

<Router ...>
    <Found ...>
        <AuthorizeRouteView RouteData="routeData" 
            DefaultLayout="typeof(Layout.MainLayout)" />
        ...
    </Found>
</Router>

Program ファイルで、カスケード認証状態サービスを登録します:

builder.Services.AddCascadingAuthenticationState();

AuthorizeRouteViewCascadingAuthenticationState の各コンポーネントを使用して、Task<AuthenticationState> カスケード パラメーターを設定します。

認証が有効にされた Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、アプリには、次の例で示す AuthorizeRouteViewCascadingAuthenticationState コンポーネントが含まれます。 クライアント側 Blazor アプリには、必要なサービス登録も含まれています。 詳細については、「Router コンポーネントを使用して承認されていないコンテンツをカスタマイズする」セクションをご覧ください。

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="routeData" 
                DefaultLayout="typeof(MainLayout)" />
            ...
        </Found>
    </Router>
</CascadingAuthenticationState>

Note

ASP.NET Core 5.0.1 のリリースと、その他の 5.x リリースでは、Router コンポーネントに @trueに設定された PreferExactMatches パラメーターが含まれています。 詳細については、「ASP.NET Core 3.1 から 5.0 への移行」を参照してください。

クライアント側 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 コンテンツが選択的に表示されます。 このアプローチは、ユーザーに対してデータを表示するだけで済み、手続き型ロジックでユーザーの identity を使用する必要がない場合に便利です。

このコンポーネントでは、型 AuthenticationState (Razor 構文の @context) の context 変数が公開されており、これを使って、サインインしたユーザーに関する情報にアクセスできます。

<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 に追加の承認ロジックを実装します。

Blazor Web App の Razor コンポーネントは、静的サーバー側レンダリング (静的 SSR) 中にサーバー側で認可が失敗した場合に <NotAuthorized> コンテンツを表示しません。 サーバー側 ASP.NET Core パイプラインは、サーバー上で認可を処理します。 サーバー側の手法を使用して、承認されていない要求を処理します。 詳細については、「ASP.NET Core Blazor レンダリング モード」を参照してください。

警告

AuthorizeView に関連付けられたクライアント側のマークアップとメソッドは、クライアント側 Blazor アプリでレンダリングされた UI での表示と実行からのみ保護されます。 クライアント側 Blazor で認可されたコンテンツとセキュリティで保護されたメソッドを保護するために、通常、サーバー API に対する安全で認可された Web API 呼び出しによってコンテンツは提供され、アプリに格納されることはありません。 詳細については、ASP.NET Core Blazor アプリから Web API を呼び出す方法の記事と「ASP.NET Core Blazor WebAssembly のセキュリティに関するその他のシナリオ」を参照してください。

AuthorizedNotAuthorized のコンテンツには、他の対話型コンポーネントなど、任意の項目を含めることができます。

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>

ユーザーが AdminSuperuser の両方のロール要求を持つことを必須にするには、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>

上記のコードは、AuthenticationState コンテキストの競合を防ぐため、内部 AuthorizeView コンポーネントに対する Context を確立します。 AuthenticationState コンテキストは、コンテキストにアクセスするための標準的なアプローチ (@context.User) を使用して、外部 AuthorizeView でアクセスされます。 コンテキストは、名前付き innerContext コンテキスト (@innerContext.User) を使用して、内部 AuthorizeView でアクセスされます。

構成ガイダンスなどの詳細については、「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 でのポリシー ベースの認可」を参照してください。

RolesPolicy も指定されていない場合、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.

重要

Blazor ルーター経由で送信される @page コンポーネントでのみ、[Authorize] を使ってください。 承認はルーティングの一面としてのみ実行され、ページ内にレンダリングされた子コンポーネントに対しては実行され "ません"。 ページ内の特定部分の表示を承認するには、代わりに 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>

RolesPolicy も指定されていない場合、[Authorize] には既定のポリシーが使われます。

  • 認証された (サインインした) ユーザーが認可されます。
  • 認証されていない (サインアウトした) ユーザーは認可されません。

ユーザーが承認されておらず、アプリが Router コンポーネントを使用して未承認のコンテンツをカスタマイズしていない場合、フレームワークには、次のフォールバック メッセージが自動的に表示されます。

Not authorized.

リソース承認

リソースのユーザーを承認するには、要求のルート データを AuthorizeRouteViewResource パラメーターに渡します。

要求されたルートの Router.Found コンテンツで、次のようにします。

<AuthorizeRouteView Resource="routeData" RouteData="routeData" 
    DefaultLayout="typeof(MainLayout)" />

手続き型ロジックでの承認状態データの受け渡し方法と使用方法の詳細については、「認証状態をカスケード パラメーターとして公開する」セクションを参照してください。

AuthorizeRouteView がリソースのルート データを受け取ると、承認ポリシーから RouteData.PageTypeRouteData.RouteValues へのアクセスが可能になり、カスタム ロジックで承認決定ができるようになります。

次の例では、アプリの承認サービス構成 (AddAuthorizationCore) の AuthorizationOptions で、次のロジックを使用して EditUser ポリシーが作成されます。

  • id のキーを持つルート値が存在するかどうかを確認します。 そのキーが存在する場合、ルート値を value に格納します。
  • id という名前の変数内に、value を文字列として格納するか、空の文字列値 (string.Empty) を設定します。
  • id が空の文字列でないとき、文字列の値が EMP で始まる場合は、ポリシーが満たされていることをアサートします (true を返します)。 それ以外の場合は、ポリシーが失敗したことをアサートします (false を返します)。

Program ファイルで次の操作を行います。

  • Microsoft.AspNetCore.ComponentsSystem.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 で始まるかどうかを判断します。 idEMP で始まる場合、ポリシーは成功し、コンポーネントへのアクセスが承認されます。 idEMP 以外の値で始まり、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> 要素のマークアップが表示されます。

重要

<NotAuthorized> および <NotFound> コンテンツを表示する Blazor ルーター機能は静的サーバー側レンダリング (静的 SSR) の際には機能しません。これは要求の処理が ASP.NET Core ミドルウェア パイプライン要求処理によって完全に処理され、承認されていない要求または不正な要求に対しては Razor コンポーネントがまったくレンダリングされないためです。 サーバー側の手法を使用して、静的 SSR における承認されていない要求と不正な要求を処理します。 詳細については、「ASP.NET Core Blazor レンダリング モード」を参照してください。

<Router ...>
    <Found ...>
        <AuthorizeRouteView ...>
            <NotAuthorized>
                ...
            </NotAuthorized>
            <Authorizing>
                ...
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
</Router>

AuthorizedNotAuthorized のコンテンツには、他の対話型コンポーネントなど、任意の項目を含めることができます。

Note

上記では、アプリの Program ファイルにカスケード認証状態サービスを登録する必要があります:

builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
    </Router>
</CascadingAuthenticationState>

NotFoundAuthorized、および NotAuthorized のコンテンツには、他の対話型コンポーネントなど、任意の項目を含めることができます。

NotAuthorized コンテンツが指定されていない場合、AuthorizeRouteView は次のフォールバック メッセージを使用します。

Not authorized.

認証が有効になっている Blazor WebAssembly プロジェクト テンプレートから作成されたアプリには、 Router コンポーネントの <NotAuthorized> コンテンツに配置される RedirectToLogin コンポーネントが含まれています。 ユーザーが認証されていない場合 (context.User.Identity?.IsAuthenticated != true)、RedirectToLogin コンポーネントはブラウザーを authentication/login エンドポイントにリダイレクトし、認証を行います。 ユーザーは identity プロバイダーで認証された後、要求された URL に戻ります。

手続き型ロジック

手続き型ロジックの一部としてアプリで承認規則をチェックする必要がある場合、型 Task<AuthenticationState> のカスケード パラメーターを使用してユーザーの ClaimsPrincipal を取得します。 ポリシーを評価するために、Task<AuthenticationState>IAuthorizationService などの他のサービスと組み合わせることができます。

次に例を示します。

  • user.Identity.IsAuthenticated は、認証された (サインインした) ユーザーのコードを実行します。
  • user.IsInRole("admin") は、'管理者' ロールのユーザーに対してコードを実行します。
  • (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded は、'content-editor' ポリシーを満たすユーザーに対してコードを実行します。

プロジェクト テンプレートから作成すると、サーバー側 Blazor アプリには適切な名前空間が含まれます。 クライアント側 Blazor アプリで、コンポーネントまたはアプリの _Imports.razor ファイル内に Microsoft.AspNetCore.AuthorizationMicrosoft.AspNetCore.Components.Authorization の名前空間があることを確認します。

@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 の使用を検討してください。

  • authenticationStateTaskに対してnull 値を受け取ります

認証が有効なサーバー側 Blazor テンプレート使用してプロジェクトが作成されなかった可能性があります。

.NET 7 以前では、UI ツリーの一部 (たとえば Blazor ルーターなど) を <CascadingAuthenticationState> でラップします。

<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 定義 (GDPR 4.1) を使用します。

PII とは、特定の自然人または特定可能な自然人に関連するあらゆる情報を指します。 特定可能な自然人とは、以下のいずれかを使用して、直接または間接的に特定できる自然人を指します。

  • 名前
  • ID 番号
  • 位置座標
  • オンライン識別子
  • その他の特定要因
    • 物理
    • 生理的
    • 遺伝的
    • 精神的 (心理的)
    • 経済的
    • 文化
    • ソーシャル identity

その他のリソース