web-dev-qa-db-fra.com

L'authentification mixte ASP.Net Core 2.0 de l'authentification JWT et Windows n'accepte pas les informations d'identification

J'ai créé une API dans asp.net core 2.0 où j'utilise l'authentification en mode mixte. Pour certains contrôleurs JWT et pour certains utilisant l'authentification Windows.

Je n'ai aucun problème avec les contrôleurs qui autorisent avec JWT. Mais pour les contrôleurs où je veux utiliser l'authentification Windows, je suis invité indéfiniment avec la boîte de dialogue de nom d'utilisateur et de mot de passe de Chrome.

Voici mon exemple de code de contrôleur où je veux utiliser l'authentification Windows au lieu de JWT.

[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = "Windows")]
public class TestController : Controller
{
    [HttpPost("processUpload")]
    public async Task<IActionResult> ProcessUploadAsync(UploadFileModel uploadFileModel)
    {

    }
}

Mon code de configuration des services

public void ConfigureServices(IServiceCollection services)
{
     services.AddAuthentication(options =>
     {
        options.DefaultAuthenticateScheme = IISDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
     })
     .AddJwtBearer("Bearer", options =>
     {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,       
            ValidateIssuer = false,  
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("blahblahKey")),
            ValidateLifetime = true, //validate the expiration and not before values in the token
            ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date
        };
     });

     // let only my api users to be able to call 
     services.AddAuthorization(auth =>
     {
        auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
            .RequireClaim(ClaimTypes.Name, "MyApiUser").Build());
     });

     services.AddMvc();
}

Ma méthode de configuration.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseCors("CorsPolicy");

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseAuthentication(); //needs to be up in the pipeline, before MVC
    app.UseMvc();
}

Appréciez vos suggestions et aidez à ce sujet.

Mise à jour: Jusqu'à présent, j'ai débogué mon code sur Chrome. Mais quand j'ai utilisé IE 11, le code ci-dessus fonctionne sans aucun problème.

Cela peut-il être un problème CORS de chrome où le problème de contrôle en amont?

Merci

13
coolcake

Vous devez vous assurer que vous [~ # ~] pas [~ # ~] paramètre Authorization: Bearer <JWT_token> En-tête HTTP lorsque vous essayez d'utiliser Windows Auth. Le point clé ici est comment fonctionne réellement "Windows Auth". Voyons comment cela fonctionne avec le navigateur par exemple.

Appelons cela "un flux normal":

  1. Vous accédez à http://example.com/api/resource dans votre navigateur;
  2. Votre navigateur envoie une demande HTTP GET à http://example.com/api/resource sans aucun Authorization En-tête HTTP pour l'instant (une demande anonyme);
  3. Le serveur Web (ou WebAPI lui-même) reçoit une demande, découvre qu'il n'y a pas d'en-tête Authorization et répond avec 401 Not Authorized code d'état avec WWW-Authenticate: NTLM,Negotiate En-tête HTTP installé ( "Allez-vous-en, pas d'accès anonyme. Seuls les types 'NTLM' ou 'Negotiate' sont les bienvenus!" );
  4. Le navigateur reçoit un 401 réponse, découvrez que la demande était anonyme, ressemble à WWW-Authenticate en-tête et répétez instantanément la demande, maintenant avec Authorization: NTLM <NTLM_token> En-tête HTTP ( "Ok, allez-y doucement, serveur Web! Voici mon token NTLM." );
  5. Le serveur reçoit une deuxième demande, trouve le jeton NTLM dans l'en-tête Authorization, vérifie-la et exécute la demande ( "Ok, vous pouvez passer. Ici est votre ressource. ").

Les choses vont un peu différemment, lorsque vous définissez initialement l'en-tête Authorization sur une valeur:

  1. Votre JS nécessite http://example.com/api/resource avec autorisation JWT;
  2. Votre navigateur envoie une demande HTTP GET à http://example.com/api/resource avec Authorization: Bearer <JWT_token> En-tête HTTP maintenant;
  3. Le serveur Web (ou WebAPI lui-même) reçoit une demande, apprend qu'il existe un en-tête Authorization avec le schéma d'authentification "Bearer" et répond de nouveau avec 401 Not Authorized code d'état avec WWW-Authenticate: NTLM,Negotiate En-tête HTTP installé ( "Allez-vous-en, nous ne savons pas qui sont ces gars 'Bearer', mais nous ne les aimons pas. Seulement 'NTLM' ou les gars de "Négocier" sont les bienvenus! ");
  4. Le navigateur reçoit un 401 réponse, découvrez que la demande était autorisée et décidez que ce jeton est mauvais. Mais, comme vous définissez réellement l'en-tête Authorization, cela signifie que vous avez réellement avez quelques informations d'identification. Et donc il vous demande ces informations d'identification avec cette boîte de dialogue.
21
vasily.sib