configure-auth について
Blazor アプリの認証設定を支援するスキルです。コーディングエージェント向けに、サービス登録、ルート保護、レンダーモード別の Identity と認証状態の扱いを説明します。
主な機能
- 01認証・認可サービスの登録
- 02ロールとポリシーによるページ保護
- 03Identity ページの静的 SSR
- 04WebAssembly と Auto 向けの認証状態シリアライズ
活用シーン
- 01Blazor プロジェクトへの認証追加
- 02インタラクティブページでの Identity 障害の調査
- 03WebAssembly レンダリングの認証状態設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dotnet/ skills --skill configure-authインストール後、Claude Code で/configure-authを入力して読み込まれたか確認します。
詳細
認証の構成
ステップ 1 — AGENTS.md を読む
変更を加える前に、ワークスペースのルートにある AGENTS.md を読み、プロジェクトのインタラクティブモードとスコープを確認します。
ステップ 2 — Program.cs に認証サービスを登録する
// Program.cs (server project)
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthorization();
ASP.NET Core Identity を使用する場合は、Identity サービスを追加します。
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies();
builder.Services.AddIdentityCore<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
ステップ 3 — 認証とレンダーモードに対応するよう App.razor を設定する
App.razor コンポーネントでは AuthorizeRouteView を使用し、インタラクティブルーティングから除外されたページが静的にレンダリングされるよう、レンダーモードを条件付きで適用する必要があります。
<!DOCTYPE html>
<html>
<head>
<HeadOutlet @rendermode="RenderModeForPage" />
</head>
<body>
<Routes @rendermode="RenderModeForPage" />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
@code {
[CascadingParameter]
public HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage =>
HttpContext.AcceptsInteractiveRouting()
? InteractiveServer // replace with the app's render mode
: null;
}
Routes.razor(またはルーターを配置している場所)では、AuthorizeRouteView を使用します。
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)">
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated != true)
{
<RedirectToLogin />
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
ステップ 4 — ページとコンポーネントを保護する
ページの [Authorize] 属性
@page "/admin"
@attribute [Authorize]
ロールまたはポリシーを使用する場合:
@attribute [Authorize(Roles = "Admin")]
@attribute [Authorize(Policy = "RequireManager")]
条件付き UI に使用する AuthorizeView
<AuthorizeView>
<Authorized>Welcome, @context.User.Identity?.Name!</Authorized>
<NotAuthorized><a href="Account/Login">Log in</a></NotAuthorized>
</AuthorizeView>
ロール/ポリシーのバリエーション:
<AuthorizeView Roles="Admin,Manager">
<Authorized>Admin content here</Authorized>
</AuthorizeView>
コードから認証状態にアクセスする
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState is not null)
{
var state = await AuthState;
var isAdmin = state.User.IsInRole("Admin");
}
}
ステップ 5 — Identity ページは静的 SSR のままにする
SignInManager と UserManager は内部で HttpContext を使用するため、インタラクティブコンポーネントでは例外が発生します。Identity ページ(ログイン、登録、管理)は静的 SSR でレンダリングする必要があります。
グローバルにインタラクティブなアプリでは、すべての Identity ページに次を指定します。
@page "/Account/Login"
@attribute [ExcludeFromInteractiveRouting]
これによりページ全体のナビゲーション(インタラクティブ回路からの離脱)が行われ、ページは実際の HttpContext を使って静的 SSR パイプライン経由でレンダリングされます。
App.razor では AcceptsInteractiveRouting()(ステップ 3)を使用して、これらのページに対して null を返す必要があります。そうしないと、フレームワークは引き続きページをインタラクティブにレンダリングしようとします。
ページ単位のアプリでは、Identity ページはデフォルトで静的です(@rendermode ディレクティブなし)。そのため、[ExcludeFromInteractiveRouting] は不要です。
ステップ 6 — WebAssembly/Auto モードでの認証状態
WebAssembly コンポーネントはブラウザーで実行され、HttpContext を持ちません。認証状態は、プリレンダリング中にサーバーからシリアル化し、クライアントでデシリアル化する必要があります。
サーバーの Program.cs:
builder.Services.AddAuthenticationStateSerialization();
クライアントの .Client/Program.cs:
builder.Services.AddAuthenticationStateDeserialization();
これらの呼び出しがない場合、WebAssembly がプリレンダリングを引き継いだ後、Task<AuthenticationState> は匿名ユーザーとして解決されます。
AddAuthenticationStateSerialization は、ロールとクレームのデータを含めるオプションを受け取ります。
builder.Services.AddAuthenticationStateSerialization(options =>
options.SerializeAllClaims = true);
レンダーモード × 認証のマトリックス
| レンダーモード | HttpContext.User | SignInManager | 認証状態の取得元 | 主な要件 |
|---|---|---|---|---|
| 静的 SSR | 使用可能 | 動作する | サーバーパイプライン | リダイレクトにはミドルウェアを使用します。<NotAuthorized> はレンダリングされません |
| サーバー(インタラクティブ) | 使用不可 | 例外が発生 | CascadingAuthenticationState | HttpContext ではなく、[Authorize] と AuthorizeView を使用します |
| WebAssembly | 使用不可 | 例外が発生 | サーバーからシリアル化 | AddAuthenticationStateSerialization / Deserialization |
| Auto | WASM 起動後は使用不可 | 例外が発生 | サーバーからシリアル化 | WebAssembly と同じです。両方の Program.cs ファイルに登録します |
よくある間違い
| 間違い | 症状 | 修正方法 |
|---|---|---|
インタラクティブコンポーネントで HttpContext.User を使用する | クレームが null または古い | [CascadingParameter] Task<AuthenticationState> を使用します |
インタラクティブコンポーネントで SignInManager を使用する | InvalidOperationException | [ExcludeFromInteractiveRouting] を指定した静的 SSR ページに移します |
AddAuthenticationStateSerialization がない | WASM の読み込み後に匿名ユーザーになる | サーバーの Program.cs に追加し、クライアントの Program.cs に Deserialization を追加します |
静的 SSR レイアウトで <NotAuthorized> を使用する | コンテンツが表示されない | 静的 SSR はミドルウェアパイプラインを使用します。LoginPath または RedirectToLogin コンポーネントでリダイレクトします |
AcceptsInteractiveRouting を指定せずにグローバルなインタラクティブ性を使用する | Identity ページでクラッシュする | App.razor に AcceptsInteractiveRouting() チェックを追加します(ステップ 3) |
AddCascadingAuthenticationState() がない | Task<AuthenticationState> が null になる | Program.cs に登録します(ステップ 2) |