ASP.NET Core Resource-based authz記事更新まとめ|Blazor化と移行確認ポイント

ASP.NET Core documentation update: Resource-based authz article overhaulは、ASP.NET Coreの「リソースベース認可」を参照している開発者ほど早めに確認したい更新です。結論から言うと、フレームワークの認可API自体が変わったというより、公式ドキュメントの構成がBlazor/Razorコンポーネント中心に整理され、MVCとRazor Pages向けの記事が分離される流れです。PR #37097では、メイン記事の置き換え、新しいMVC/Razor Pages記事の追加、旧パスから新パスへのリダイレクト追加が示されています。(GitHub)

既存アプリでまず見るべきポイントは、古いresourcebasedへの社内リンク、サンプルコードの参照先、そして[Authorize]属性だけで「自分の文書だけ編集できる」といったオブジェクト単位の権限判定を済ませていないかの3つです。なお、指定ソースのPRは2026年5月5日にレビュー準備状態になった情報で、執筆時点ではOpenのため、Microsoft Learn上の最終公開内容は細部が変わる可能性があります。(GitHub)

目次

ASP.NET Core documentation updateとして見た今回の変更点

今回のResource-based authz article overhaulは、単なる文言修正ではなく、ASP.NET Coreのリソースベース認可ドキュメントを「利用シナリオ別に読みやすくする」ための再構成です。PRの概要では、旧来の汎用的なリソースベース認可記事をBlazor例中心の新しいresource-based.mdに置き換え、MVCとRazor Pagesの個別記事を追加し、TOCや関連リンクも更新すると説明されています。(GitHub)

確認項目変更内容実務での対応
メイン記事Blazor/Razorコンポーネントの例を中心にした内容へ再構成Blazor Web AppやRazorコンポーネントで認可を実装する場合は、新しいメイン記事を優先して参照する
MVC向け記事aspnetcore/mvc/security/authorization/resource-based.mdが追加Controller/Actionベースの実装はMVC記事に切り替えて確認する
Razor Pages向け記事aspnetcore/razor-pages/security/authorization/resource-based.mdが追加PageModelやPage Handlerでの認可はRazor Pages記事を参照する
URL/パス旧resourcebased.mdから新resource-basedへのリダイレクトが追加社内Wiki、設計書、研修資料、ブックマークは新パスへ更新する
サンプルコードBlazor向けサンプルとしてBlazorWebAppAuthorizationが示されるサンプルを本番ひな形として使わず、認可ロジックの考え方を確認する用途に限定する

特に重要なのは、メイン記事が「ASP.NET Core全般の説明」から「Blazor/Razorコンポーネントを中心にした説明」へ寄っている点です。PRの説明でも、MVCとRazor Pages版は大きく変えず、メイン記事のほうにBlazorサンプルと詳細な説明を追加する方針が示されています。(GitHub)

リソースベース認可とは何か

リソースベース認可は、ユーザーのロールやログイン状態だけでなく、「対象データそのもの」を見てアクセス可否を判断する認可方式です。たとえば、同じEditorロールのユーザーでも、Aさんが作成した文書はAさんだけが編集でき、Bさんは閲覧のみ、またはアクセス不可にする、といったケースが該当します。

ASP.NET Coreのドキュメントでは、リソースはC#クラスで表されることが多く、ファイル、クラウドストレージ、メモリ上のオブジェクト、データベースなどから読み込まれるデータと、その識別子、作成者、表示名などのメタデータを含むものとして説明されています。(GitHub)

通常の[Authorize]属性は、ページやActionに到達できるかどうかを判定するには便利です。しかし「このユーザーはこの特定の文書を編集できるか」を判断するには、まず文書データを読み込む必要があります。ASP.NET Coreでは属性による認可評価がデータバインディングやリソース読込より前に行われるため、リソースベース認可ではIAuthorizationService.AuthorizeAsyncを使った命令的な認可が必要になります。(GitHub)

