Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AuthorizeAttribute with JWT Token- Authentication in .NET Core 2.0

I implemented a JWT Bearer Token- Authentication in my Web-API that runs with .net core 2.0. Now I created another Website that speaks with my Web-API. Retrieving the token works, I'm adding it into cookies, when I'm debugging I can see my cookie (name is "identity") with the correct value.

In the projects template there is the controller HomeController with the actions. I'm using the action Contact for my purposes and annotate it with the AuthorizeAttribute:

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

    return View();
}

Now I'm navigating (as an anonymous user) to /home/contact - perfect: it redirects me to /home/login where I need to login.

When I'm trying to login I get following error-message:

No IAuthenticationSignInHandler is configured to handle sign in for the scheme: Bearer

I guess the token configuration is wrong- I guess there are a few more things I'm doing wrong here.

First, here is my Startup.cs (I didn't delete anything since there are dependencies on the order):

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?}");
    });
}

and here is my 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;
    }
}
like image 625
Matthias Burger Avatar asked Oct 12 '17 12:10

Matthias Burger


People also ask

How do I authenticate with JWT?

To authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to your backend API. API Gateway validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication.

What is JWT token in .NET core?

JSON Web Tokens (commonly known as JWT) is an open standard to pass data between client and server, and enables you to transmit data back and forth between the server and the consumers in a secure manner. This article talks about how you can take advantage of JWTs to protect APIs.


1 Answers

Here is a blog post on how you can use cookies as a delivery mechanism for your JWTs on ASP.NET Core 2.0, which is what you are trying to do: JWT Token Authentication with Cookies in ASP.NET Core

I have not tried it, but it could guide you on understanding where you could be doing it wrong.

like image 86
Frank Fajardo Avatar answered Oct 19 '22 10:10

Frank Fajardo