次の方法で共有


IAuthorizationRequirementDataを使用したカスタム認可ポリシー

IAuthorizationRequirementData インターフェイスを使用して、属性定義で承認ポリシーに関連付けられている要件を指定します。

サンプル アプリ

この記事で説明する完全なサンプルは、 AuthRequirementsData サンプル アプリ (dotnet/AspNetCore.Docs.Samples GitHub リポジトリ) (ダウンロード方法) です。 このサンプル アプリでは、ユーザーの最小年齢ハンドラーが実装され、ユーザーは少なくとも 21 歳であることを示す生年月日要求を提示する必要があります。

最小年齢承認属性

MinimumAgeAuthorizeAttributeIAuthorizationRequirementData実装では、承認期間が設定されます。

using Microsoft.AspNetCore.Authorization;

namespace AuthRequirementsData.Authorization;

class MinimumAgeAuthorizeAttribute(int age) : AuthorizeAttribute, 
    IAuthorizationRequirement, IAuthorizationRequirementData
{
    public int Age { get; set; } = age;

    public IEnumerable<IAuthorizationRequirement> GetRequirements()
    {
        yield return this;
    }
}

最小年齢承認ハンドラー

MinimumAgeAuthorizationHandler クラスは、ジェネリック パラメーター IAuthorizationRequirementで指定された、MinimumAgeAuthorizeAttributeによって提供される単一のMinimumAgeAuthorizeAttributeを処理します。

HandleRequirementAsync メソッド:

  • ユーザーの生年月日の主張を取得します。
  • 要求からユーザーの年齢を取得します。
  • ユーザーが今年誕生日を過ごしていない場合は、年齢を調整します。
  • ユーザーが年齢要件を満たしている場合は、承認要件が成功したことをマークします。
  • デモンストレーション用のログ記録を実装します。
using System.Globalization;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

namespace AuthRequirementsData.Authorization;

class MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger) 
    : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
{
    // Check whether a given minimum age requirement is satisfied.
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, 
        MinimumAgeAuthorizeAttribute requirement)
    {
        logger.LogInformation(
            "Evaluating authorization requirement for age >= {age}", 
            requirement.Age);

        // Get the user's birth date claim.
        var dateOfBirthClaim = 
            context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth);

        if (dateOfBirthClaim != null)
        {
            // If the user has a date of birth claim, obtain their age.
            var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value, 
                CultureInfo.InvariantCulture);
            var age = DateTime.Now.Year - dateOfBirth.Year;

            // Adjust age if the user hasn't had a birthday yet this year.
            if (dateOfBirth > DateTime.Now.AddYears(-age))
            {
                age--;
            }

            // If the user meets the age requirement, mark the authorization
            // requirement succeeded.
            if (age >= requirement.Age)
            {
                logger.LogInformation(
                    "Minimum age authorization requirement {age} satisfied", 
                    requirement.Age);
                context.Succeed(requirement);
            }
            else
            {
                logger.LogInformation(
                    "Current user's DateOfBirth claim ({dateOfBirth}) doesn't " +
                    "satisfy the minimum age authorization requirement {age}",
                    dateOfBirthClaim.Value,
                    requirement.Age);
            }
        }
        else
        {
            logger.LogInformation("No DateOfBirth claim present");
        }

        return Task.CompletedTask;
    }
}

MinimumAgeAuthorizationHandlerは、アプリのIAuthorizationHandler ファイルにシングルトン Program サービスとして登録されます。

builder.Services.AddSingleton<IAuthorizationHandler,
    MinimumAgeAuthorizationHandler>();

GreetingsControllerは、ユーザーが最小年齢ポリシーを満たす場合に、[MinimumAgeAuthorize({AGE})]属性を持つ 21 歳の年齢を使用して、ユーザーの名前を表示します。ここで、{AGE}プレースホルダーは年齢です。

using Microsoft.AspNetCore.Mvc;
using AuthRequirementsData.Authorization;

namespace AuthRequirementsData.Controllers;

[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
    [MinimumAgeAuthorize(21)]
    [HttpGet("hello")]
    public string Hello() => 
        $"Hello {HttpContext.User.Identity?.Name}!";
}