[Authorize]で足りるケース、足りないケース

要件[Authorize]で足りるか推奨される実装
ログイン済みユーザーだけが管理画面に入れる足りる[Authorize]
Adminロールだけが設定画面に入れる足りる[Authorize(Roles = "Admin")]またはポリシー
自分が作成した文書だけ編集できる足りないリソースを読み込んでAuthorizeAsync(user, document, policy)
CRUD操作ごとに条件が違う足りないOperationAuthorizationRequirementを使った操作別認可
Blazor画面でボタンを非表示にするだけセキュリティとしては足りないUI制御に加え、処理側・API側でも認可

BlazorではAuthorizeViewで表示内容を切り替えられますが、これはUIの表示制御であり、イベントハンドラーやバックエンドAPIの保護そのものではありません。Microsoft LearnのBlazor認可ドキュメントでも、AuthorizeViewは要素の可視性を制御するが、イベントハンドラー自体のセキュリティは強制しないと説明されています。(Microsoft Learn)

既存アプリへの影響範囲

今回の更新は、基本的には「ドキュメントとサンプルの整理」です。そのため、既存のASP.NET Coreアプリが突然ビルドできなくなるような変更ではありません。ただし、ドキュメントを参照して実装や教育資料を作っているチームには影響があります。

影響が大きいチーム

対象影響確認すべきこと
Blazor Web Appを開発しているチームメイン記事の例がBlazor中心になるAuthenticationStateProvider、IAuthorizationService、バックエンドAPI側の認可をセットで確認する
MVCアプリを保守しているチームMVC向け記事が別記事になるController内でリソース読込後にAuthorizeAsyncしているか確認する
Razor Pagesアプリを保守しているチームRazor Pages向け記事が別記事になるPage Handlerでのリソース読込と認可順序を確認する
社内ドキュメントを持つチーム旧URLや古いサンプル参照が残りやすいresourcebasedからresource-basedへのリンク更新を行う
セキュリティレビュー担当オブジェクト単位の認可漏れを見つけやすくなる[Authorize]だけで所有者判定を済ませていないか確認する

PRでは、旧resourcebased.mdが削除され、新しいresource-based.mdが追加され、さらに.openpublishing.redirection.jsonで旧パスから新パスへのリダイレクトが追加されています。リダイレクトがあるため短期的にはリンク切れを避けられますが、社内資料では新しい正規パスへ更新しておくほうが安全です。(GitHub)

移行・設定確認のチェックリスト

今回の更新を受けて、既存コードを大きく書き換える必要はありません。ただし、リソースベース認可はセキュリティ不備が起きやすい領域です。以下の順に確認すると、ドキュメント更新に合わせて実装品質も見直せます。

確認項目見る場所判断基準
旧リンクの利用README、社内Wiki、研修資料、設計書resourcebasedではなくresource-basedを参照している
フレームワーク別の記事選択チームの実装方式Blazor、MVC、Razor Pagesで参照記事を分けている
リソース読込の順序Controller、PageModel、Razorコンポーネント対象データを読み込んでからAuthorizeAsyncしている
ポリシー名Program.cs、認可呼び出し箇所登録名と呼び出し名が一致している
Handler登録DI設定IAuthorizationHandlerがサービス登録されている
DBアクセスを使うHandlerHandlerのコンストラクターEF Coreなどスコープ付きサービスを使うHandlerをSingleton登録していない
失敗時の応答Controller、Page Handler、API未認証はChallenge、認証済みだが権限なしはForbidを返す設計になっている
UIだけの制御BlazorコンポーネントAuthorizeViewだけで保護したつもりになっていない

認可HandlerはDIコンテナーへ登録する必要があります。また、Microsoft Learnでは、EFを使う認可HandlerをSingletonとして登録しないよう注意されています。ドキュメント例をそのまま写す場合でも、Handler内部でDbContextやRepositoryを使うならサービス寿命を必ず確認してください。(Microsoft Learn)

実装で押さえるべき基本パターン

