Minimal API での認証と認可

Minimal API では、ASP.NET Core で使用できるすべての認証と認可のオプションがサポートされ、認証を扱うエクスペリエンスを強化するための追加機能もいくつか用意されています。

認証と認可における重要な概念

認証は、ユーザーの ID を突き止めるプロセスです。 認可は、ユーザーがリソースにアクセスできるかどうかを判断するプロセスです。 ASP.NET Core では、認証と認可の両方のシナリオで、類似した実装のセマンティクスが共有されます。 認証は、認証サービス IAuthenticationService によって処理されます。これは、認証ミドルウェアによって使用されます。 認可は、認可サービス IAuthorizationService によって処理されます。これは、認可ミドルウェアによって使用されます。

認証サービスは、登録済みの認証ハンドラーを使用して、認証関連のアクションを完了します。 認証関連のアクションの例としては、ユーザーの認証やユーザーのサインアウトがあります。 認証スキームとは、認証ハンドラーとその構成オプションを一意に識別するために使用される名前のことです。 認証ハンドラーは、OAuth や OIDC といった特定の認証方式を指定したうえで、認証方式を実装し、ユーザーのクレームを生成する役割を担います。 構成オプションもその方式に固有であり、リダイレクト URI などの認証動作に影響を与える構成がハンドラーに提供されます。

認可レイヤーでは、リソースへのユーザー アクセスを判断するための方式が 2 つあります。

  • ロールベースの方式では、ユーザーに割り当てられているロール (AdministratorUser など) に基づいてユーザーのアクセスを判断します。 ロールベースの認可について詳しくは、ロールベースの認可に関するドキュメントを参照してください。
  • クレームベースの方式では、中央機関によって発行されたクレームに基づいてユーザーのアクセスを判断します。 クレームベースの認可について詳しくは、クレームベースの認可に関するドキュメントを参照してください。

ASP.NET Core では、両方の方式が認可要件に取り込まれています。 認可サービスでは、認可ハンドラーを利用して、特定のユーザーがリソースに適用される認可要件を満たしているかどうかを判断します。

最小限のアプリにおける認証の有効化

認証を有効にするには、AddAuthentication を呼び出して、アプリのサービス プロバイダーに必要な認証サービスを登録します。

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

通常は、特定の認証方法が使用されます。 次のサンプルでは、JWT ベアラーベースの認証をサポートするようにアプリが構成されています。 この例では、Microsoft.AspNetCore.Authentication.JwtBearer NuGet パッケージで使用できる API を使用します。

var builder = WebApplication.CreateBuilder(args);
// Requires Microsoft.AspNetCore.Authentication.JwtBearer
builder.Services.AddAuthentication().AddJwtBearer();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

既定では、WebApplication では、特定の認証サービスや認可サービスが有効である場合、認証ミドルウェアや認可ミドルウェアが自動的に登録されます。 次のサンプルでは、UseAuthentication または UseAuthorization を呼び出してミドルウェアを登録する必要はありません。AddAuthentication または AddAuthorization が呼び出された後に、WebApplication によって自動的に登録されるためです。

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

ミドルウェアの順序を管理するケースなど、場合によっては、認証と認可を明示的に登録する必要があります。 次のサンプルでは、CORS ミドルウェアが実行された "後に" 認証ミドルウェアが実行されます。 ミドルウェアとこのような自動動作について詳しくは、「Minimal API アプリのミドルウェア」を参照してください。

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

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

app.MapGet("/", () => "Hello World!");
app.Run();

認証方式の構成

通常、各認証方式ではさまざまな構成がサポートされており、オプションを使って読み込むことができます。 最小限のアプリでは、次の認証戦略の構成からの読み込みオプションがサポートされています。

ASP.NET Core フレームワークでは、構成Authentication:Schemes:{SchemeName} セクションでこれらのオプションを指定することが想定されています。 次のサンプルでは、2 つの異なるスキーム BearerLocalAuthIssuer が、それぞれのオプションと共に定義されています。 Authentication:DefaultScheme オプションを使って、使用される既定の認証方式を構成できます。

