dotnet user-jwts を使用した開発での JSON Web トークンの管理

作成者: Rick Anderson

dotnet user-jwts コマンドライン ツールは、アプリ固有のローカル JSON Web トークン (JWT) の作成および管理を行えます。

この記事では、コマンドと例の構文の詳細について説明します。

概要

dotnet user-jwts [<PROJECT>] [command]
dotnet user-jwts [command] -h|--help

説明

プロジェクト固有のローカル JSON Web トークンを作成および管理します。

引数

PROJECT | SOLUTION

コマンドの適用対象の MSBuild プロジェクトです。 プロジェクトが指定されていない場合、MSBuild は現在の作業ディレクトリで、ファイル拡張子が proj で終わるファイルを検索します。 その後、そのファイルを使用してコマンドのプロジェクト情報を取得します。

コマンド

コマンド 説明
clear プロジェクトに対して発行されたすべての JWT を削除します。
create 新しい JSON Web トークンを発行します。
remove 特定の JWT を削除します。
key JWT の発行に使用される署名キーを表示またはリセットします。
list プロジェクトに対して発行された JWT を一覧表示します。
print 特定の JWT の詳細を表示します。

create コマンドのオプション

使用法: dotnet user-jwts create [options]

オプション 説明
-p \| --project 操作対象のプロジェクトのパスです。 デフォルトでは、カレントディレクトリ内のプロジェクトが使用されます。
--scheme 生成されたトークンに対して使用するスキーム名です。 既定値は Bearer です。
-n \| --name JWT を作成するユーザーの名前です。 既定では現在の環境ユーザーを使用します。
--audience JWT を作成する対象ユーザーです。 既定では、プロジェクトの launchSettings.json ファイルで構成された URL が使用されます。
--issuer JWT の発行者です。 既定値は dotnet-user-jwts です。
--scope JWT に追加するスコープ要求です。 各スコープに対して 1 回指定します。
--role JWT に追加するロール クレームです。 ロールごとに 1 回のみ指定します。
--claim JWT に追加する要求です。 name=value形式で要求ごとに 1 回指定します。
--not-before JWT が有効になる UTC 日時 ( yyyy-MM-dd [[HH:mm[[:ss]]]]形式)。 JWT が作成される日時が既定値になります。
--expires-on JWT の有効期限が切れる UTC 日時 ( yyyy-MM-dd [[[ [HH:mm]]:ss]]形式)。 既定値は --not-before の日付から 6 か月後です。 このオプションは、--valid-for オプションと共に使わないでください。
--valid-for JWT の有効期間。 時間に達すると、JWT は期限切れになります。 数値の後に期間の種類 (d 日、 h 時間、 m 分、 s 秒) を指定します (例: 365d)。 このオプションは、--expires-on オプションと共に使わないでください。
-o \| --output コマンドからの出力を表示するために使用する形式: defaulttoken、または json
-h \| --help コマンドのヘルプ情報を表示します。

例示

次のコマンドを実行して空の Web プロジェクトを作成し、Microsoft.AspNetCore.Authentication.JwtBearer NuGet パッケージを追加します。

dotnet new web -o MyJWT
cd MyJWT
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

Program.cs ファイルの内容を次のコードに置き換えます。

using System.Security.Claims;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();
builder.Services.AddAuthentication("Bearer").AddJwtBearer();

var app = builder.Build();

app.UseAuthorization();

app.MapGet("/", () => "Hello, World!");
app.MapGet("/secret", (ClaimsPrincipal user) => $"Hello {user.Identity?.Name}. My secret")
    .RequireAuthorization();

app.Run();

上記のコードでは、 /secret エンドポイントに対する GET 要求によって 401 Unauthorized エラーが返されます。 運用アプリは、資格情報を使用したサインインに応答して、 セキュリティ トークン サービスから JWT を取得する場合があります。 ローカル開発時に API を使用する場合は、 dotnet user-jwts コマンド ライン ツールを使用して、アプリ固有のローカル JWT を作成および管理できます。

user-jwts ツールの概念は、ユーザー シークレット ツールと似ています。 これは、ローカル コンピューター上の開発者に対してのみ有効なアプリの値を管理するために使用できます。 実際、 user-jwts ツールは、 user-secrets インフラストラクチャを利用して、JWT が署名されているキーを管理します。 この方法により、キーがユーザー プロファイルに安全に格納されます。

user-jwts ツールは、値が格納される場所や方法などの実装の詳細を隠します。 このツールは、実装の詳細を知らなくても使用できます。

値は、ローカル コンピューターのユーザー プロファイル フォルダー内の JSON ファイルに格納されます。

  • Windows: %APPDATA%\Microsoft\UserSecrets<secrets_GUID>\user-jwts.json

  • Linux/macOS: ~/.microsoft/usersecrets/<secrets_GUID>/user-jwts.json

JWT を作成する

次のコマンドはローカル JWT を作成します。

dotnet user-jwts create

上記のコマンドは、JWT を作成し、次の例のような JSON を使用してプロジェクト appsettings.Development.json ファイルを更新します。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Authentication": {
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "http://localhost:8401",
          "https://localhost:44308",
          "http://localhost:5182",
          "https://localhost:7076"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      }
    }
  }
}

前述のコマンドで作成された JWT と ID をコピーします。 Curl などのツールを使用して、 /secret エンドポイントをテストします。ここで、 {token} は以前に生成された JWT です。

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

JWT セキュリティ情報を表示する

次のコマンドは、有効期限、スコープ、ロール、トークン ヘッダー、ペイロード、コンパクト トークンなどの JWT セキュリティ情報を表示します。

dotnet user-jwts print {ID} --show-all

特定のユーザーとスコープのトークンを作成する

次のコマンドは、 MyTestUserという名前のユーザーの JWT を作成します。 サポートされている create オプションについては、「 作成コマンド」セクションの「オプション」を 参照してください。

dotnet user-jwts create --name MyTestUser --scope "myapi:secrets"

上記のコマンドには、次の例のような出力があります。

New JWT saved with ID '43e0b748'.
Name: MyTestUser
Scopes: myapi:secrets

Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.{Remaining token deleted}

前述のトークンを使用して、次のコードで /secret2 エンドポイントをテストできます。

using System.Security.Claims;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();
builder.Services.AddAuthentication("Bearer").AddJwtBearer();

var app = builder.Build();

app.MapGet("/", () => "Hello, World!");
app.MapGet("/secret", (ClaimsPrincipal user) => $"Hello {user.Identity?.Name}. My secret")
    .RequireAuthorization();
app.MapGet("/secret2", () => "This is a different secret!")
    .RequireAuthorization(p => p.RequireClaim("scope", "myapi:secrets"));

app.Run();