2017-09-20 3 views
5

(Bearbeiten - Gefunden passende Lösung siehe unten!)Net Core 2.0 Web API JWT mit - Hinzufügen von Identität bricht die JWT Authentifizierung

OK - das ist mein erster Versuch Net Core 2.0 und Authentifizierung, obwohl Ich habe in der Vergangenheit mit Web API 2.0 gearbeitet und in den letzten Jahren ziemlich viel über verschiedene MVC- und Webforms-ASP-Projekte gearbeitet.

Ich versuche, ein Web API ONLY Projekt mit .Net Core zu erstellen. Dies wird das Backend einer Multi-Tenant-Anwendung für die Erstellung einiger Berichte bilden, so dass ich in der Lage sein muss, Benutzer zu authentifizieren. Es scheint, dass der übliche Ansatz darin besteht, JWT zu verwenden - zuerst authentifizieren Sie den Benutzer, um ein Token zu generieren, und geben Sie das dann an den Client weiter, um es bei jeder API-Anfrage zu verwenden. Daten werden mit EF Core gespeichert und abgerufen.

Ich folgte this post für eine grundlegende Möglichkeit, um diese Einrichtung zu erhalten, und ich habe es geschafft zu arbeiten ok - Ich habe einen Controller, der einen Benutzernamen/ein Passwort akzeptiert und ein Token zurückgibt, wenn gültig, und einige Autorisierungsrichtlinien eingerichtet basierend auf den Ansprüchen.

Das nächste, was ich brauche, ist tatsächlich die Benutzer/Passwörter/etc zu verwalten. Ich dachte, ich würde einfach .Net Core Identity dafür verwenden, denn auf diese Weise hätte ich viele vorgefertigte Code für Sorgen über Benutzer/Rollen, Passwörter usw. Ich verwendete benutzerdefinierte User Klasse und UserRole Klassen, die aus dem Standard IdentityUser abgeleitet und IdentityRole Klassen, aber jetzt habe ich wieder zu den Standard-zurückgesetzt.

Das Problem, das ich habe, ist, dass ich nicht ganz herausfinden kann, wie Identität hinzufügen & registrieren Sie alle verschiedenen Dienste (Rollenmanager, UserManager, etc) ohne auch die Authentifizierung zu brechen - im Grunde, sobald ich diese Zeile zu meinem hinzufügen Startup.ConfigureServices Klasse:

services.AddIdentity<IdentityUser, IdentityRole>() 
    .AddEntityFrameworkStores<MyContext>(); 

Es geht alles schief, und ich kann keine Ansprüche nicht mehr sehen, wenn ich eine Anfrage erhalten, so dass alle Richtlinien sperren nur nach unten und man kann nicht auf etwas bekommen.

Wenn ich diese Zeilen nicht habe, dann habe ich Fehler im Zusammenhang mit UserManager, RoleManager, UserStore usw., die nicht für DI registriert sind.

Also ... wie (wenn es möglich ist) kann ich die Identität registrieren und richtig mit dem Kontext verbinden, aber vermeiden/entfernen Sie alle Änderungen am eigentlichen Autorisierungsmechanismus?

Ich habe mich online ein wenig umgeschaut, aber vieles hat sich seit .Net Core 1.x geändert, so dass viele der Tutorials usw. nicht mehr wirklich gültig sind.

Ich habe nicht vor, dass diese API-Anwendung Front-End-Code haben, so dass ich für Cookie-Authentifizierung für Formulare oder etwas für den Moment nicht benötigen.

bearbeiten
ok, habe ich festgestellt jetzt in diesem Code, dass die JWT-Authentifizierung in der Startup.ConfigureServices() Methode einrichten:

services.AddAuthentication(
      JwtBearerDefaults.AuthenticationScheme) 
       .AddJwtBearer(options => 
       { 
       >>breakpoint>>> options.TokenValidationParameters = 
         new TokenValidationParameters 
         { 
          ValidateIssuer = true, 
          ValidateAudience = true, 
          ValidateLifetime = true, 
          ValidateIssuerSigningKey = true, 

          ValidIssuer = "Blah.Blah.Bearer", 
          ValidAudience = "Blah.Blah.Bearer", 
          IssuerSigningKey = 
          JwtSecurityKey.Create("verylongsecretkey") 

         }; 
       }); 

Wenn ich einen Haltepunkt an der Linie angedeutet setzen (über „> > breakpoint >>> ") dann wird es getroffen, wenn ich nicht die Zeilen hinzufügen, um Identitätsdienste hinzuzufügen, aber wenn ich diese Zeilen dann hinzufügen nie wird getroffen. Dies ist unabhängig davon, wo in der Methode ich den services.AddIdentity() Anruf gesetzt habe.Ich bekomme, dass dies einfach ein Lambda ist, so dass es zu einem späteren Zeitpunkt ausgeführt wird, aber gibt es eine Möglichkeit, die AddIdentity-Zeug, um keine Authentifizierung einzurichten, oder den Code sofort entfernen lassen? Ich gehe davon aus irgendwann gibt es einige Code ist, die nicht die Lambda für config wählt ich habe dort gesetzt, wie die Identität stopfen es bereits gesetzt hat ...

Vielen Dank für alles, was zu lesen, wenn Sie :)

haben

EDIT - gefunden einer Antwort
ok, fand ich schließlich dieses GH Problem, das dieses Problem im Grunde genau das ist: https://github.com/aspnet/Identity/issues/1376

Im Grunde, was ich war zweifach zu tun hatte:

Ens ure, dass der Anruf zu services.AddIdentity<IdentityUser, IdentityContext()der Anruf Auth von hinzufügen

ändert zuerst gemacht wurde:

services.AddAuthentication(
      JwtBearerDefaults.AuthenticationScheme) 
       .AddJwtBearer(options => 
... 

An:

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

Diese annoyingly führen in einem Cookie erstellt werden, aber Dies wird dann nicht für die Authentifizierung verwendet, soweit ich das beurteilen kann - es verwendet lediglich das Bearer-Token für Anfragen an Controller/Aktionen, die mindestens [Authorize(Policy = "Administrator")] oder ähnlich eingestellt haben.

Ich muss mehr testen, und ich werde versuchen, hier ein Update hierher zu kommen, wenn ich finde, dass es in irgendeiner Weise nicht funktioniert.

(Herausgegeben - jetzt in als Antwort die richtige Lösung setzen)

+0

hast du mich gerettet. Danke, –

+0

sollten Sie in Betracht ziehen, dies in eine Frage zu brechen und es dann selbst als eine richtige Antwort zu beantworten. – alwayslearning

+0

@alwayslearning keine schlechte Idee ... also habe ich es getan. – GPW

Antwort

3

ich schließlich die Lösung zusammen, so auf Vorschlag des Benutzers alwayslearning ich meinen Beitrag bearbeitet haben und ich diese bei der Umsetzung als tatsächliches Antworten.

ok, das kann richtig gemacht werden. Zuerst müssen Sie die Authentifizierungsoptionen verwenden, auf die ich oben in meiner Bearbeitung hingewiesen habe - das ist in Ordnung. Dann müssen Sie services.AddIdentityCore<TUser>() statt services.AddIdentity<TUser>() verwenden. Dies fügt jedoch nicht eine ganze Menge von Dingen für die Rollenverwaltung hinzu und es fehlt offensichtlich der richtige Konstruktor, um ihm den Typ von Rolle zu geben, den Sie verwenden möchten. Das bedeutet, dass ich in meinem Fall hatte dies zu tun:

IdentityBuilder builder = services.AddIdentityCore<IdentityUser>(opt => 
     { 
      opt.Password.RequireDigit = true; 
      opt.Password.RequiredLength = 8; 
      opt.Password.RequireNonAlphanumeric = false; 
      opt.Password.RequireUppercase = true; 
      opt.Password.RequireLowercase = true; 
     } 
     ); 
     builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services); 
     builder 
      .AddEntityFrameworkStores<MyContext>(); 
     //.AddDefaultTokenProviders(); 

     builder.AddRoleValidator<RoleValidator<IdentityRole>>(); 
     builder.AddRoleManager<RoleManager<IdentityRole>>(); 
     builder.AddSignInManager<SignInManager<IdentityUser>>(); 

Nachdem das getan, das nächste, was sicher zu machen, ist, dass, wenn ein Benutzer-Login-Validierung (vor einem Token zu senden) stellen Sie sicher, das zu verwenden, SignInManager Methode CheckPasswordSignInAsync und nichtPasswordSignInAsync:

public async Task<IdentityUser> GetUserForLogin(string userName, string password) 
    { 
     //find user first... 
     var user = await _userManager.FindByNameAsync(userName); 

     if (user == null) 
     { 
      return null; 
     } 

     //validate password... 
     var signInResult = await _signInManager.CheckPasswordSignInAsync(user, password, false); 

     //if password was ok, return this user. 
     if (signInResult.Succeeded) 
     { 
      return user; 
     } 

     return null; 
    } 

, wenn Sie die PasswordSignInAsync Methode verwenden, dann werden Sie einen Laufzeitfehler erneut erhalten. Kein IAuthenticationSignInHandler wird konfiguriert.

Ich hoffe, das hilft jemandem irgendwann.

+0

Du hast mir definitiv geholfen. Danke vielmals. Es gibt viele Tutorials im Internet veraltet, wenn Sie keine Erfahrung mit JWT oder Identity haben, es ist schwer, eine Lösung zu finden. –

Verwandte Themen