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 で終わるファイル名拡張子を持つファイルを検索し、そのファイルを使用します。

コマンド

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

作成

使用法: 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 がそれ以前に有効であってはいけない、'yyyy-MM-dd [[HH:mm[[:ss]]]]' 形式での UTC の日付と時刻。 既定値は、JWT が作成された日付と時刻です。
--expires-on JWT の有効期限が切れる、'yyyy-MM-dd [[[ [HH:mm]]:ss]]' 形式での UTC の日付と時刻。 既定値は --not-before の日付の 6 か月後です。 このオプションは、--valid-for オプションと組み合わせて使用しないでください。
--valid-for その後に JWT の有効期限が切れることになる期間です。 日数の場合は 'd'、時間の場合は 'h'、分の場合は 'm'、秒の場合は 's' が続く数値 (例: 365d') を使用して指定します。 このオプションは、--expires-on オプションと組み合わせて使用しないでください。
-o | --output コマンドからの出力を表示するために使用する形式です。 'default'、'token'、または '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 エラーを返します。 運用アプリは、一連の資格情報を介したログインに対する応答で、セキュリティ トークン サービス (STS) から JWT を取得する場合があります。 ローカル開発中に API を操作するために、dotnet user-jwts コマンド ライン ツールを使用して、アプリ固有のローカル JWT を作成および管理できます。

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

user-jwts ツールは、値が格納される場所や方法などの実装の詳細を隠します。 このツールは、実装の詳細を知らなくても使用できます。 値は、ローカル コンピューターのユーザー プロファイル フォルダー内の JSON ファイルに格納されます。

ファイル システム パス:

%APPDATA%\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 をテストします。

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

ここで {token} は先程生成した JWT です。

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

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

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

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

サポートされている作成オプションについては、このトピックの「作成」を参照してください。

次のコマンドは、MyTestUser という名前のユーザーの JWT を作成します。

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();