How to check if AspNetUser satisfies condition before PasswordSignInAsync?

1.3k Views Asked by At

I've added a new column to AspNetUsers using the way proposed by Microsoft:

public class ApplicationUser : IdentityUser
{
    public bool AdminConfirmed { get; set; }
}

Which means that admin have to confirm user account after registering.

The default way to log in is to do that:

var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
     _logger.LogInformation(1, "User logged in.");
     return RedirectToLocal(returnUrl);
}

But as I see I don't have any possibility to edit the code behind "PasswordSignInAsync". So how can I add another condition that will cause this method to return result.IsNotAllowed if user's account is not confirmed by admin?

I also don't really know how can I get some data about user from database. My DbContext where I store authorization data look like this:

public class AuthorizationDbContext : IdentityDbContext<ApplicationUser>
    {
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
        }
    }

And normally I would use:

public DbSet<SomeModel> SomeData { get; set; }

to access some data. But in case of AspNetUsers table that was generated for me by VisualStudio, I don't have any "c# class model" to put into DbSet. How can I then access user data to tell if his account is for example confirmed by admin?

1

There are 1 best solutions below

3
On

You can override CanSignInAsync(TUser user) method of SignInManager

public class ApplicationSignInManager: SignInManager<User>
{
   public ApplicationSignInManager(UserManager<User> userManager, IHttpContextAccessor contextAccessor,
            IUserClaimsPrincipalFactory<User> claimsFactory, IOptions<IdentityOptions> optionsAccessor,
            ILogger<SignInManager<User>> logger)
            : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger){}

   public override Task<bool> CanSignInAsync(User user)
   {
       if (!user.AdminConfirmed)
           return false;

       return base.CanSignInAsync(user);
   }           
}

Also you need to add the ApplicationSignInManager as services to the services container to make it available within your application via dependency injection.

public void ConfigureServices(IServiceCollection services)
{
       ...    
       services.AddIdentity...
       services.AddScoped<ApplicationSignInManager>();    
}