Share via

Adding IdentityUser.Enabled

David Thielen 3,231 Reputation points
2023-07-02T19:24:16.7366667+00:00

This is for Blazor (server) using the Identity library. This is what I did to add the property IdentityUser.Enabled. Please let me know if I missed anything.

First the class Ex(tended)IdentityUser:

   public class ExIdentityUser : IdentityUser
    {
        /// <summary>
        /// true if the user is enabled. If false, the user is disabled and should not be allowed to log in.
        /// </summary>
        public bool Enabled { get; set; } = true;

        /// <inheritdoc />
        public ExIdentityUser()
        {
        }

        /// <inheritdoc />
        public ExIdentityUser(string userName) : base(userName)
        {
        }
    }

And next the DbContext:

public class UserDbContext : IdentityDbContext<ExIdentityUser>
{
    public UserDbContext(DbContextOptions options)
        : base(options)
    {
    }
}

Then you need to change IdentityUser to ExIdentityUser everywhere. The two places I found were

Register.cshtml.cs:

	public partial class RegisterModel : PageModel
	{
		private readonly SignInManager<ExIdentityUser> _signInManager;
		private readonly UserManager<ExIdentityUser> _userManager;
		private readonly IUserStore<ExIdentityUser> _userStore;
		private readonly IUserEmailStore<ExIdentityUser> _emailStore;


_LoginPartial.cshtml

@inject SignInManager<ExIdentityUser> SignInManager
@inject UserManager<ExIdentityUser> UserManager

You then need to set this in Program.cs

        builder.Services.AddDefaultIdentity<ExIdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<UserDbContext>();

// ...

		// after AddServerSideBlazor() 		
builder.Services.AddScoped<AuthenticationStateProvider, ExAuthenticationStateProvider>(); 

And then the final key part is an AuthenticationStateProvider that enforces this. If the User.Enabled == false, then it set the authenticated user to anonymous user. The Identity library has no concept of a disabled user so anonymous is the only possibility (I think).

   public class ExAuthenticationStateProvider : ServerAuthenticationStateProvider
    {
        private readonly UserManager<ExIdentityUser> _userManager;

        public ExAuthenticationStateProvider(UserManager<ExIdentityUser> userManager)
        {
            _userManager = userManager;
        }

        /// <inheritdoc />
        public override async Task<AuthenticationState> GetAuthenticationStateAsync()
        {

            // if we're not authenticated, then just return the default
            var authState = await base.GetAuthenticationStateAsync();
            if (authState.User.Identity == null)
            {
                Trap.Break();
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            }

            if ((!authState.User.Identity.IsAuthenticated) || string.IsNullOrEmpty(authState.User.Identity.Name))
                return new AuthenticationState(new ClaimsPrincipal(authState.User.Identity));

            // if the user is not in the database, then just return the default
            ExIdentityUser? user = await _userManager.FindByNameAsync(authState.User.Identity.Name);
            if (user == null)
            {
                Trap.Break();
                return new AuthenticationState(new ClaimsPrincipal(authState.User.Identity));
            }

            // if enabled, we're good
            if (user.Enabled)
                return new AuthenticationState(new ClaimsPrincipal(authState.User.Identity));

            // disabled - so anonymous user (system doesn't have the concept of disabled users)
            var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
            return new AuthenticationState(anonymousUser);
        }
    }

Did I miss anything?

Developer technologies | .NET | Blazor
Developer technologies | ASP.NET Core | Other

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.