2017-09-20 2 views
5

(Modifier - trouvé solution appropriée voir ci-dessous!).Net Core 2.0 API Web à l'aide JWT - Ajout d'identité casse l'authentification JWT

OK - ceci est ma première tentative de .Net Core 2.0 et l'authentification, bien que J'ai fait des choses avec l'API Web 2.0 par le passé et j'ai beaucoup travaillé sur divers projets ASP MVC et Webform au cours des dernières années. J'essaie de créer un projet API Web UNIQUEMENT en utilisant .Net Core. Cela constituera l'arrière-plan d'une application multi-locataire pour la production de certains rapports. Je dois donc pouvoir authentifier les utilisateurs. Il semble que l'approche habituelle consiste à utiliser JWT - d'abord authentifier l'utilisateur pour générer un jeton, puis le passer au client pour l'utiliser sur chaque requête d'API. Les données seront stockées et récupérées en utilisant EF Core.

J'ai suivi this post pour une façon simple d'obtenir cette configuration, et j'ai réussi à faire fonctionner ça - j'ai un contrôleur qui accepte un nom d'utilisateur/mot de passe et retourne un jeton si valide, et quelques règles d'autorisation basé sur les revendications.

La prochaine chose dont j'ai besoin est de gérer réellement les utilisateurs/mots de passe/etc. Je pensais que j'utiliserais .Net Core Identity pour cela comme ça j'aurais beaucoup de code prêt à l'emploi pour m'inquiéter des utilisateurs/rôles, mots de passe etc. J'utilisais des classes User et UserRole qui dérivaient de la norme IdentityUser et IdentityRole classes, mais je suis depuis revenu aux standards maintenant. Le problème que j'ai est que je ne peux pas tout à fait comprendre comment ajouter l'identité & enregistrer tous les différents services (rolemanager, usermanager, etc) sans également briser l'authentification - fondamentalement dès que j'ajoute cette ligne à mon Startup.ConfigureServices classe:

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

tout va mal, et je ne peux plus voir toute réclamation quand je reçois une demande, de sorte que toutes les politiques de verrouillage juste en bas et vous ne pouvez pas arriver à quoi que ce soit.

Si je n'ai pas ces lignes, alors je me retrouve avec des erreurs liées à UserManager, RoleManager, UserStore, etc., toutes n'étant pas enregistrées pour DI.

Alors ... comment (si c'est possible) puis-je enregistrer Identity et l'accrocher au contexte correctement, mais éviter/supprimer des modifications au mécanisme d'autorisation actuel?

J'ai regardé un peu en ligne, mais beaucoup de choses ont changé depuis. Net Core 1.x, donc beaucoup de tutoriels, etc. ne sont plus vraiment valables.

Je n'ai pas l'intention de cette application API d'avoir un code frontal, donc je n'ai pas besoin d'authentification par cookie pour les formulaires ou quoi que ce soit pour le moment.

Modifier
ok, je l'ai maintenant trouvé que dans ce code la mise en place de l'authentification JWT dans la méthode Startup.ConfigureServices():

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") 

         }; 
       }); 

Si je mets un point d'arrêt à la ligne indiquée (via « > > breakpoint >>> ") puis il est frappé quand je ne pas ajouter les lignes pour ajouter des services d'identité, mais si j'ajoute ces lignes alors jamais obtient touché. C'est vrai, peu importe où dans la méthode j'ai mis l'appel services.AddIdentity().Je comprends qu'il s'agit simplement d'un lambda, donc il sera exécuté plus tard, mais est-ce qu'il y a un moyen de faire en sorte que l'élément AddIdentity ne configure pas l'authentification, ou que le code le supprime immédiatement? Je suppose à un moment donné, il y a un code qui choisit de ne pas exécuter le Lambda pour config je l'ai mis là comme la substance d'identité est déjà réglée ...

Merci d'avoir lu tout ce que si vous avez :)

EDIT - trouvé une réponse
ok, j'ai finalement trouvé ce problème GH qui est essentiellement exactement ce problème: https://github.com/aspnet/Identity/issues/1376

En fait ce que je devais faire était double:

Ens ure que l'appel à services.AddIdentity<IdentityUser, IdentityContext() a été fait premier

Modifier l'appel à ajouter auth de:

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

Pour:

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

Cela ne génère fâcheusement dans un cookie en cours de création, mais ceci n'est pas utilisé pour l'authentification autant que je peux dire - c'est purement en utilisant le jeton de porteur sur des demandes aux contrôleurs/actions qui ont [Authorize(Policy = "Administrator")] ou un ensemble semblable au moins.

J'ai besoin de tester plus, et je vais essayer de revenir ici une mise à jour si je trouve que cela ne fonctionne pas d'une manière ou d'une autre.

(Sous la direction - mettre en bonne solution comme une réponse maintenant)

+0

vous m'a sauvé. merci –

+0

vous devriez envisager de briser ceci en une question et ensuite y répondre vous-même comme une bonne réponse. – alwayslearning

+0

@alwayslearning n'est pas une mauvaise idée ... alors je l'ai fait. – GPW

Répondre

3

j'ai finalement mis en place la solution, donc à la suggestion de l'utilisateur alwayslearning j'ai édité mon post et je mets cela en tant que réelle répondre.

ok, Cela peut être fait correctement. Tout d'abord, vous devez utiliser les options d'authentification que j'ai indiquées dans mon édition ci-dessus - c'est bien. Ensuite, vous devez utiliser services.AddIdentityCore<TUser>() plutôt que services.AddIdentity<TUser>(). Cependant, cela n'ajoute pas tout un tas de choses à la gestion des rôles et manque apparemment du bon constructeur pour lui donner le type de rôle que vous voulez utiliser. Cela signifie que, dans mon cas, je devais le faire:

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

Après avoir fait cela, la prochaine chose est de faire en sorte que lors de la validation d'une connexion de l'utilisateur (avant l'envoi d'un jeton), vous assurez-vous d'utiliser la méthode SignInManager CheckPasswordSignInAsync et pasPasswordSignInAsync:

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; 
    } 

si vous utilisez la méthode PasswordSignInAsync vous obtiendrez une erreur d'exécution re. Non IAuthenticationSignInHandler en cours de configuration. J'espère que cela aidera quelqu'un à un moment donné.

+0

Vous m'avez certainement aidé. Merci beaucoup. Il existe de nombreux didacticiels obsolètes sur Internet lorsque vous n'avez aucune expérience avec JWT ou Identity, il est difficile de trouver une solution. –