Home > Blockchain >  Web API Core JWT Authentication is not working
Web API Core JWT Authentication is not working

Time:05-19

I'm new to writing Web APIs in .NET. I wrote this API which is working fine normally but then I added JWT authentication and now when I provide correct username and password I get an authentication bearer token that I add to swagger UI but now when I try to access any other end point I get this 401 Unauthorized status. I'm unable to understand why. I've also tried this with Postman but same response.

Here is my Program.cs

using System.Text;
using Comply_Api_DotNet.Database;
using Comply_Api_DotNet.Repository;
using Comply_Api_DotNet.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddScoped<IUsersDb, UsersDb>();
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = @"Please provide authorization token to access restricted features.",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement()
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                },

                Scheme = "oauth2",
                Name = "Bearer",
                In = ParameterLocation.Header,
            },
            new List<string>()
        }
    });
});
// ADD JWT Authentication
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    var key = Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]);
    o.SaveToken = true;
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidAudience = builder.Configuration["JWT:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(key)
    };
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

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

app.MapControllers();

app.Run();  

Her is my Controller.

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
    private readonly IAuthenticationService _authenticationService;
    private readonly IUsersDb _usersDb;

    public UsersController(IAuthenticationService authenticationService, IUsersDb usersDb)
    {
        _authenticationService = authenticationService;
        _usersDb = usersDb;
    }

    [AllowAnonymous]
    [HttpPost]
    [Route("authenticate")]
    public IActionResult Authenticate(User user)
    {
        var token = _authenticationService.Authenticate(user);

        if (token == null)
        {
            return Unauthorized();
        }

        return Ok(token);
    }


    // GET api/<UsersController>/5
    [HttpGet]
    public IEnumerable<User> Get(long id)
    {
        var usersFound = _usersDb.GetAllUsers(id);
        return usersFound;
    }

    // POST api/<UsersController>
    [HttpPost]
    public User Post([FromBody] User user)
    {
        var userAdded = _usersDb.AddNewUser(user);
        return userAdded;
    }

    // PUT api/<UsersController>/5
    [HttpPut("{id:long}")]
    public void Put(long id, [FromBody] User user)
    {
        throw new NotImplementedException();
    }


    [HttpDelete("{id:long}")]
    public bool Delete(long id)
    {
        return _usersDb.DeleteUser(id);
    }
} // end of class  

appsettings.Json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "JWT": {
    "Key": "fc746b61cde4f6665d3f9791446cd5395661860c0075a905ed9810b7391af467",
    "Issuer": "Comply",
    "Audience": "comply"
  } 
}

UPDATE: Authentication Service

public class AuthenticationService : IAuthenticationService
{
    private readonly IConfiguration _configuration;
    private readonly IUsersDb _usersDb;

    public AuthenticationService(IConfiguration configuration, IUsersDb usersDb)
    {
        _configuration = configuration;
        _usersDb = usersDb;
    }

    public AuthenticationToken? Authenticate(User user)
    {
        var foundUser = _usersDb.GetAllUsers(0)
            .FirstOrDefault(x => x.Name == user.Name && x.Password == user.Password);
        if (foundUser == null)
        {
            return null;
        }

        //If user found then generate JWT
        return CreateAuthenticationToken(foundUser);
    }

    private AuthenticationToken CreateAuthenticationToken(User user)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var tokenKey = Encoding.UTF8.GetBytes(_configuration["JWT:Key"]);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new(ClaimTypes.Name, user.Name),
            }),

            Expires = DateTime.UtcNow.AddMinutes(10),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenKey),
                SecurityAlgorithms.HmacSha256Signature),
            Issuer = _configuration["JWT:Issuer"],
            Audience = _configuration["JWT:Audience"],
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);

        return new AuthenticationToken()
        {
            Token = tokenHandler.WriteToken(token),
        };
    }
} //end of class

CodePudding user response:

The issue is here Type = SecuritySchemeType.ApiKey, you are specifying security scheme type as apiKey. you need to replace that with Type = SecuritySchemeType.Http,. So, your OpenApiSecurityScheme should now look like this.

c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
    Description = @"Please provide authorization token to access restricted features.",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
    Scheme = "Bearer",
    BearerFormat = "JWT",
});
  • Related