ASP.NET Core Blazorの認証状態
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
この記事では、カスタム 認証状態プロバイダーを作成し、ユーザー認証状態変更通知をコードで受信する方法について説明します。
サーバー側およびクライアント側の Blazor アプリに対して行われる一般的なアプローチは似ていますが、正確な実装が異なるため、この記事では、サーバー側の Blazor アプリとクライアント側の Blazor アプリの間でピボットします。 記事の上部にあるピボット セレクターを使用して、作業中の Blazor プロジェクトの種類に合わせて記事のピボットを変更します。
- サーバー側 Blazor アプリ (Server ピボット): .NET 7 以前の Blazor Server と、.NET 8 以降の Blazor Web App のサーバー プロジェクト。
- クライアント側 Blazor アプリ (Blazor WebAssembly ピボット): .NETのすべてのバージョンのBlazor WebAssembly、または .NET 8 以降のBlazor Web Appの
.Client
プロジェクト。
抽象 AuthenticationStateProvider
クラス
Blazor フレームワークには、次のメンバーを持つ現在のユーザーの認証状態に関する情報を提供する抽象 AuthenticationStateProvider クラスが含まれています。
- GetAuthenticationStateAsync: 現在のユーザーの認証状態を非同期的に取得します。
- AuthenticationStateChanged: 認証状態が変更されたときに通知を提供するイベント。 たとえば、ユーザーがアプリにサインインまたはサインアウトすると、このイベントが発生する可能性があります。
- NotifyAuthenticationStateChanged: 認証状態変更イベントを発生させます。
カスタムの AuthenticationStateProvider
を実装する
アプリは、Blazor アプリの認証と承認のサポートを提供するMicrosoft.AspNetCore.Components.Authorization
NuGet パッケージを参照する必要があります。
Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
Program
ファイルで、次の認証、承認、およびカスケード認証状態サービスを構成します。
認証が有効になっている Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリは次のサービス登録で事前構成されます。これには、カスケード パラメーターとして認証状態が公開されます。 詳しくは、「ASP.NET Core Blazor の認証と承認」と、その記事の「Router
コンポーネントを使用して未承認のコンテンツをカスタマイズする」セクションの追加情報をご覧ください。
using Microsoft.AspNetCore.Components.Authorization;
...
builder.Services.AddAuthorization();
builder.Services.AddCascadingAuthenticationState();
Program
ファイルで、認証サービスと承認サービスを構成します。
認証が有効にされた Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリには次のサービス登録が含まれます。
using Microsoft.AspNetCore.Components.Authorization;
...
builder.Services.AddAuthorization();
Startup.cs
の Startup.ConfigureServices
で認証サービスと承認サービスを構成します。
認証が有効にされた Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリには次のサービス登録が含まれます。
using Microsoft.AspNetCore.Components.Authorization;
...
services.AddAuthorization();
Blazor WebAssembly アプリ (すべての .NET バージョン) または Blazor Web App (.NET 8 以降) の .Client
プロジェクトでは、Program
ファイルで認証サービス、承認サービス、およびカスケード認証状態サービスを構成します。
認証が有効になっている Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリは次のサービス登録で事前構成されます。これには、カスケード パラメーターとして認証状態が公開されます。 詳しくは、「ASP.NET Core Blazor の認証と承認」と、その記事の「Router
コンポーネントを使用して未承認のコンテンツをカスタマイズする」セクションの追加情報をご覧ください。
using Microsoft.AspNetCore.Components.Authorization;
...
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
Program
ファイルで、認証サービスと承認サービスを構成します。
認証が有効にされた Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリには次のサービス登録が含まれます。
using Microsoft.AspNetCore.Components.Authorization;
...
builder.Services.AddAuthorizationCore();
AuthenticationStateProvider をサブクラス化し、GetAuthenticationStateAsync をオーバーライドして、ユーザーの認証状態を作成します。 前の例では、すべてのユーザーがユーザー名 mrfibuli
で認証されます。
CustomAuthStateProvider.cs
:
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
public class CustomAuthStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity(
[
new Claim(ClaimTypes.Name, "mrfibuli"),
], "Custom Authentication");
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
}
Note
新しい ClaimsIdentity を作成する上記のコードでは、C# 12 (.NET 8) で導入された簡略化されたコレクション初期化を使用します。 詳細については、「コレクション式 - C# 言語リファレンス」をご覧ください。
CustomAuthStateProvider
サービスは Program
ファイルに登録されます。 AddScoped でスコープ付きサービスを登録します。
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
Blazor Server アプリで、スコープ付きサービスを、AddServerSideBlazorへの呼び出し後に AddScoped で登録します。
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
Blazor Server アプリで、スコープ付きサービスを、AddServerSideBlazorへの呼び出し後に AddScoped で登録します。
services.AddServerSideBlazor();
services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();
CustomAuthStateProvider
サービスは Program
ファイルに登録されます。 シングルトンサービスを AddSingleton で登録します。
builder.Services.AddSingleton<AuthenticationStateProvider, CustomAuthStateProvider>();
存在しない場合は、@using
ステートメントを _Imports.razor
ファイルに追加して、コンポーネント間で Microsoft.AspNetCore.Components.Authorization 名前空間を使用できるようにします。
@using Microsoft.AspNetCore.Components.Authorization;
Router コンポーネント定義で、ルート ビュー コンポーネントを確認するか、AuthorizeRouteView に変更します。 Router
コンポーネントの場所は、アプリの種類によって異なります。 プロジェクト内でコンポーネントの場所がわからない場合は、そのコンポーネントの場所を検索します。
<Router ...>
<Found ...>
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)" />
...
</Found>
</Router>
Note
認証が有効にされた Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリには AuthorizeRouteView コンポーネントが含まれます。 詳しくは、「ASP.NET Core Blazor の認証と承認」と、その記事の「Router
コンポーネントを使用して未承認のコンテンツをカスタマイズする」セクションの追加情報をご覧ください。
Router コンポーネントが配置されている場所:
- ルート ビュー コンポーネントを確認するか、AuthorizeRouteView に変更します。
- CascadingAuthenticationState コンポーネントを確認するか、Router コンポーネントの周囲にそのコンポーネントを追加します。
Router
コンポーネントの場所は、アプリの種類によって異なります。 プロジェクト内でコンポーネントの場所がわからない場合は、そのコンポーネントの場所を検索します。
<CascadingAuthenticationState>
<Router ...>
<Found ...>
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(MainLayout)" />
...
</Found>
</Router>
</CascadingAuthenticationState>
Note
認証が有効にされた Blazor プロジェクト テンプレートのいずれかから Blazor アプリを作成すると、そのアプリには AuthorizeRouteView コンポーネントと CascadingAuthenticationState コンポーネントが含まれます。 詳しくは、「ASP.NET Core Blazor の認証と承認」と、その記事の「Router
コンポーネントを使用して未承認のコンテンツをカスタマイズする」セクションの追加情報をご覧ください。
次の AuthorizeView コンポーネント例は、認証されたユーザー名を示しています。
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
</Authorized>
<NotAuthorized>
<p>You're not authorized.</p>
</NotAuthorized>
</AuthorizeView>
AuthorizeView の使用に関するガイダンスについては、「ASP.NET Core Blazor の認証と承認」をご覧ください。
認証状態変更通知
カスタム AuthenticationStateProvider
では、AuthenticationStateProvider 基本クラスで NotifyAuthenticationStateChanged を呼び出して、認証状態の変更を再レンダリングするようコンシューマーに通知できます。
次の例は、この記事で前述されている「カスタムの AuthenticationStateProvider
を実装する」セクションのガイダンスに従って行ったカスタム AuthenticationStateProvider の実装に基づいています。 そのセクションのガイダンスに既に従っている場合は、次の CustomAuthStateProvider
はセクションに示されているガイダンスに取って代わります。
次の CustomAuthStateProvider
の実装では、ユーザーをサインインさせて、認証状態の変更をコンシューマーに通知するために、カスタム メソッド AuthenticateUser
を公開してします。
CustomAuthStateProvider.cs
:
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
public class CustomAuthStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity();
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
public void AuthenticateUser(string userIdentifier)
{
var identity = new ClaimsIdentity(
[
new Claim(ClaimTypes.Name, userIdentifier),
], "Custom Authentication");
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(
Task.FromResult(new AuthenticationState(user)));
}
}
Note
新しい ClaimsIdentity を作成する上記のコードでは、C# 12 (.NET 8) で導入された簡略化されたコレクション初期化を使用します。 詳細については、「コレクション式 - C# 言語リファレンス」をご覧ください。
コンポーネントでは:
- AuthenticationStateProvider を挿入する。
- ユーザーの識別子を保持するフィールドを追加します。
- ボタンと、AuthenticationStateProvider を
CustomAuthStateProvider
にキャストしてからユーザーの識別子を使ってAuthenticateUser
を呼び出すメソッドを追加します。
@inject AuthenticationStateProvider AuthenticationStateProvider
<input @bind="userIdentifier" />
<button @onclick="SignIn">Sign in</button>
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
</Authorized>
<NotAuthorized>
<p>You're not authorized.</p>
</NotAuthorized>
</AuthorizeView>
@code {
public string userIdentifier = string.Empty;
private void SignIn()
{
((CustomAuthStateProvider)AuthenticationStateProvider)
.AuthenticateUser(userIdentifier);
}
}
上記のアプローチを拡張し、カスタム サービスを使って認証状態の変更の通知をトリガーできます。 次の CustomAuthenticationService
クラスは、認証状態プロバイダーがサブスクライブできるイベント (UserChanged
) で、現在のユーザーの要求プリンシパルをバッキング フィールド (currentUser
) に保持します。このイベントは NotifyAuthenticationStateChanged を呼び出します。 このセクションで後ほど示す追加の構成では、CurrentUser
を設定して UserChanged
イベントをトリガーするロジックと共に、CustomAuthenticationService
をコンポーネントに挿入できます。
CustomAuthenticationService.cs
:
using System.Security.Claims;
public class CustomAuthenticationService
{
public event Action<ClaimsPrincipal>? UserChanged;
private ClaimsPrincipal? currentUser;
public ClaimsPrincipal CurrentUser
{
get { return currentUser ?? new(); }
set
{
currentUser = value;
if (UserChanged is not null)
{
UserChanged(currentUser);
}
}
}
}
Program
ファイルで、CustomAuthenticationService
を依存関係挿入コンテナーに登録します。
builder.Services.AddScoped<CustomAuthenticationService>();
Startup.cs
の Startup.ConfigureServices
で、CustomAuthenticationService
を依存関係挿入コンテナーに登録します。
services.AddScoped<CustomAuthenticationService>();
Program
ファイルで、CustomAuthenticationService
を依存関係挿入コンテナーに登録します。
builder.Services.AddSingleton<CustomAuthenticationService>();
次の CustomAuthStateProvider
は、CustomAuthenticationService.UserChanged
イベントをサブスクライブします。 GetAuthenticationStateAsync
メソッドは、ユーザーの認証状態を返します。 初期状態で認証状態は CustomAuthenticationService.CurrentUser
の値に基づいています。 ユーザーに変更があると、GetAuthenticationStateAsync
への呼び出しに対して、新しいユーザー (new AuthenticationState(newUser)
) に新しい認証状態が作成されます。
using Microsoft.AspNetCore.Components.Authorization;
public class CustomAuthStateProvider : AuthenticationStateProvider
{
private AuthenticationState authenticationState;
public CustomAuthStateProvider(CustomAuthenticationService service)
{
authenticationState = new AuthenticationState(service.CurrentUser);
service.UserChanged += (newUser) =>
{
authenticationState = new AuthenticationState(newUser);
NotifyAuthenticationStateChanged(Task.FromResult(authenticationState));
};
}
public override Task<AuthenticationState> GetAuthenticationStateAsync() =>
Task.FromResult(authenticationState);
}
次のコンポーネントの SignIn
メソッドでは、CustomAuthenticationService.CurrentUser
に設定するために、ユーザーの識別子の要求プリンシパルが作成されます。
@using System.Security.Claims
@inject CustomAuthenticationService AuthService
<input @bind="userIdentifier" />
<button @onclick="SignIn">Sign in</button>
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
</Authorized>
<NotAuthorized>
<p>You're not authorized.</p>
</NotAuthorized>
</AuthorizeView>
@code {
public string userIdentifier = string.Empty;
private void SignIn()
{
var currentUser = AuthService.CurrentUser;
var identity = new ClaimsIdentity(
[
new Claim(ClaimTypes.Name, userIdentifier),
],
"Custom Authentication");
var newUser = new ClaimsPrincipal(identity);
AuthService.CurrentUser = newUser;
}
}
Note
新しい ClaimsIdentity を作成する上記のコードでは、C# 12 (.NET 8) で導入された簡略化されたコレクション初期化を使用します。 詳細については、「コレクション式 - C# 言語リファレンス」をご覧ください。
その他のリソース
- カスタム
AuthenticationStateProvider
を使用したプリレンダリング中に、サーバ側の未承認コンテンツが表示される IHttpClientFactory
を使用して設定したDelegatingHandler
からAuthenticationStateProvider
にアクセスする方法- OpenID Connect (OIDC) を使用して ASP.NET Core Blazor Web App をセキュリティで保護する
- ASP.NET Core Identity を使用した ASP.NET Core Blazor WebAssembly のセキュリティ保護 ホストされた Blazor WebAssembly アプリでの認証によるプリレンダリング
ASP.NET Core