{
  "Authentication": {
    "DefaultScheme":  "LocalAuthIssuer",
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "https://localhost:7259",
          "http://localhost:5259"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      },
      "LocalAuthIssuer": {
        "ValidAudiences": [
          "https://localhost:7259",
          "http://localhost:5259"
        ],
        "ValidIssuer": "local-auth"
      }
    }
  }
}

Program.cs では、次の 2 つの JWT ベアラーベースの認証戦略が登録されます。

  • "Bearer" スキーム名。
  • "LocalAuthIssuer" スキーム名。

"Bearer" は JWT ベアラーベースが有効なアプリの一般的な既定のスキームですが、上記の例のように、DefaultScheme プロパティを設定することで既定のスキームをオーバーライドできます。

スキーム名は、認証方式を一意に識別するために使用され、次の例に示すように、構成から認証オプションを解決するときに参照キーとして使用されます。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication()
  .AddJwtBearer()
  .AddJwtBearer("LocalAuthIssuer");
  
var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.Run();

最小限のアプリにおける認可ポリシーの構成

認証は、API に対してユーザーの ID を識別して検証するために使用されます。 認可は、API でリソースへのアクセスを検証および確認するために使用され、AddAuthorization 拡張メソッドによって登録された IAuthorizationService によって容易になります。 次のシナリオでは、ユーザーが greetings_api スコープ クレームを使って admin ロール クレームを提示する必要がある、/hello リソースが追加されます。

リソースに対する認可要件の構成は、次が必要になる 2 段階のプロセスです。

  1. ポリシーで認可要件をグローバルに構成する。
  2. 個々のポリシーをリソースに適用する。

以下のコードでは、次のことを行う AddAuthorizationBuilder が呼び出されます。

  • 認可関連のサービスを DI コンテナーに追加します。
  • 認可ポリシーを直接登録するために使用できる AuthorizationBuilder を返します。

このコードでは、2 つの認可要件をカプセル化する、admin_greetings という名前の新しい認可ポリシーを作成します。

  • admin ロールを持つユーザーに対する、RequireRole を介したロールベースの要件。
  • ユーザーが greetings_api スコープ クレームを提供する必要がある、RequireClaim を介したクレームベースの要件。

admin_greetings ポリシーは、/hello エンドポイントに必要なポリシーとして指定されます。

using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorizationBuilder()
  .AddPolicy("admin_greetings", policy =>
        policy
            .RequireRole("admin")
            .RequireClaim("scope", "greetings_api"));

var app = builder.Build();

app.MapGet("/hello", () => "Hello world!")
  .RequireAuthorization("admin_greetings");

app.Run();

開発テストに dotnet user-jwts を使用する

この記事全体を通して、JWT ベアラーベースの認証で構成されたアプリが使用されています。 JWT ベアラーベースの認証では、クライアントは要求ヘッダーでトークンを提示し、自分の ID とクレームを検証する必要があります。 通常、これらのトークンは、ID サーバーなどの中央機関によって発行されます。

ローカル コンピューター上で開発している場合は、dotnet user-jwts ツールを使ってベアラー トークンを作成できます。

dotnet user-jwts create

注意

プロジェクトで呼び出されると、ツールによって、生成されたトークンに一致する認証オプションが appsettings.json に自動的に追加されます。

トークンは、さまざまなカスタマイズによって構成できます。 たとえば、前のコードの認可ポリシーで想定される、admin ロールと greetings_api スコープ用のトークンを作成する場合:

dotnet user-jwts create --scope "greetings_api" --role "admin"

その後、生成されたトークンを、任意のテスト ツールでヘッダーの一部として送信できます。 たとえば、curl を使う場合:

curl -i -H "Authorization: Bearer {token}" https://localhost:{port}/hello

dotnet user-jwts ツールについて詳しくは、完全なドキュメントを参照してください。