リソースベース認可の基本は、次の流れです。

手順内容
リソースを取得するdocumentIdなどから対象データを読み込む
ユーザー情報を取得するMVC/Razor PagesではUser、Blazorでは認証状態からClaimsPrincipalを取得する
AuthorizeAsyncを呼ぶユーザー、リソース、ポリシーまたは要件を渡す
結果に応じて処理する成功なら処理続行、失敗ならForbid/Challenge/NotFoundなどを返す

たとえば、文書の所有者だけが編集できる設計なら、考え方は次のようになります。

using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

public sealed class DocumentOwnerRequirement : IAuthorizationRequirement
{
}

public sealed class DocumentOwnerHandler
    : AuthorizationHandler<DocumentOwnerRequirement, Document>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        DocumentOwnerRequirement requirement,
        Document document)
    {
        var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);

        if (userId is not null && userId == document.OwnerUserId)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

Program.csでは、ポリシーとHandlerを登録します。Handlerが外部リソースに依存しない単純な判定ならSingletonでも扱いやすいですが、DbContextなどを使う場合はScoped登録を検討します。

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("DocumentOwnerPolicy", policy =>
        policy.Requirements.Add(new DocumentOwnerRequirement()));

builder.Services.AddScoped<IAuthorizationHandler, DocumentOwnerHandler>();

Blazorコンポーネントで使う場合は、画面表示の前後でユーザー状態と文書を取得し、IAuthorizationServiceで判定します。

var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var user = authState.User;

var document = await DocumentRepository.FindAsync(documentId);

var result = await AuthorizationService.AuthorizeAsync(
    user,
    document,
    "DocumentOwnerPolicy");

if (!result.Succeeded)
{
    message = "この文書を操作する権限がありません。";
    return;
}

ここで大切なのは、ボタンを非表示にするだけで終わらせないことです。ユーザーが直接URLやAPIを叩くケース、イベントハンドラーが別経路で呼ばれるケース、SPAやBlazor WebAssemblyでクライアント側コードが見えるケースを考えると、最終的な保護はサーバー側の処理またはAPI側で行う必要があります。

Blazor、MVC、Razor Pagesで読み替えるポイント

Blazorでは「画面制御」と「実処理の認可」を分ける

今回のメイン記事はBlazor/Razorコンポーネントの例に寄っています。Blazorでは、コンポーネント上で現在のユーザーを取得し、対象リソースを読み込んでAuthorizeAsyncする流れを理解することが重要です。PRで示された新しいメイン記事には、BlazorWebAppAuthorizationサンプルがあり、事前に用意されたユーザーと文書オブジェクトで認可の動きを確認できると説明されています。(GitHub)

ただし、そのサンプルはインメモリデータベースを使うデモ用途で、本番環境のひな形としては適していないと明記されています。実務では、永続化、監査ログ、例外処理、IDプロバイダーとの連携を別途設計する必要があります。(GitHub)

MVCではAction内でリソースを読み込んでから判定する

MVCでは、Controller Actionに入ったあとでdocumentIdなどを使って対象データを取得し、そのデータをAuthorizeAsyncに渡します。PRで追加されたMVC向け記事でも、属性評価はActionがリソースを読み込む前に行われるため、[Authorize]だけではリソースベース認可に不十分で、命令的な認可が必要だと説明されています。(GitHub)

失敗時は、未認証ユーザーにはChallengeResult、認証済みだが権限がないユーザーにはForbidResultを返す、という整理が基本です。PR内のMVC/Razor Pages記事でも、認可失敗時のChallengeとForbidの使い分けが説明されています。(GitHub)

Razor PagesではPage Handler単位で同じ考え方を使う

Razor Pagesでも考え方は同じです。OnGetAsyncやOnPostAsyncなどのPage Handlerで対象リソースを取得し、その後にAuthorizeAsyncします。PRで追加されたRazor Pages向け記事でも、属性評価はPage Handlerがリソースを読み込む前に行われるため、宣言的な[Authorize]だけでは不十分だとされています。(GitHub)