ユーザーの生年月日要求が 21 歳以上であることを示す場合、コントローラーはあいさつ文字列を表示し、200 (OK) 状態コードを発行します。 ユーザーに生年月日の要求がない場合、または要求が 21 歳以上でないことを示している場合、あいさつは表示されず、403 (禁止) 状態コードが発行されます。

JWT ベアラー認証サービスは、アプリの Program ファイルに追加されます。

builder.Services.AddAuthentication().AddJwtBearer();

アプリ設定ファイル (appsettings.json) は、JWT ベアラー認証の対象ユーザーと発行者を構成します。

"Authentication": {
  "Schemes": {
    "Bearer": {
      "ValidAudiences": [
        "https://localhost:51100"
      ],
      "ValidIssuer": "dotnet-user-jwts"
    }
  }
}

前の例では、localhost 対象ユーザーは、アプリの起動プロファイル (applicationUrl) でProperties/launchSettings.jsonによって指定された localhost アドレスと一致します。

デモ

dotnet user-jwtsと curl を使用してサンプルをテストします。

コマンド シェル内のプロジェクトのフォルダーから、次のコマンドを実行して、21 歳以上のユーザーを作成する生年月日要求を含む JWT ベアラー トークンを作成します。

dotnet user-jwts create --claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth=1989-01-01

出力では、コマンド シェルの "Token:" の後にトークンが生成されます。

New JWT saved with ID '{JWT ID}'.
Name: {USER}
Custom Claims: [http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth=1989-01-01]

Token: {TOKEN}

後で使用するために、トークンの値 (前の出力に {TOKEN} プレースホルダーが表示される場所) を別に設定します。

jwt.msなどのオンライン JWT デコーダーでトークンをデコードしてコンテンツを表示し、ユーザーの生年月日を含むbirthdate要求が含まれていることを明らかにできます。

{
  "alg": "HS256",
  "typ": "JWT"
}.{
  "unique_name": "{USER}",
  "sub": "{USER}",
  "jti": "{JWT ID}",
  "birthdate": "1989-01-01",
  "aud": [
    "https://localhost:51100",
    "http://localhost:51101"
  ],
  "nbf": 1747315312,
  "exp": 1755264112,
  "iat": 1747315313,
  "iss": "dotnet-user-jwts"
}.[Signature]

21 歳未満のユーザーを作成する dateofbirth 値を指定して、コマンドをもう一度実行します。

dotnet user-jwts create --claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth=2020-01-01

2 番目のトークンの値を確保しておく。

Visual Studio で、または .NET CLI の dotnet watch コマンドを使用してアプリを起動します。

.NET CLI で、次の curl.exe コマンドを実行して、 api/greetings/hello エンドポイントを要求します。 {TOKEN} プレースホルダーを、前に保存した最初の JWT ベアラー トークンに置き換えます。

curl.exe -i -H "Authorization: Bearer {TOKEN}" https://localhost:51100/api/greetings/hello

ユーザーの生年月日要求が 21 歳以上であることを示しているため、出力は成功を示します。

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Thu, 15 May 2025 22:58:10 GMT
Server: Kestrel
Transfer-Encoding: chunked

Hello {USER}!

ログは、年齢要件が満たされたことを示します。

MinimumAgeAuthorizationHandler: Information: Evaluating authorization requirement for age >= 21
MinimumAgeAuthorizationHandler: Information: Minimum age authorization requirement 21 satisfied

ユーザーが 21 歳未満であることを示す 2 番目のトークンを使用して、 curl.exe コマンドを再実行します。 出力は、要件が満たされていないことを示します。 エンドポイントへのアクセスは禁止されています (状態コード 403):

HTTP/1.1 403 Forbidden
Content-Length: 0
Date: Thu, 15 May 2025 22:58:36 GMT
Server: Kestrel

MinimumAgeAuthorizationHandler: Information: Evaluating authorization requirement for age >= 21
MinimumAgeAuthorizationHandler: Information: Current user's DateOfBirth claim (2020-01-01) doesn't satisfy the minimum age authorization requirement 21