web-dev-qa-db-fra.com

AuthorizeAttribute avec JWT Token- Authentication dans .NET Core 2.0

J'ai implémenté une authentification Token Bearer JWT dans mon API Web qui s'exécute avec .net core 2.0. Maintenant, j'ai créé un autre site Web qui parle avec mon API Web. La récupération du jeton fonctionne, je l’ajoute aux cookies, lorsque je débogue, je vois mon cookie (nom est "identité") avec la valeur correcte.

Dans le modèle de projets, il y a le contrôleur HomeController avec les actions. J'utilise l'action Contact à mes fins et l'annote avec AuthorizeAttribute:

[Authorize]
public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    return View();
}

Maintenant, je navigue (en tant qu'utilisateur anonyme) vers /home/contact - parfait: il me redirige vers /home/login où je dois me connecter.

Lorsque j'essaie de me connecter, le message d'erreur suivant s'affiche:

IAuthenticationSignInHandler n'est pas configuré pour gérer la connexion pour le schéma: porteur

Je suppose que la configuration des jetons est fausse - je suppose qu'il y a encore quelques choses que je fais mal ici.

Tout d’abord, voici mon fichier Startup.cs (je n’ai rien supprimé car il existe des dépendances dans la commande):

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();

    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(30);
        options.Cookie.HttpOnly = true;
    });

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

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("mysupersecret_secretkey!123")),
            ValidateIssuer = true,
            ValidIssuer = "ExampleIssuer",
            ValidateAudience = true,
            ValidAudience = "ExampleAudience",
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero,
            SaveSigninToken = true
        };
        options.Events = new JwtBearerEvents
        {
            OnTokenValidated = context =>
            {
                JwtSecurityToken accessToken = context.SecurityToken as JwtSecurityToken;
                if (accessToken != null)
                {
                    ClaimsIdentity identity = context.Result.Principal.Identity as ClaimsIdentity;
                    identity?.AddClaim(new Claim("access_token", accessToken.RawData));
                }

                return Task.CompletedTask;
            }
        };
     })
    .AddCookie(
           o =>
           {
               o.Cookie.Name = "beareridentity";
               o.LoginPath = new PathString("/Home/Login/");
               o.AccessDeniedPath = new PathString("/Home/Login/");
           });

    services.AddMvc();

    services.AddTransient<IAccountService, AccountService>();
    services.AddTransient(typeof(ISession), serviceProvider =>
    {
        var httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>();
        return httpContextAccessor.HttpContext.Session;
    });
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseSession();
    app.UseStaticFiles();
    app.UseAuthentication();


    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

et voici mon login-action:

[HttpPost]
public async Task<IActionResult> Login(LoginData data)
{
    var loginresult = (await _accountService.GetLoginToken(data.Username, data.Password));

    if (!loginresult.Success)
        return RedirectToAction("Login");

    Response.Cookies.Append("identity", loginresult.Token, new CookieOptions { Expires = DateTimeOffset.Now.Add

    int id = await _getIdFromToken(loginresult);

    ApplicationUser user;
    await _signin(user = await _accountService.GetUserAsync(id));
    _session.SetData("actualuser", user);

    return RedirectToAction("Index");
}

private async Task _signin(ApplicationUser c)
{
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.MobilePhone, c.Phone??""),
        new Claim(ClaimTypes.Name, c.UserName)
    };
    var userIdentity = new ClaimsIdentity();
    userIdentity.AddClaims(claims);
    ClaimsPrincipal userPrincipal = new ClaimsPrincipal(userIdentity);

    try
    {
        await HttpContext.SignInAsync(
            JwtBearerDefaults.AuthenticationScheme,
            userPrincipal,
            new Microsoft.AspNetCore.Authentication.AuthenticationProperties
                {
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
                    IsPersistent = true,
                    AllowRefresh = true,
                    IssuedUtc = DateTimeOffset.Now
                });
    }
    catch (Exception e)
    {
        throw;
    }
}
7
Matthias Burger

Voici un article de blog sur la façon dont vous pouvez utiliser les cookies comme mécanisme de diffusion pour vos JWT sur ASP.NET Core 2.0, comme vous essayez de le faire: Authentification par jeton JWT avec des cookies dans ASP.NET Core

Je ne l'ai pas essayé, mais cela pourrait vous aider à comprendre où vous pourriez le faire mal.

2
Frank Fajardo

J'avais un problème similaire. Vérifiez le fichier Web.config et vérifiez si vous avez un nœud du type ou vérifiez s'il existe un nœud pour l'authentification, peut-être pour cette raison ou si la configuration est incorrecte.

Je développe une application MVC 5 et ma configuration Web est comme ceci

  <modules>
  <remove name="FormsAuthentication" />
  <remove name="ApplicationInsightsWebTracking" />
  <add name="ApplicationInsightsWebTracking" 
   type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, 
   Microsoft.AI.Web" preCondition="managedHandler" />
   </modules>
<authentication mode="None" />

J'utilise les modules d'authentification asp.net pré construits avec leur base de données

0
dlogon

Le schéma par défaut ne correspond à aucun gestionnaire (dans ce cas, le cookie). Si vous le pouvez, essayez d’intégrer cela dans votre code (cela pourrait être spécifique au .net Core 2):

services.AddAuthentication("YourSchemeNameHere")
.AddCookie("YourSchemeNameHere", options => 
{
    ...
});

Si cela ne fonctionne pas, modifiez la propriété AuthenticationScheme dans les options du cookie afin qu'elle corresponde à la propriété DefaultAuthenticateScheme dans les options d'authentification.

0
E. Mourits