MVCとRazor Pagesの違いは、Controller ActionかPage Handlerかという実装場所の違いです。所有者判定、CRUD操作別判定、Challenge/Forbidの判断基準はほぼ同じ考え方で整理できます。

コード例を読むときの注意点

今回のドキュメントでは、C# 12のプライマリコンストラクターを使う例が示されています。PR内のMVC/Razor Pages記事では、C# 12は.NET 8以降で利用でき、.NET 8より前を対象にするサンプルでは従来のコンストラクター注入を使うと説明されています。(GitHub)

そのため、既存プロジェクトが.NET 6や.NET 7の場合、コード例をそのまま貼り付けるのではなく、次のように読み替えてください。

ドキュメント例で見る表現既存プロジェクトでの確認
プライマリコンストラクター従来のコンストラクター注入に置き換える
AddAuthorizationBuilder()既存の認可設定方式と競合しないか確認する
Blazor向けサンプルMVC/Razor Pagesには個別記事のコードを参照する
サンプルのユーザー・ロール自社のIDプロバイダー、Claim、Role設計に合わせる
インメモリDB本番では永続DB、監査、例外処理を別途設計する

ドキュメント更新時にありがちな失敗は、「新しいサンプルがあるから古い実装は間違い」と受け取ることです。今回の更新は主に記事構成とサンプルの分かりやすさを改善するものなので、既存実装が正しくリソースベース認可を行っているなら、無理に全面移行する必要はありません。

セキュリティレビューで見るべき失敗パターン

リソースベース認可は、見た目には動いていても権限漏れが残りやすい領域です。レビューでは次の点を重点的に確認してください。

失敗パターン何が危険か修正方針
一覧画面だけで自分のデータに絞っているURL直打ちで他人の詳細IDを指定される可能性がある詳細・編集・削除の各処理でもリソースベース認可を行う
[Authorize]だけで所有者判定をしていないログイン済みなら他人のデータにアクセスできる可能性があるリソース取得後にAuthorizeAsyncを呼ぶ
AuthorizeViewだけでボタンを隠しているAPIやイベント処理が直接呼ばれる可能性があるサーバー側処理にも認可を入れる
Handler内でUser.Identity.Nameだけに依存表示名変更や外部ID連携で不安定になる場合があるNameIdentifierなど安定したClaimを使う
404と403の使い分けが雑リソースの存在有無を推測される可能性がある業務要件に応じてNotFound扱いも検討する
HandlerがDBに依存するのにSingleton登録DIライフタイム不整合や実行時エラーの原因になるScoped登録または依存関係の分離を行う

特に「一覧で絞っているから安全」という思い込みは危険です。攻撃者や不正利用者は画面の導線どおりに操作するとは限りません。詳細、編集、削除、ダウンロード、APIエンドポイントなど、リソースIDを受け取るすべての入口で確認する必要があります。

今回の更新を受けて次にやること

ASP.NET Core documentation update: Resource-based authz article overhaulを受けて、まずはリンクと参照記事を整理しましょう。Blazorなら新しいメイン記事、MVCならMVC向け記事、Razor PagesならRazor Pages向け記事を参照する流れに変えるのが第一歩です。

次に、既存コードで[Authorize]だけに依存している箇所を洗い出します。「ユーザー単位」「所有者単位」「部署単位」「契約単位」「操作種別単位」で権限が変わる処理は、リソースベース認可の対象候補です。該当する処理では、対象データを読み込んだあとにIAuthorizationService.AuthorizeAsyncで判定しているか確認してください。

最後に、BlazorではUI制御と実際の保護を分けて考えることが重要です。画面上のボタンを隠すだけではなく、イベントハンドラー、サーバー処理、Web API側にも認可を入れる。この基本を守るだけで、今回のドキュメント更新を単なるニュースではなく、実装品質を上げる機会として活用できます。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次