it-swarm.com.de

Dotnet Core 2.0-Authentifizierung, mehrere Schemas, Identitäts-Cookies und JWT

In dotnet core 1.1 asp konnte ich Identitäts-Middleware, gefolgt von jwt-Middleware, konfigurieren und verwenden. Dazu habe ich Folgendes getan:

  app.UseIdentity();
  app.UseJwtBearerAuthentication(new JwtBearerOptions() {});

Das hat sich nun dahingehend geändert, dass wir die Middleware implementieren mit:

   app.UseAuthentication();

Die Konfiguration der Einstellungen erfolgt über den Abschnitt ConfigureServices von Startup.cs.

In der Migrationsdokumentation gibt es einige Verweise auf die Verwendung von Berechtigungsschemas:

https://docs.Microsoft.com/de-de/aspnet/core/migration/1x-to-2x/identity-2x#authentication-middleware-und-services

In 2.0-Projekten wird die Authentifizierung über Dienste konfiguriert. Jeder Das Authentifizierungsschema wird in der ConfigureServices-Methode von .__ registriert. Startup.cs. Die UseIdentity-Methode wird durch UseAuthentication ersetzt.

Zusätzlich gibt es einen Hinweis auf:

Standardauthentifizierungsschemas festlegen

In 1.x die Eigenschaften AutomaticAuthenticate und AutomaticChallenge waren auf ein einziges Authentifizierungsschema festgelegt. Dort war keine gute Möglichkeit, dies durchzusetzen. 

In 2.0 waren diese beiden Eigenschaften Als Flag für die einzelne AuthenticationOptions-Instanz und .__ entfernt. sind in die Basisklasse AuthenticationOptions umgezogen. Die Eigenschaften kann im Aufruf der AddAuthentication-Methode innerhalb von .__ konfiguriert werden. ConfigureServices-Methode von Startup.cs:

Verwenden Sie alternativ eine überladene Version der AddAuthentication Methode, um mehr als eine Eigenschaft festzulegen. Im folgenden überladen Beispiel für eine Methode ist das Standardschema auf .__ eingestellt. CookieAuthenticationDefaults.AuthenticationScheme. Die Authentifizierung Das Schema kann alternativ in Ihrer Person angegeben werden [Authorize] -Attribute oder Berechtigungsrichtlinien.

Ist es in dotnet core 2.0 noch möglich, mehrere Authentifizierungsschemas zu verwenden? Ich kann die Richtlinie nicht dazu bringen, die JWT-Konfiguration ("Bearer" -Schema) zu respektieren, und nur Identity arbeitet derzeit mit beiden Konfigurationen. Ich kann keine Beispiele für mehrere Authentifizierungsschemas finden.

Bearbeiten:

Ich habe die Dokumentation noch einmal gelesen und verstehe jetzt, dass

app.UseAuthentication()

fügt die automatische Authentifizierung für ein Standardschema hinzu. Identität konfiguriert die Standardschemas für Sie.

Ich bin mit dem Problem umgegangen, das wie ein Hack aussieht, der gegen die neuen APIs arbeitet, indem ich Folgendes in Startup.cs Configure ausführte:

    app.UseAuthentication();
    app.Use(async (context, next) =>
    {
        if (!context.User.Identity.IsAuthenticated)
        {
            var result = await context.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
            if (result?.Principal != null)
            {
                context.User = result.Principal;
            }
        }

        await next.Invoke();
    });

Ist dies der richtige Weg, oder sollte ich das Framework, das DI und die Schnittstellen für benutzerdefinierte Implementierungen von IAuthenticationSchemeProvider verwenden?

Bearbeiten - Weitere Details zur Implementierung und wo sie zu finden sind.

Die JWT-Konfiguration ist hier zu finden, und ich benutze Richtlinien, um die Autorisierung zu definieren. Dazu gehören die akzeptierten Auth-Schemas:

https://github.com/Arragro/ArragroCMS/blob/master/src/ArragroCMS.Management/Startup.cs

Benutzerdefinierte Middleware ist noch implementiert. Der Auth-Controller ist hier:

https://github.com/Arragro/ArragroCMS/blob/master/src/ArragroCMS.Web.Management/ApiControllers/AuthController.cs

Es verwendet von der App generierte API-Schlüssel, um nur lesenden Zugriff auf Daten zu erhalten. Die Implementierung eines Controllers unter Verwendung der Richtlinie finden Sie hier:

https://github.com/Arragro/ArragroCMS/blob/master/src/ArragroCMS.Web.Management/ApiControllers/SitemapController.cs

Ändern Sie die DB-Verbindungszeichenfolge so, dass sie auf Ihren SQL Server verweist, und führen Sie die Anwendung aus. Es migriert die Datenbank automatisch und konfiguriert einen Admin-Benutzer ([email protected] - ArragroPassword1!). Gehen Sie dann zur Registerkarte Einstellungen in der Menüleiste und klicken Sie auf "Konfigurieren der JWT ReadOnly-API-Schlüsseleinstellungen", um einen Schlüssel zu erhalten. Rufen Sie in Postman ein jwt-Token ab, indem Sie eine neue Registerkarte konfigurieren und auf POST mit der folgenden Adresse setzen:

