1
votes

I am trying to make WEB API using .NET Core 3.1 and make Client Application that uses that API for all the server stuff. for the Client App I am using ASP .Net Core 3.1 MVC.
On my API I am trying to make JWT Bearer Authentication and Authorization.

JwtAuthenticationService.cs is a class I made to generate Token.

public async Task<String> GenerateJsonWebToken(ApplicationUser appUser)
{
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.Name, appUser.UserName),
        new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
        new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddDays(5)).ToUnixTimeSeconds().ToString())
    };

    var roleNames = await _userManager.GetRolesAsync(appUser);

    foreach (var roleName in roleNames)
    {
        claims.Add(new Claim(ClaimTypes.Role, roleName));
    }
  

    var token = new JwtSecurityToken(
        new JwtHeader(
            new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"])),
            SecurityAlgorithms.HmacSha256)),
        new JwtPayload(claims));
            
    return new JwtSecurityTokenHandler().WriteToken(token);
}

This is my Login controller

public async Task<IActionResult> Login([FromBody] POCOUser pocoUser)
{
    IActionResult response = Unauthorized();

    var appUser = await _userManager.FindByNameAsync(pocoUser.UserName);
    
   
    if ( await _userManager.CheckPasswordAsync(appUser, pocoUser.Password))
    {
        var tokenString = _jwtAuthenticationService.GenerateJsonWebToken(appUser);
        return Ok(new { token = tokenString });
    }

    return response;
}

I managed to determine that the problems is in my TokenValidationParameters

 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
            {
                options.SaveToken = true;
                options.RequireHttpsMetadata = false;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false, // If I change to true it stops working
                    ValidateAudience = false, // if I change to true it stops working.
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration["Jwt:Issuer"],
                    ValidAudience = Configuration["Jwt:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"])),
                    ClockSkew = TimeSpan.Zero
                };
            });

When I change to true of these parameters ValidateIssuer or ValidateAudience the API does not give me access to the controller and redirects me.

This is my appsettings.json

"Jwt": {
    "SecretKey": "SomeSecretKey",
    "Issuer": "https://localhost:44393/",
    "Audience": "https://localhost:44301/"
  },
2

2 Answers

0
votes

When I change to true of these parameters ValidateIssuer or ValidateAudience the API does not give me access to the controller and redirects me.

Because there is no Issuer and Audience in the generated token.

If you want to change to the true of ValidateIssuer or ValidateAudience,change like below:

var token = new JwtSecurityToken(_config["Jwt:Issuer"],
    _config["Jwt:Audience"],
    claims: claims,
    expires: DateTime.Now.AddDays(5),
    signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"])),
        SecurityAlgorithms.HmacSha256));
1
votes

You must include the token when you call that endpoint because it is now protected. You can either get your token in your browser's localstorage or cookies depending on how you store it.

Then place your token here:

enter image description here

Add [Authorize(AuthenticationSchemes = "Bearer")] on top of your Login controller to check headers with Bearer tokens.