I am trying to create a basic WebApp in .NET 5 using Identity. I implemented Database, Repos, API, etc., and Identity(extended) without a problem. Now, I want to implement a login system using cookies and IdentityRole.
I am using signInManager.PasswordSignIn to sign in the user and I got a cookie without a problem. But when I try to request an Authorized call from the controller I am redirected to the login path even though the user has the role specified in the [Authorize] annotation.
Here you can see the cookie I get after requesting signin and I can get all users because there is no [Authorize] annotation on that request.
But when I try to access a specific user I get 401 because GetUser(id) has [Authorize(Roles = "User")] as an annotation even though my user has a "User" role.
Id of FirstUser and UserId in UserRoles matches, so I am not logged in on wrong user
What am I doing wrong?
Startup.cs
//ConfigureServices
services.AddIdentity<User, IdentityRole>(config => {
config.SignIn.RequireConfirmedEmail = false;
})
.AddEntityFrameworkStores<FoodDonationContext>()
.AddDefaultTokenProviders();
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));
services.ConfigureApplicationCookie(options =>
{
options.AccessDeniedPath = "/TEST1"; //These TEST redirections are for debbugging
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = new TimeSpan(1, 0, 0);
options.LoginPath = "/TEST2";
options.LogoutPath = "/TEST3";
options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
};
});
//Configure
app.UseRouting();
app.UseHttpsRedirection();
app.UseCors("MyPolicy");
app.UseCookiePolicy(new CookiePolicyOptions
{
Secure = CookieSecurePolicy.None
});
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
UserController.cs
[Route("api/[controller]")]
[ApiController]
public class UserController : Controller
{
private readonly IUserRepo _repository;
private readonly IMapper _mapper;
private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
public UserController(IUserRepo repository, IMapper mapper, UserManager<User> userManager, SignInManager<User> signInManager)
{
_repository = repository;
_mapper = mapper;
_userManager = userManager;
_signInManager = signInManager;
}
[HttpPost("signin")]
public async Task<ActionResult> SignInUser(UserSignInDTO signInData)
{
var user = await _repository.GetUserWithUserNameAsync(signInData.UserName);
if (user != null)
{
var result = await _signInManager.PasswordSignInAsync(user, signInData.Password, false, false);
if (result.Succeeded)
{
RedirectToRoute("/TEST5");
return Ok(result);
}
else
return BadRequest();
}
return NotFound();
}
[Authorize(Roles = "User")]
[HttpGet("{id}", Name = "GetUser")]
public async Task<ActionResult<UserReadDTO>> GetUser(string id)
{
var user = await _repository.GetUserAsync(id);
if (user != null)
{
user.Age = DateTime.Now.Subtract(user.BirthdayDate).Days / 365;
_repository.SaveChangesAsync();
return Ok(_mapper.Map<UserReadDTO>(user));
}
return NotFound();
}
[HttpGet(Name = "GetAllUsers")]
public async Task<ActionResult<IEnumerable<UserReadDTO>>> GetAllUsers()
{
var userList = await _repository.GetAllUsersAsync();
if (userList != null)
{
foreach (var user in userList) {
user.Age = DateTime.Now.Subtract(user.BirthdayDate).Days / 365;
}
_repository.SaveChangesAsync();
return Ok(_mapper.Map<IEnumerable<UserReadDTO>>(userList));
}
return NotFound();
}
}
CodePudding user response:
app.UseAuthorization();
app.UseAuthentication();
It worked when I changed the order of these two.