Invalid jwt Token in asp.net core

Viewed 774

I am trying to use a JWT in my Angular application and ASP.net core. For starters, I am using "Postman" to test my end points. In my API this is how I set up the JWT

launchsettings.json

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:22468",
      "sslPort": 0
    }
  },
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "ancmHostingModel": "InProcess"
    },
    "autosweeprfid_api": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:5000"
    }
  }
}

appsettings.json

"Jwt": {
    "SecretKey": "KqcL7s998JrfFHRP1",
    "Issuer": "http://localhost:22468",
    "Audience": "http://localhost:4201"
  }

startup.cs => ConfigureServices

 // Get the Validators in appsettings
            var validIssuer = Configuration["Jwt:Issuer"];
            var validAudience = Configuration["Jwt:Audience"];

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
               .AddJwtBearer(options =>
               {
                   options.TokenValidationParameters = new TokenValidationParameters
                   {
                       ValidateIssuer = true,
                       ValidateAudience = false,
                       ValidateLifetime = true,
                       ValidateIssuerSigningKey = true,

                       ValidIssuer = validIssuer,
                       ValidAudience = validAudience,
                       IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"]))

                   };
               });

startup => Configure

 app.UseCors("MyPolicy");

            // Make the "PrivateImages" forlder servable
            app.UseStaticFiles();
            app.UseStaticFiles(new StaticFileOptions()
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"PrivateImages")),
                RequestPath = new PathString("/PrivateImages")
            });

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapHub<MessageHub>("/MessageHub");
            });

AuthorizationController

[HttpPost, Route("login")]
        public IActionResult Login([FromBody] LoginModelDto model)
        {
            IActionResult response = Unauthorized();

            User user = context.Users.SingleOrDefault(x => x.UserName == model.UserName);

            if (user == null) return response;
            if (!user.IsActive) return response;

            var decryptedPassword = Decryption.Decrypt(user.Password, user.SaltValue);
            if (decryptedPassword == model.Password)
            {
                var roles = (from a in context.UserRoles
                             join b in context.Roles on a.RoleId equals b.Id into ab
                             from x in ab.DefaultIfEmpty()
                             where a.UserId == user.Id
                             select new Role
                             {
                                 RoleName = x.RoleName,
                             }).ToList();

                var claims = new List<Claim>
                {
                    new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Sub, user.UserName),
                    new Claim("UserId", user.Id.ToString()),
                    new Claim("FirstName", user.FirstName.ToString()),
                    new Claim("MiddleName", user.MiddleName.ToString()),
                    new Claim("LastName", user.LastName.ToString()),
                    new Claim("EmailAddress", user.EmailAddress.ToString()),
                    new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                };

                foreach (var role in roles)
                {
                    //claims.Add(new Claim(ClaimTypes.Role, role.RoleName));
                    claims.Add(new Claim("role", role.RoleName));
                }

                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:SecretKey"]));
                var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

                var tokeOptions = new JwtSecurityToken(
                        issuer: "http://localhost:22468",
                        audience: "http://localhost:4201",
                        claims: claims,
                        expires: DateTime.Now.AddMinutes(30),
                        signingCredentials: signinCredentials
                    );
                var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);

                user.Online = true;
                context.SaveChanges();

                return Ok(new { Token = tokenString });
            }
            else
            {
                return response;
            }
        }

I can login just fine, but when I try to consume a method that has an attribute of [Authorize], Postman gives me a 401.

enter image description here

2 Answers

You have just configured authorization inside of your pipeline. You need to configure authentication as well. And remember it has to be done prior to authorization inside of the pipeline. Order matters because first we need to authenticate on who the user is and then we need to check what permissions he/she has.

app.UseRouting();

app.UseAuthentication(); //Authentication

app.UseAuthorization(); //Authorization

I got it. All codes are correct. I just missed using the "authentication" itself. So I just placed the line app.UseAuthentication(); between app.UseRouting(); and app.UseAuthorization(); and it went good. Thank you.

Related