Verwalten von JSON-Webtoken in der Entwicklung mit dotnet-user-jwts

Von Rick Anderson

Das dotnet user-jwts Befehlszeilentool kann App-spezifische lokale JSON-Webtoken (JWTs) erstellen und verwalten.

Dieser Artikel enthält Syntaxdetails für den Befehl und die Beispiele.

Übersicht

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

Beschreibung

Erstellt und verwaltet projektspezifische lokale JSON-Webtoken.

Argumente

PROJECT | SOLUTION

Das MSBuild-Projekt, auf das ein Befehl angewendet werden soll. Wenn kein Projekt angegeben ist, durchsucht MSBuild das aktuelle Arbeitsverzeichnis nach einer Datei, die über eine Dateierweiterung verfügt, die in Proj endet. Anschließend wird diese Datei verwendet, um die Projektinformationen für den Befehl abzurufen.

Befehle

Befehl Beschreibung
clear Löscht alle ausgestellten JWTs für ein Projekt.
create Stellt ein neues JSON-Webtoken aus.
remove Ein angegebenes JWT löschen.
key Den zum Ausstellen von JWTs verwendeten Signaturschlüssel anzeigen oder zurücksetzen.
list Die für das Projekt ausgegebenen JWTs auflisten.
print Zeigen Sie die Details eines angegebenen JWTTyps an.

Optionen für den Befehl "Erstellen"

Verwendung: dotnet user-jwts create [options]

Option Beschreibung
-p \| --project Der Pfad des Projekts, das bearbeitet werden soll. Ist standardmäßig auf das Projekt im aktuellen Verzeichnis festgelegt.
--scheme Der Schemaname, der für das generierte Token verwendet werden soll. Wird standardmäßig auf Bearer festgelegt.
-n \| --name Der Name des Benutzers, für den das JWT erstellt werden soll. Standardmäßig wird der aktuelle Umgebungsbenutzer verwendet.
--audience Die Zielgruppen, für die JWT erstellt werden soll. Standardmäßig werden die URLs verwendet, die in der launchSettings.json-Datei des Projekts konfiguriert sind.
--issuer Der Emittent ist JWT. Wird standardmäßig auf dotnet-user-jwts festgelegt.
--scope Ein Berechtigungsbereichsanspruch, der zum JWT hinzugefügt werden soll. Einmal pro Bereich angeben.
--role Ein Rollen-Claim, der zu JWT hinzugefügt werden soll. Geben Sie dies einmal für jede Rolle an.
--claim Elemente, die dem JWT hinzugefügt werden sollen. Geben Sie dies für jeden Anspruch einmal im Format name=value an.
--not-before Das UTC-Datum und die Uhrzeit, zu der die JWT gültig wird, im Format yyyy-MM-dd [[HH:mm[[:ss]]]]. Standardmäßig werden Datum und Uhrzeit verwendet, zu denen das JWT erstellt wird.
--expires-on Das UTC-Datum und die Uhrzeit, zu der JWT abläuft, im Format yyyy-MM-dd [[[ [HH:mm]]:ss]]. Der Standardwert ist sechs Monate nach dem --not-before Datum. Verwenden Sie diese Option nicht mit der Option --valid-for.
--valid-for Die Zeitspanne, die JWT gültig bleibt. Wenn der Zeitpunkt erreicht ist, läuft JWT ab. Geben Sie eine Zahl gefolgt von der Zeiteinheit (d Tage, h Stunden, m Minuten, s Sekunden) an, z. B. 365d. Verwenden Sie diese Option nicht mit der Option --expires-on.
-o \| --output Das Format, das zum Anzeigen der Ausgabe aus dem Befehl verwendet werden soll: default, , tokenoder json.
-h \| --help Hilfeinformationen für den Befehl anzeigen.

Mit dateibasierten Apps verwenden

dotnet user-jwts funktioniert mit dateibasierten Apps über die --file Option. Zeigen Sie --file auf die C#-Datei der App (.cs).

Im folgenden Beispiel ist die App eine Datei app.cs ohne Projektdatei, und der Befehl wird in einer Befehlsshell aus dem Stammverzeichnis der App ausgeführt:

dotnet user-jwts create --file app.cs

Die --file Option gilt für jeden user-jwts Befehl (create, clear, key, list, print und remove), auf die gleiche Weise wie die --project Option. Wenn weder --file angegeben noch --project angegeben wird, durchsucht das Tool das aktuelle Verzeichnis nach einem MSBuild-Projekt.

Regeln:

  • Der übergebene --file Pfad muss eine C#-Datei mit der .cs Dateierweiterung sein.
  • --file und --project können nicht zusammen verwendet werden.

Beispiele

Führen Sie die folgenden Befehle aus, um ein leeres Webprojekt zu erstellen und das NuGet-Paket Microsoft.AspNetCore.Authentication.JwtBearer hinzuzufügen:

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

Ersetzen Sie den Inhalt der datei Program.cs durch den folgenden Code:

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

Im vorherigen Code gibt eine GET-Anforderung an den /secret Endpunkt einen 401 Unauthorized Fehler zurück. Eine Produktions-App erhält möglicherweise den JWT von einem Security Token Service, möglicherweise als Reaktion auf die Anmeldung mit Anmeldeinformationen. Wenn Sie die API während der lokalen Entwicklung verwenden, kann das dotnet user-jwts Befehlszeilentool zum Erstellen und Verwalten von appspezifischen lokalen JWTs verwendet werden.

Das user-jwts Tool ähnelt dem Konzept des Tools mit geheimen Benutzerschlüsseln . Sie kann verwendet werden, um Werte für die App zu verwalten, die nur für den Entwickler auf dem lokalen Computer gültig sind. Tatsächlich verwendet das user-jwts Tool die user-secrets Infrastruktur, um den Schlüssel zu verwalten, mit dem die JWTs signiert sind. Durch diesen Ansatz wird sichergestellt, dass der Schlüssel sicher im Benutzerprofil gespeichert wird.

Das user-jwts Tool blendet Implementierungsdetails aus, z. B. wo und wie die Werte gespeichert werden. Das Tool kann verwendet werden, ohne die Implementierungsdetails zu kennen.

Die Werte werden in einer JSON-Datei im Benutzerprofilordner des lokalen Computers gespeichert:

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

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

JWT erstellen

Mit dem folgenden Befehl wird ein lokaler JWT erstellt:

dotnet user-jwts create

Mit dem vorherigen Befehl wird eine JWT erstellt und die Projektdatei appsettings.Development.json mit JSON aktualisiert, ähnlich wie im folgenden Beispiel:

{
  "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"
      }
    }
  }
}

Kopieren Sie die JWT und die ID, die im vorherigen Befehl erstellt wurden. Verwenden Sie ein Tool wie Curl, um den /secret Endpunkt zu testen, wobei {token} die zuvor generierte JWT ist:

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

JWT Sicherheitsinformationen anzeigen

Der folgende Befehl zeigt die JWT Sicherheitsdaten an, einschließlich Ablauf, Bereiche, Rollen, Tokenheader und Nutzlast sowie das kompakte Token:

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

Erstellen eines Tokens für einen bestimmten Benutzer und Bereich

Der folgende Befehl erstellt einen JWT für einen Benutzer mit dem Namen MyTestUser. Die unterstützten create Optionen finden Sie im Abschnitt "Optionen für den Befehl erstellen" .

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

Der vorangehende Befehl gibt eine Ausgabe aus, die dem folgenden Beispiel ähnelt:

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

Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.{Remaining token deleted}

Das vorangehende Token kann verwendet werden, um den /secret2-Endpunkt im folgenden Code zu testen:

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