it-swarm.com.de

.NET Core IssuerSigningKey aus der Datei für die JWT Bearer-Authentifizierung

Ich habe Probleme mit der Implementierung (oder dem Verständnis) von Signaturschlüsseln für die JWT-Bearer-Token-Authentifizierung. Und ich hoffe, jemand kann mir helfen oder mir erklären, was ich missverstehe.

In den letzten Wochen habe ich unzählige Tutorials gecrawlt und es geschafft, einen benutzerdefinierten Auth-Controller zum Ausführen zu bringen, der meine Token ausgibt. Außerdem habe ich die JWT-Trägerauthentifizierung eingerichtet, um die Token im Header zu validieren.

Es klappt.

Mein Problem ist, dass alle Beispiele und Tutorials entweder zufällige oder in Gedächtnis (Herausgeber) signierende Schlüssel generieren oder fest codierte "Passwort" -Strings verwenden oder sie aus einer Konfigurationsdatei entnehmen (suchen Sie in den Codebeispielen nach "Passwort").

Was ich für das Validierungssetup (in der StartUp.cs) meine:


  //using hardcoded "password"
  SecurityKey key = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes("password"));

  app.UseJwtBearerAuthentication(new JwtBearerOptions
  {
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters
    {
      ValidateIssuer = true,
      ValidIssuer = "MyIssuer",
      ValidateAudience = true,
      ValidAudience = "MyAudience",
      ValidateLifetime = true,
      IssuerSigningKey = key
    }
  });

Im AuthController, der das Token erstellt:


  //using hardcoded password
  var signingKey = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes("password"));
  SigningCredentials credentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

  var jwt = new JwtSecurityToken     // Create the JWT and write it to a string
  (
    issuer: _jwtTokenSettings.Issuer,
    audience: _jwtTokenSettings.Audience,
    claims: claims,
    notBefore: now,
    expires: now.AddSeconds(_jwtTokenSettings.LifetimeInSeconds),
    signingCredentials: credentials
  );

In diese Frage verwendeten sie:

RSAParameters keyParams = RSAKeyUtils.GetRandomKey();

Meine (aktuelle) Annahme war, dass Sie in der Produktion keine fest codierten Zeichenfolgen oder Zeichenfolgen aus Konfigurationsdateien für die Tokensignaturschlüssel verwenden sollten. Verwenden Sie stattdessen einige Zertifikatsdateien ??? Liege ich falsch?

Deshalb habe ich versucht, die Zeichenfolgen durch ein Zertifikat zu ersetzen, das im Auth-Controller funktioniert:


  //using a certificate file
  X509Certificate2 cert = new X509Certificate2("MySelfSignedCertificate.pfx", "password");
  X509SecurityKey key = new X509SecurityKey(cert);
  SigningCredentials credentials = new SigningCredentials(key, "RS256");

  var jwt = new JwtSecurityToken      // Create the JWT and write it to a string
  (
     issuer: _jwtTokenSettings.Issuer,
     audience: _jwtTokenSettings.Audience,
     claims: claims,
     notBefore: now,
     expires: now.AddSeconds(_jwtTokenSettings.LifetimeInSeconds),
     signingCredentials: credentials
  );

Es scheint jedoch keine Möglichkeit zu geben, die Validierung mithilfe eines Zertifikats zu erhalten.


  X509Certificate2 cert = new X509Certificate2("MySelfSignedCertificate.pfx", "password");
  SecurityKey key == // ??? how to get the security key from file (not necessarily pfx)

  app.UseJwtBearerAuthentication(new JwtBearerOptions
  {
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters
    {
      ValidateIssuer = true,
      ValidIssuer = "MyIssuer",
      ValidateAudience = true,
      ValidAudience = "MyAudience",
      ValidateLifetime = true,
      IssuerSigningKey = key
    }
  });

Liege ich falsch, dass ich Zertifikate für die Signaturschlüssel verwenden soll? Wie kann ich die Signaturschlüssel in der Produktion ändern, wenn sich der Authentifizierungscontroller auf einem anderen Server befindet als die konsumierende/gesicherte Web-API (möglicherweise einmal, nicht jetzt)?

Es scheint, dass ich auch den Punkt (erforderliche Schritte) verpasse, um die Antwort von diese Frage zu erhalten.


Jetzt habe ich es zum Laufen gebracht. Mir fehlt immer noch der Punkt, ob es so sein sollte.


Bemerkenswert: Datei nicht gefunden (nach Bereitstellung auf dem Server)

Für alle, die dies verwenden und es funktioniert, wenn es in Visual Studio gestartet wird, aber nach der Bereitstellung auf einem Server/Azure lautet die Meldung "Datei nicht gefunden":

lesen und stimmen Sie dieser Frage zu: X509-Zertifikat lädt private Schlüsseldatei nicht auf Server


Bemerkenswert 2: Man braucht es eigentlich nicht für die tokenbasierte Authentifizierung

Der öffentliche Schlüssel muss sich nicht auf der API-Seite befinden. Es wird automatisch über den Erkennungsendpunkt des Authentifizierungsservers abgerufen.

15
monty

Oh je, so einfach ist das:

SecurityKey key = new X509SecurityKey(cert);

Oder als vollständiges Beispiel von oben:

X509Certificate2 cert = new X509Certificate2("MySelfSignedCertificate.pfx", "password");
SecurityKey key = new X509SecurityKey(cert); //well, seems to be that simple
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidIssuer = "MyIssuer",
        ValidateAudience = true,
        ValidAudience = "MyAudience",
        ValidateLifetime = true,
        IssuerSigningKey = key
     }
});
11
monty

Ein sehr wichtiger Punkt, wenn Sie Zertifikatsdateien verwenden, ist, dass der Client nur den öffentlichen Schlüssel verwenden sollte, während der Server die Datei mit dem privaten Schlüssel benötigt.

Sie möchten Ihre private Schlüsseldatei nicht an Dritte weitergeben. Sie benötigen immer nur den öffentlichen Schlüssel.

// On client
var publicCert = new X509Certificate2("MySelfSignedCertificate.cer");
var publicKey = new X509SecurityKey(publicCert);
...
    IssuerSigningKey = publicKey

Die einfachste Möglichkeit, PFX (privat) in CER (öffentlich) zu konvertieren, besteht möglicherweise darin, in den Windows-Zertifikat-Manager zu importieren und dann nur mit dem öffentlichen Schlüssel zu exportieren.

Über die Befehlszeile können Sie auch PowerShell 5 erstellen (noch nicht in PowerShell 6):

Get-PfxCertificate -FilePath MySelfSignedCertificate.pfx | Export-Certificate -FilePath MySelfSignedCertificate.cer

Alternativ können Sie OpenSSL installieren und verwenden, um es über die Befehlszeile zu konvertieren.

Hinweis 1: Nachdem Sie die Autorität festgelegt haben, kann die automatische Erkennung möglicherweise den öffentlichen Schlüssel vom Server finden.

Hinweis 2: Anstatt das Zertifikat in einer Datei zu speichern, können Sie es auch im Windows-Zertifikatspeicher speichern und per Fingerabdruck darauf verweisen (PFX- und CER-Dateien können importiert werden).

1
Sly Gryphon