ASP.NET Core でのクレーム ベースの承認

ID が作成されるときには、信頼された相手によって発行された 1 つ以上のクレームが、ID に割り当てられる場合があります。 クレームは、サブジェクトが何であるかを表す名前と値のペアであり、サブジェクトで何が実行できるかではありません。 たとえば、あなたは地元の運転免許証機関によって発行された運転免許証を持っているかも知れません。 運転免許証にはあなたの生年月日が記載されています。 この場合、クレーム名は DateOfBirth になり、クレームの値は、たとえば 8th June 1970 となります。そして発行者は、運転免許証機関になります。 クレーム ベースの承認では、簡単に言うと、クレームの値がチェックされ、その値に基づいてリソースへのアクセスが許可されます。 たとえば、ナイト クラブへの入場 (アクセス) であれば、承認プロセスは次のようになる可能性があります。

出入口のセキュリティ責任者が、あなたの生年月日クレームの値と、発行者 (運転免許機関) を信頼するかどうかを評価します。

1 つの ID には、複数の値があるクレームが複数含まれる場合があり、同じ種類のクレームが複数含まれる場合があります。

クレーム チェックの追加

クレーム ベースの承認チェック:

  • 宣言型です。
  • コントローラー内の Razor Pages、コントローラー、またはアクションに適用されます。
  • Razor Page ハンドラー レベルで適用することは "できません"。Page に適用する必要があります。

コード内のクレームによって、現在のユーザーが所有する必要があるクレーム、および、必要に応じて、要求されたリソースにアクセスするためにクレームが保持する必要がある値が指定されます。 クレーム要件はポリシー ベースであり、開発者は、クレーム要件を表すポリシーを作成して登録する必要があります。

最も単純な種類のクレーム ポリシーでは、クレームが存在することは調べられますが、値はチェックされません。

ポリシーを作成および登録し、UseAuthorization を呼び出します。 ポリシーの登録は、通常は Program.cs ファイル内で、承認サービスの構成の一部として行います。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddAuthorization(options =>
{
   options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();
app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

この場合は、EmployeeOnly ポリシーにより、現在の ID に EmployeeNumber クレームが存在するかがチェックされます。

次に、[Authorize] 属性の Policy プロパティを使用してポリシーを適用し、ポリシー名を指定します。

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

[Authorize] 属性はコントローラー全体、または Razor Page に適用できます。その場合、ポリシーに一致する ID のみに、コントローラー上の任意のアクションへのアクセスが許可されます。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public ActionResult VacationBalance()
    {
        return View();
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
        return View();
    }
}

次のコードによって、[Authorize] 属性が Razor Page に適用されます。

[Authorize(Policy = "EmployeeOnly")]
public class IndexModel : PageModel
{
    public void OnGet()
    {

    }
}

Razor Page ハンドラー レベルでポリシーを適用することは "できません"。Page に適用する必要があります。

[Authorize] 属性によって保護されているコントローラーがあっても、特定のアクションへの匿名アクセスを許可する場合は、AllowAnonymousAttribute 属性を適用します。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public ActionResult VacationBalance()
    {
        return View();
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
        return View();
    }
}

Razor Page ハンドラー レベルでポリシーを適用することは "できない" ため、ポリシーをページ ハンドラー レベルで適用する必要がある場合には、コントローラーを使用することをお勧めします。 Razor Page ハンドラー レベルでポリシーを必要としないアプリの残りの部分では、Razor Pages を使用できます。

ほとんどのクレームには値が指定されています。 ポリシーの作成時に、許可される値の一覧を指定できます。 次の例では、成功になるのは従業員番号が 1、2、3、4、5 の従業員に対してのみです。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("Founders", policy =>
                      policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();
app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

汎用のクレーム チェックを追加する

要求値が単一の値ではない場合や変換が必要な場合は、RequireAssertion を使用します。 詳細については、「func を使用してポリシーを満たす」を参照してください。

複数のポリシーの評価

コントローラー レベルとアクション レベルで複数のポリシーが適用される場合、アクセスが許可されるにはすべてのポリシーを満たしている必要があります。

[Authorize(Policy = "EmployeeOnly")]
public class SalaryController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    public IActionResult Payslip()
    {
        return View();
    }

    [Authorize(Policy = "HumanResources")]
    public IActionResult UpdateSalary()
    {
        return View();
    }
}

上の例では、EmployeeOnly ポリシーを満たすどの ID でも Payslip アクションにアクセスできます。そのポリシーは、コントローラーに対して適用されるためです。 ただし、UpdateSalary アクションを呼び出すには、ID が EmployeeOnly ポリシーと HumanResources ポリシーの "両方" を満たしている必要があります。

生年月日クレームを取得し、それから年齢を計算した後で、年齢が 21 歳以上であるかをチェックするといった、より複雑なポリシーが必要な場合は、カスタム ポリシー ハンドラーを記述する必要があります。

次のサンプルでは、両方のページ ハンドラー メソッドが、EmployeeOnly ポリシーと HumanResources ポリシーの "両方" を満たす必要があります。

[Authorize(Policy = "EmployeeOnly")]
[Authorize(Policy = "HumanResources")]
public class SalaryModel : PageModel
{
    public ContentResult OnGetPayStub()
    {
        return Content("OnGetPayStub");
    }

    public ContentResult OnGetSalary()
    {
        return Content("OnGetSalary");
    }
}

ID が作成されるときには、信頼された相手によって発行された 1 つ以上のクレームが、ID に割り当てられる場合があります。 クレームは、サブジェクトが何であるかを表す名前と値のペアであり、サブジェクトで何が実行できるかではありません。 たとえば、あなたは地元の運転免許証機関によって発行された運転免許証を持っているかも知れません。 運転免許証にはあなたの生年月日が記載されています。 この場合、クレーム名は DateOfBirth になり、クレームの値は、たとえば 8th June 1970 となります。そして発行者は、運転免許証機関になります。 クレーム ベースの承認では、簡単に言うと、クレームの値がチェックされ、その値に基づいてリソースへのアクセスが許可されます。 たとえば、ナイト クラブへの入場 (アクセス) であれば、承認プロセスは次のようになる可能性があります。

出入口のセキュリティ責任者が、あなたの生年月日クレームの値と、発行者 (運転免許機関) を信頼するかどうかを評価します。

1 つの ID には、複数の値があるクレームが複数含まれる場合があり、同じ種類のクレームが複数含まれる場合があります。

クレーム チェックの追加

クレーム ベースの承認チェックは宣言型です。開発者は、コントローラーまたはコントローラー内のアクションに対するチェックをコード内に埋め込み、現在のユーザーが所有している必要があるクレームを指定します。そしてオプションで、要求されたリソースにアクセスするためにクレームが保持している必要がある値を指定します。 クレーム要件はポリシー ベースであり、開発者は、クレーム要件を表すポリシーを作成して登録する必要があります。

最も単純な種類のクレーム ポリシーでは、クレームが存在することは調べられますが、値はチェックされません。

ポリシーを作成して登録します。 これは、通常は ConfigureServices() ファイルの Startup.cs に含まれる、承認サービス構成の一部として行われます。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

Configure 内で UseAuthorization を呼び出します。 ASP.NET Core の Web アプリ テンプレートによって、次のコードが生成されます。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

この場合は、EmployeeOnly ポリシーにより、現在の ID に EmployeeNumber クレームが存在するかがチェックされます。

次に、[Authorize] 属性の Policy プロパティを使用してポリシーを適用し、ポリシー名を指定します。

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

[Authorize] 属性はコントローラー全体に適用できます。このインスタンスでは、ポリシーに一致する ID のみに、コントローラー上の任意のアクションへのアクセスが許可されます。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }
}

[Authorize] 属性によって保護されているコントローラーがあっても、特定のアクションへの匿名アクセスを許可する場合は、AllowAnonymousAttribute 属性を適用します。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
    }
}

ほとんどのクレームには値が指定されています。 ポリシーの作成時に、許可される値の一覧を指定できます。 次の例では、成功になるのは従業員番号が 1、2、3、4、5 の従業員に対してのみです。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Founders", policy =>
                          policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
    });
}

汎用のクレーム チェックを追加する

要求値が単一の値ではない場合や変換が必要な場合は、RequireAssertion を使用します。 詳細については、「func を使用してポリシーを満たす」を参照してください。

複数のポリシーの評価

コントローラーまたはアクションに対して複数のポリシーを適用する場合は、すべてのポリシーが合格してからアクセスが許可されます。 次に例を示します。

[Authorize(Policy = "EmployeeOnly")]
public class SalaryController : Controller
{
    public ActionResult Payslip()
    {
    }

    [Authorize(Policy = "HumanResources")]
    public ActionResult UpdateSalary()
    {
    }
}