http: // localhost: 5000/api/auth/readonly-token

Geben Sie die Header an: Content-Type: application/json

Liefern Sie den Körper: 

{
    "apiKey": "the api token from the previous step"
}

Kopieren Sie das Token in der Antwort, und verwenden Sie dann im Postman das Folgende:

http: // localhost: 5000/api/sitemap/flat

Authorization: "bearer - The token you received in the previous request"

Aufgrund der benutzerdefinierten Middleware wird es anfänglich funktionieren. Kommentieren Sie den oben genannten Code aus und versuchen Sie es erneut. Sie erhalten eine 401.

Edit - @ DonnyTians Antwort unten beschreibt meine Lösung in seinen Kommentaren. Das Problem, das ich hatte, bestand darin, eine Standardrichtlinie für UseMvc festzulegen, das Schema jedoch nicht anzugeben:

    services.AddMvc(config =>
    {
        var defaultPolicy = new AuthorizationPolicyBuilder(new[] { JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme })
                         .RequireAuthenticatedUser()
                         .Build();
        config.Filters.Add(new AuthorizeFilter(defaultPolicy));
        config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
        config.Filters.Add(new ValidateModelAttribute());
    });

Diesem Ratschlag folgend funktioniert dies ohne benutzerdefinierte Middleware.

26
didiHamman

Asp.Net Core 2.0 unterstützt definitiv mehrere Authentifizierungsschemata. Anstelle eines Hackings mit authentifizierter Middleware können Sie versuchen, das Schema im Attribut Authorize anzugeben:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Ich habe es versucht und es hat gut funktioniert. Angenommen, Sie haben Identity und JWT wie folgt hinzugefügt:

services.AddIdentity<ApplicationUser, ApplicationRole>()
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

Da AddIdentity() bereits die Cookie-Authentifizierung als Standardschema festgelegt hat, müssen Sie das Schema im Authorize-Attribut von Controllern angeben. Im Moment habe ich keine Ahnung, wie ich das von AddIdentity() festgelegte Standardschema überschreiben könnte, oder vielleicht sollten wir das lieber nicht tun.

Eine Problemumgehung besteht darin, eine neue Klasse zu erstellen (Sie können sie JwtAuthorize nennen), die von Authorize abgeleitet ist und Bearer als Standardschema hat, sodass Sie sie nicht jedes Mal angeben müssen.

UPDATE

Weg gefunden, das Identitäts-Standardauthentifizierungsschema außer Kraft zu setzen!

Statt unter der Zeile:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

Verwenden Sie unterhalb der Überladung, um das Standardschema festzulegen:

services.AddAuthentication(option =>
                {
                    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>....

UPDATE 2 Wie in Kommentaren erwähnt, können Sie sowohl Identity als auch JWT-Authentifizierung aktivieren, indem Sie sie zusammenfügen . [Authorize(AuthenticationSchemes = "Identity.Application" + "," + JwtBearerDefaults.AuthenticationScheme)]

21
DonnyTian

Ich habe diese Frage verwendet, um mein (ähnliches) Problem der Kombination von Identitäts- und Trägerauthentifizierung in einer .Net Core 2.0-Webanwendung zu lösen. Wichtig zu beachten ist, dass Sie new[] { JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme zum folgenden Code hinzufügen müssen: 

services.AddMvc(config =>
    {
        var defaultPolicy = new AuthorizationPolicyBuilder(new[] { JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme })
                         .RequireAuthenticatedUser()
                         .Build();
        config.Filters.Add(new AuthorizeFilter(defaultPolicy));
        config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
        config.Filters.Add(new ValidateModelAttribute());
    });

UND

Fügen Sie die Standardauthentifizierungsoption hinzu: 

services.AddAuthentication(option =>
                {
                    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>....

Bei meiner auf dieser Frage basierenden ersten Lösung habe ich nicht bemerkt, dass beide Änderungen in meinem Code erforderlich waren. Hoffentlich kann ich jemandem die Stunden ersparen, die ich verschwendet habe :)

13
MartinH

Sean Wildermuth hat einen Blogbeitrag zum Aktivieren von Cookies und jwt: https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2

Er kettet es so:

services.AddAuthentication()
  .AddCookie(cfg => cfg.SlidingExpiration = true)
  .AddJwtBearer(cfg =>
  {
    cfg.RequireHttpsMetadata = false;
    cfg.SaveToken = true;

    cfg.TokenValidationParameters = new TokenValidationParameters()
    {
      ValidIssuer = Configuration["Tokens:Issuer"],
      ValidAudience = Configuration["Tokens:Issuer"],
      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
    };

  });
0
Guerrilla

Basierend auf dem, was Kevin Rich hier sagt http://www.whoiskevinrich.com/configuring-asp-net-core-2-0-authentication

Ich konnte jwt als Standardauthentifizierungsmethode festlegen:

        services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            sharedOptions.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
        })

Ich habe dies getestet und konnte (AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme) aus dem in donnytians Beitrag genannten Berechtigungsattribut entfernen.

0
John