Reputation: 253
I've created a simple application and will register and getAccess token with asp.net core Identity.
I can get accesstoken but when I try to call the endpoint I get 404 error code.
Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var appConfiguration = builder.Configuration;
builder.Services.AddDependencies(appConfiguration);
//JWT Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
});
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores<PracticalTestWriteDbContext>()
.AddDefaultTokenProviders();
builder.Services.AddAuthorization();
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();
UserController.cs
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace PracticalTest.Endpoint.Controllers;
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
//For admin Only
[HttpGet]
[Route("Admins")]
[Authorize(Roles = "Admin")]
public IActionResult AdminEndPoint()
{
var currentUser = GetCurrentUser();
return Ok($"Hi you are an {currentUser.Role}");
}
private UserModel GetCurrentUser()
{
var identity = HttpContext.User.Identity as ClaimsIdentity;
if (identity != null)
{
var userClaims = identity.Claims;
return new UserModel
{
UserName = userClaims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value,
Role = userClaims.FirstOrDefault(x => x.Type == ClaimTypes.Role)?.Value
};
}
return null;
}
}
public class UserModel
{
public string UserName { get; set; }
public string Role { get; set; }
}
If I remove builder.Services.AddIdentity<IdentityUser, IdentityRole> then my controller will work, but I need to get the user from usermanager, and then generate the token and use it in my UserController.
here is the get access token process:
[HttpPost]
[Route("AccessToken")]
public async Task<IActionResult> AccessToken([FromBody] LoginCredential? credential)
{
if (!ModelState.IsValid || credential == null)
{
return new BadRequestObjectResult(new { Message = "Login failed" });
}
var identityUser = await _userManager.FindByEmailAsync(credential.Email);
var roles = await _userManager.GetRolesAsync(identityUser);
if (identityUser == null)
{
return new BadRequestObjectResult(new { Message = "Login failed" });
}
var result =
_userManager.PasswordHasher.VerifyHashedPassword(identityUser, identityUser.PasswordHash,
credential.Password);
if (result == PasswordVerificationResult.Failed)
{
return new BadRequestObjectResult(new { Message = "Login failed" });
}
var accessToken = GenerateToken(credential, roles.ToList());
return Ok(new { AccessToken = accessToken });
}
private string GenerateToken(LoginCredential user,List<string> roles)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new List<Claim>()
{
new (ClaimTypes.Email,user.Email)
};
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
var token = new JwtSecurityToken(_config["Jwt:Issuer"],
_config["Jwt:Audience"],
claims,
expires: DateTime.Now.AddMinutes(15),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Upvotes: 0
Views: 1643
Reputation: 425
I got the same error, and solved this problem by using;
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
If you don't want to use this, change your code with this;
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
I solved my problem with this. I hope this helps.
Upvotes: 2