上の例では、EmployeeOnly ポリシーを満たすどの ID でも Payslip アクションにアクセスできます。そのポリシーは、コントローラーに対して適用されるためです。 ただし、UpdateSalary アクションを呼び出すには、ID が EmployeeOnly ポリシーと HumanResources ポリシーの "両方" を満たしている必要があります。

生年月日クレームを取得し、それから年齢を計算した後で、年齢が 21 歳以上であるかをチェックするといった、より複雑なポリシーが必要な場合は、カスタム ポリシー ハンドラーを記述する必要があります。

ID が作成されるときには、信頼された相手によって発行された 1 つ以上のクレームが、ID に割り当てられる場合があります。 クレームは、サブジェクトが何であるかを表す名前と値のペアであり、サブジェクトで何が実行できるかではありません。 たとえば、あなたは地元の運転免許証機関によって発行された運転免許証を持っているかも知れません。 運転免許証にはあなたの生年月日が記載されています。 この場合、クレーム名は DateOfBirth になり、クレームの値は、たとえば 8th June 1970 となります。そして発行者は、運転免許証機関になります。 クレーム ベースの承認では、簡単に言うと、クレームの値がチェックされ、その値に基づいてリソースへのアクセスが許可されます。 たとえば、ナイト クラブへの入場 (アクセス) であれば、承認プロセスは次のようになる可能性があります。

出入口のセキュリティ責任者が、あなたの生年月日クレームの値と、発行者 (運転免許機関) を信頼するかどうかを評価します。

1 つの ID には、複数の値があるクレームが複数含まれる場合があり、同じ種類のクレームが複数含まれる場合があります。

クレーム チェックの追加

クレーム ベースの承認チェックは宣言型です。開発者は、コントローラーまたはコントローラー内のアクションに対するチェックをコード内に埋め込み、現在のユーザーが所有している必要があるクレームを指定します。そしてオプションで、要求されたリソースにアクセスするためにクレームが保持している必要がある値を指定します。 クレーム要件はポリシー ベースであり、開発者は、クレーム要件を表すポリシーを作成して登録する必要があります。

最も単純な種類のクレーム ポリシーでは、クレームが存在することは調べられますが、値はチェックされません。

ポリシーを作成して登録します。 これは、通常は ConfigureServices() ファイルの Startup.cs に含まれる、承認サービス構成の一部として行われます。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

この場合は、EmployeeOnly ポリシーにより、現在の ID に EmployeeNumber クレームが存在するかがチェックされます。

次に、[Authorize] 属性の Policy プロパティを使用してポリシーを適用し、ポリシー名を指定します。

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

[Authorize] 属性はコントローラー全体に適用できます。このインスタンスでは、ポリシーに一致する ID のみに、コントローラー上の任意のアクションへのアクセスが許可されます。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }
}

[Authorize] 属性によって保護されているコントローラーがあっても、特定のアクションへの匿名アクセスを許可する場合は、AllowAnonymousAttribute 属性を適用します。

[Authorize(Policy = "EmployeeOnly")]
public class VacationController : Controller
{
    public ActionResult VacationBalance()
    {
    }

    [AllowAnonymous]
    public ActionResult VacationPolicy()
    {
    }
}

ほとんどのクレームには値が指定されています。 ポリシーの作成時に、許可される値の一覧を指定できます。 次の例では、成功になるのは従業員番号が 1、2、3、4、5 の従業員に対してのみです。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("Founders", policy =>
                          policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
    });
}

汎用のクレーム チェックを追加する

要求値が単一の値ではない場合や変換が必要な場合は、RequireAssertion を使用します。 詳細については、「func を使用してポリシーを満たす」を参照してください。

複数のポリシーの評価

コントローラーまたはアクションに対して複数のポリシーを適用する場合は、すべてのポリシーが合格してからアクセスが許可されます。 次に例を示します。

[Authorize(Policy = "EmployeeOnly")]
public class SalaryController : Controller
{
    public ActionResult Payslip()
    {
    }

    [Authorize(Policy = "HumanResources")]
    public ActionResult UpdateSalary()
    {
    }
}

上の例では、EmployeeOnly ポリシーを満たすどの ID でも Payslip アクションにアクセスできます。そのポリシーは、コントローラーに対して適用されるためです。 ただし、UpdateSalary アクションを呼び出すには、ID が EmployeeOnly ポリシーと HumanResources ポリシーの "両方" を満たしている必要があります。

生年月日クレームを取得し、それから年齢を計算した後で、年齢が 21 歳以上であるかをチェックするといった、より複雑なポリシーが必要な場合は、カスタム ポリシー ハンドラーを記述する必要があります。