locked
Accessing Enum Claim in Login.cshtml.cs page RRS feed

  • Question

  • User1554758465 posted

    I'm developing a web application with ASP.Net Core MVC and identity. I extend the identity table as following with Enum field type "AccountStatusId" as following:

    ApplicationUser.cs

    namespace RegisterTest.Models
    {
        public class ApplicationUser : IdentityUser
        {
    
            public int StatusId { get; set; }
            public string StatusName { get; set; }
            public AccountStatusId AccountStatusId { get; set; }
            public AccountStatus AccountStatus { get; set; }
    
        }
            public enum AccountStatusId : int
            {
                Active = 0,
                InActive = 1,
                Expired = 2,
                Locked = 3
            }
            public class AccountStatus
            {
                public AccountStatusId AccountStatusId { get; set; }
                public string Status { get; set; }
    
                public List<ApplicationUser> Statuses { get; set; }
            }
    }

    and to make sure that the account is locked after successful registration i make the AccountStatusId is locked by default in Register.cshtml.cs

    var user = new ApplicationUser {
                        UserName = Input.Email,
                        Email = Input.Email,
                        AccountStatusId = AccountStatusId.Locked
                   };

    And i did all needed configuration in OnModelCreating method in ApplicationDbContext

    Now, I want to check the "AccountStatus" field but in the Login.cshtml.cs. So, if the user who trying to log in with (AccountStatus.Locked) value -> display a message "Waiting for approval".

    if the value (AccountStatus.Active) -> Successful Login.

    After long search, I think i have to use claim in this situation. So, I come up with the following: 1) Creating customize claim: MyUserClaimsPrincipalFactory.cs

    namespace RegisterTest.Controllers
    {
    
        public class MyUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
        {
            public MyUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor)
                    : base(userManager, optionsAccessor)
            {
            }
            protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
            {
                var identity = await base.GenerateClaimsAsync(user);
                identity.AddEnumClaim("AccountStatus", AccountStatusId.Locked);
                return identity;
            }
        }
    }

    2) Creating AddingEnumClaim class since AddClaim method just accept the string and i need it as Enum.

    AddEnumClaim.cs

    namespace RegisterTest.Controllers
    {
        public static class AddingEnumClaim
        {
            public static void AddEnumClaim<T>(this ClaimsIdentity identity, String type, T enumvalue)
                  where T : struct
            {
                if (!typeof(T).IsEnum)
                    throw new ArgumentException("AddEnumClaim must be an enum");
                identity.AddClaim(new Claim(type, enumvalue.ToString()));
            }
        }
    }

    Now all what i want is to chech the account status here in Login.cshtml.cs page, in OnPostAsync method.

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
            {
                returnUrl = returnUrl ?? Url.Content("~/");
    
                if (ModelState.IsValid)
                {
                    // This doesn't count login failures towards account lockout
                    // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                    var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
    
    
                    if (result.Succeeded)
                    {
                        _logger.LogInformation("User logged in.");
                        return LocalRedirect(returnUrl);
                    }
                    if (result.RequiresTwoFactor)
                    {
                        return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
                    }
                    if (result.IsLockedOut)
                    {
                        _logger.LogWarning("User account locked out.");
                        return RedirectToPage("./Lockout");
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                        return Page();
                    }
                }
    
                // If we got this far, something failed, redisplay form
                return Page();
            }

    Am i in the right track or i miss understanding something? Where i can exactly check the AccountStatus for a user while logging ?

    Any help is appreciated

    Monday, June 8, 2020 9:03 PM

Answers

  • User711641945 posted

    Hi ShahadAlshuhail,

    Check like below:

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
    
        if (ModelState.IsValid)
        {
            var user = _userManager.FindByEmailAsync(Input.Email).Result;
            if(user.AccountStatusId == AccountStatusId.Locked)
            {
                ModelState.AddModelError(string.Empty, "Waits for Approval");
                return Page();
            }
            if(user.AccountStatusId == AccountStatusId.Active)
            {
                var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");
                    return LocalRedirect(returnUrl);
                }
                if (result.RequiresTwoFactor)
                {
                    return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("User account locked out.");
                    return RedirectToPage("./Lockout");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return Page();
                }
            }
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                    
        }
    
        // If we got this far, something failed, redisplay form
        return Page();
    }

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 9, 2020 9:30 AM

All replies

  • User711641945 posted

    Hi ShahadAlshuhail,

    Check like below:

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
    
        if (ModelState.IsValid)
        {
            var user = _userManager.FindByEmailAsync(Input.Email).Result;
            if(user.AccountStatusId == AccountStatusId.Locked)
            {
                ModelState.AddModelError(string.Empty, "Waits for Approval");
                return Page();
            }
            if(user.AccountStatusId == AccountStatusId.Active)
            {
                var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");
                    return LocalRedirect(returnUrl);
                }
                if (result.RequiresTwoFactor)
                {
                    return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("User account locked out.");
                    return RedirectToPage("./Lockout");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return Page();
                }
            }
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                    
        }
    
        // If we got this far, something failed, redisplay form
        return Page();
    }

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 9, 2020 9:30 AM
  • User1554758465 posted

    Thank you so much ! 

    Tuesday, June 9, 2020 9:39 PM