0
votes

I am facing a problem which I can't navigate to the dashboard as I always got Authorization Failed i have used jwt in login and pass all data in claims username and role but I can't check which rules is it in case I stop Authorization it works I need to know where is the error happen this is my login method

 [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            if (ModelState.IsValid)
            {

                var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);


                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");
                    ApplicationUser user = await _userManager.FindByEmailAsync(model.Email);
                    
                    var tokenvalue = createToken(user);


                    if (tokenvalue != null)
                    {
                             HttpContext.Session.SetString("JWToken", tokenvalue);
                    }

                    return RedirectToAction("Index", "DashBoard");

                }
                if (result.RequiresTwoFactor)
                {
                    return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("User account locked out.");
                    return RedirectToAction(nameof(Lockout));
                }
                else
                {
                    ModelState.AddModelError(string.Empty, _localizer["Invalidloginattempt"]);
                    return View(model);
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

my token code is

     public String createToken(ApplicationUser user)
    {

        DateTime issuedAt = DateTime.UtcNow;
        //set the time when it expires
        DateTime expires = DateTime.UtcNow.AddDays(1);

        var tokenHandler = new JwtSecurityTokenHandler();


     ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
     {
            new Claim("UserName", user.UserName),
            new Claim("Id", user.Id),
            new Claim("Role", "Admin"),
    });

        var sec = _configuration["Jwt:Key"];
        var now = DateTime.UtcNow;
        var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
        var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

        var token = (JwtSecurityToken)
            tokenHandler.CreateJwtSecurityToken(issuer: _configuration["Jwt:Issuer"], audience: _configuration["Jwt:Audience"],
                subject: claimsIdentity, notBefore: issuedAt, expires: expires, signingCredentials: signingCredentials);
        var tokenString = tokenHandler.WriteToken(token);

        return tokenString;
    }

and this my startup

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
        app.UseRequestLocalization(options.Value);


        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseSession();

        app.Use(async (context, next) =>
        {
            var JWToken = context.Session.GetString("JWToken");
            if (!string.IsNullOrEmpty(JWToken))
            {
                context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
            }
            await next();
        });

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "areas",
                pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });

    }

my dashboard is

    [Authorize(Roles = "Admin,User")]
    public IActionResult Index()
    {
     
        return View();
    }
1
You might want to go to jwt.io and use it to decode you token and look at the claims. You can get the tokens from the auth header using you F12 developer tools. - GlennSills

1 Answers

1
votes

If the authentication goes well as you said, i think the problem seem to be the role ClaimName. Use the default claim configuration like

Subject = new ClaimsIdentity(new Claim[] 
            {
                new Claim(ClaimTypes.Name, user.Id.ToString()),
                new Claim(ClaimTypes.Role, user.Role)
            }),

The default authorization middleware and the data annotations that you are using are configured to know ClaimTypes.Role instead of custom claim names.

For more details about jwt auth read this : https://jasonwatmore.com/post/2019/10/16/aspnet-core-3-role-based-authorization-tutorial-with-example-api