I am having a 401
error code when I access to the api using Jquery Ajax.
This is my front-end code:
$(document).ready(function() { $("#submit").click(function(e) { debugger let payLoad = JSON.stringify({ Username: $("#username").val(), Password: $("#password").val() }); console.log(payLoad) $.ajax({ headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, type: "POST", url: "https://localhost:44342/api/Authenticate/login", data: payLoad, dataType: "json", success: function(result) { console.log('ok') debugger if (result != "Error") { console.log('Authenticated'); CallAPI(result); } else { console.log('Invalid username or password'); } }, error: function(req, status, error) { debugger alert(error); } }); }); function CallAPI(token) { debugger $.ajax({ url: 'https://localhost:44342/api/Customers', headers: { Authorization: 'Bearer ' + token }, contentType: "application/json", dataType: 'json', success: function(result) { console.log(result) }, error: function(error) { console.log(error); } }) }
For my back-end, I am using ASP.NET Identity
[HttpPost] [Route("login")] public async Task<IActionResult> Login([FromBody] LoginModel model) { var user = await userManager.FindByNameAsync(model.Username); if (user != null && await userManager.CheckPasswordAsync(user, model.Password)) { var userRoles = await userManager.GetRolesAsync(user); var authClaims = new List<Claim> { new Claim(ClaimTypes.Name, user.UserName), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), }; foreach (var userRole in userRoles) { authClaims.Add(new Claim(ClaimTypes.Role, userRole)); } var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"])); var token = new JwtSecurityToken( issuer: _configuration["JWT:ValidIssuer"], audience: _configuration["JWT:ValidAudience"], expires: DateTime.Now.AddHours(3), claims: authClaims, signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256) ); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token), expiration = token.ValidTo }); } return Unauthorized(); } [Authorize] [Route("api/[controller]")] [ApiController] public class CustomersController : ControllerBase { private readonly ApplicationContext _context; public CustomersController(ApplicationContext context) { _context = context; } // GET: api/Customers [HttpGet] public async Task<ActionResult<IEnumerable<Customer>>> GetCustomer() { return await _context.Customer.ToListAsync(); } }
and my startup.cs code is
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); // For Identity services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); // Adding Authentication services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }) // Adding Jwt Bearer .AddJwtBearer(options => { options.SaveToken = true; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidateAudience = true, ValidAudience = Configuration["JWT:ValidAudience"], ValidIssuer = Configuration["JWT:ValidIssuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"])) }; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
I have tested. Without [Authorize]
attribute, I can see the result response at the client side. But once I have added [Authorize]
attribute and added headers
property in CallAPI
method, it hits 401
. I have tested https://localhost:44342/api/Authenticate/login
and it works as expected. It returns the token. But when I use the token to call ‘https://localhost:44342/api/Customers’, it hits 401
Advertisement
Answer
But once I have added [Authorize] attribute and added headers property in CallAPI method, it hits 401.
Based on the code of Startup.cs
that you shared, we can find that you configured multiple authentication mechanisms in your project.
As we discussed in comments, we can specify the authentication scheme (or schemes) with the [Authorize]
attribute they depend on to authenticate the user.
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
For more information about selecting the scheme with the Authorize attribute, please check this doc: