Open Closed

Customize SignInManager (Override) #1843


User avatar
0
lalitChougule created
  • ABP Framework version: v4.3.1
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no / yes
  • Exception message and stack trace:
  • Steps to reproduce the issue:"

I want to perform some check for the user before loggin in. If user pass those check user should be able to login or else throw some validation error.

What is the better approach for this requirement ?

I tried implementing IUserValidator but its not working as per expected.

There is already another ticket going on with 2 different topic so creating this ticket for this topic https://support.abp.io/QA/Questions/1826/Customizing-Application-Modules-Extending-User-Entity-ie-ApbUsers#answer-3ac227f1-8d97-2c1e-25c5-39fef082cb09


11 Answer(s)
  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    You can examine this document to see how you can create a CustomSigninManager.

    And after you've created CustomSigninManager, you can override the SignInAsync method and implement your logic.

    Don't forget to register your CustomSigninManager => https://docs.abp.io/en/abp/2.9/How-To/Customize-SignIn-Manager#register-to-dependency-injection

  • User Avatar
    0
    lalitChougule created

    You can examine this document to see how you can create a CustomSigninManager.

    And after you've created CustomSigninManager, you can override the SignInAsync method and implement your logic.

    Don't forget to register your CustomSigninManager => https://docs.abp.io/en/abp/2.9/How-To/Customize-SignIn-Manager#register-to-dependency-injection

    But this is for v2.9 right ? My project is on v4.3.1 And on gitHub as well I was not able to find SignInManager code, If u can provide github source code for SignInManager it will be helpful.

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    You can inherit from AbpSignInManager and override the PasswordSignInAsync method.

    https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Overriding-Services#overriding-a-service-class

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(AbpSignInManager))]
    public class MyCustomSignInManager : AbpSignInManager 
    {
        public async override Task<SignInResult> PasswordSignInAsync(string userName, string password,
            bool isPersistent, bool lockoutOnFailure)
        {
            //your logic
        }
    }
    
  • User Avatar
    0
    lalitChougule created

    Hi EngincanV,

    Not able to use AbpSignInManager Do I need to install any nuget package for this ?

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Do you use separated identity server? If you use, you can add the .IdentityServer project's reference to the project (SCV.Litmus.LitmusIdentity)

    Don't forget to add DependsOn.

  • User Avatar
    0
    lalitChougule created

    Hi EngincanV,

    I implemented custom signInManager, I registered it in PreConfigureServices as well but its not working. PasswordSignInAsync : My debugger doesn't even hit this method. And user was able to login.

    Not sure where it went wrong.

    My Code :

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(AbpSignInManager))]
    public class LitmusSiginManager : AbpSignInManager
    {
        private readonly IRepository<AppUser, Guid> _appUserRepository;
    
        public LitmusSiginManager(IdentityUserManager userManager,
            IHttpContextAccessor contextAccessor,
            IUserClaimsPrincipalFactory<Volo.Abp.Identity.IdentityUser> claimsFactory,
            IOptions<IdentityOptions> optionsAccessor,
            ILogger<SignInManager<Volo.Abp.Identity.IdentityUser>> logger,
            IAuthenticationSchemeProvider schemes,
            IUserConfirmation<Volo.Abp.Identity.IdentityUser> confirmation,
            IOptions<AbpIdentityOptions> options,
            IRepository<AppUser, Guid> appUserRepository
            ) : base(userManager,
                contextAccessor,
                claimsFactory,
                optionsAccessor,
                logger,
                schemes,
                confirmation,
                options)
        {
            _appUserRepository = appUserRepository;
        }
    
        public override async Task<SignInResult> PasswordSignInAsync(Volo.Abp.Identity.IdentityUser user, string password, bool isPersistent, bool lockoutOnFailure)
        {
            var appUser = await _appUserRepository.FirstOrDefaultAsync(x => x.Id == user.Id);
    
            if (appUser != null)
            {
                if (appUser.Status == AbpUserStatusEnum.InActive)
                    throw new AbpAuthorizationException("User is in InActive state.");
            }
    
            return base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure).Result;
        }
    }
    

    IdentityServerModule :

    public class LitmusIdentityServerModule : AbpModule
    {
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            PreConfigure<IdentityBuilder>(identityBuilder =>
            {
                identityBuilder.AddSignInManager<LitmusSiginManager>();
            });
        }
    }
    

    Can you tell me what is wrong ?

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Can you also expose SignInManager<IdentityUser> as below?

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(AbpSignInManager), typeof(SignInManager<IdentityUser>))]
    public class LitmusSiginManager : AbpSignInManager 
    {
        public override Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
        {
            //your logic
            return base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure);
        }
    
        public override Task<SignInResult> PasswordSignInAsync(IdentityUser user, string password, bool isPersistent, bool lockoutOnFailure)
        {
            //your logic
            return base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
        }
    }
    
  • User Avatar
    0
    lalitChougule created

    typeof(SignInManager<IdentityUser>)

    Hi, Even with this its not working

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer
    [Dependency(ReplaceServices = true)] 
    [ExposeServices(typeof(AbpSignInManager), typeof(SignInManager<IdentityUser>))] 
    public class LitmusSiginManager : AbpSignInManager 
    { 
        private readonly IRepository<AppUser, Guid> _appUserRepository; 
     
        public LitmusSiginManager(IdentityUserManager userManager, 
            IHttpContextAccessor contextAccessor, 
            IUserClaimsPrincipalFactory<Volo.Abp.Identity.IdentityUser> claimsFactory, 
            IOptions<IdentityOptions> optionsAccessor, 
            ILogger<SignInManager<Volo.Abp.Identity.IdentityUser>> logger, 
            IAuthenticationSchemeProvider schemes, 
            IUserConfirmation<Volo.Abp.Identity.IdentityUser> confirmation, 
            IOptions<AbpIdentityOptions> options, 
            IRepository<AppUser, Guid> appUserRepository 
            ) : base(userManager, 
                contextAccessor, 
                claimsFactory, 
                optionsAccessor, 
                logger, 
                schemes, 
                confirmation, 
                options) 
        { 
            _appUserRepository = appUserRepository; 
        } 
     
        public override async Task<SignInResult> PasswordSignInAsync(Volo.Abp.Identity.IdentityUser user, string password, bool isPersistent, bool lockoutOnFailure) 
        { 
            var appUser = await _appUserRepository.FirstOrDefaultAsync(x => x.Id == user.Id); 
     
            if (appUser != null) 
            { 
                if (appUser.Status == AbpUserStatusEnum.InActive) 
                    throw new AbpAuthorizationException("User is in InActive state."); 
            } 
     
            return base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure).Result; 
        } 
    } 
    

    IdentityServerModule :

    public class LitmusIdentityServerModule : AbpModule 
    { 
        public override void PreConfigureServices(ServiceConfigurationContext context) 
        { 
            PreConfigure<IdentityBuilder>(identityBuilder => 
            { 
                identityBuilder.AddSignInManager<LitmusSiginManager>(); 
            }); 
        } 
    } 
    

    Can you move the related changes to your separated identity module? And also can you check the IdentityUser's namespace? It is important to use Volo.Abp.Identity.IdentityUser type for SignInManager.

  • User Avatar
    0
    lalitChougule created

    Hi,

    I have already implemented it in seperate identity project

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(AbpSignInManager), typeof(SignInManager<Volo.Abp.Identity.IdentityUser>))]
    public class LitmusSiginManager : AbpSignInManager
    {
        private readonly IRepository<AppUser, Guid> _appUserRepository;
    
        public LitmusSiginManager(IdentityUserManager userManager,
            IHttpContextAccessor contextAccessor,
            IUserClaimsPrincipalFactory<Volo.Abp.Identity.IdentityUser> claimsFactory,
            IOptions<IdentityOptions> optionsAccessor,
            ILogger<SignInManager<Volo.Abp.Identity.IdentityUser>> logger,
            IAuthenticationSchemeProvider schemes,
            IUserConfirmation<Volo.Abp.Identity.IdentityUser> confirmation,
            IOptions<AbpIdentityOptions> options,
            IRepository<AppUser, Guid> appUserRepository
            ) : base(userManager,
                contextAccessor,
                claimsFactory,
                optionsAccessor,
                logger,
                schemes,
                confirmation,
                options)
        {
            _appUserRepository = appUserRepository;
        }
    
        public override async Task<SignInResult> PasswordSignInAsync(Volo.Abp.Identity.IdentityUser user, string password, bool isPersistent, bool lockoutOnFailure)
        {
            var appUser = await _appUserRepository.FirstOrDefaultAsync(x => x.Id == user.Id);
    
            if (appUser != null)
            {
                if (appUser.Status == AbpUserStatusEnum.InActive)
                    throw new AbpAuthorizationException("User is in InActive state.");
            }
    
            return base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure).Result;
        }
    }
    

    Actually I need to work when I log in from angular. I tried as per you gif to login via https://localhost:44350/Account/Login But I am getting this error :

    "Status" is the extra column I added to AbpUsers table : reference https://support.abp.io/QA/Questions/1826/Customizing-Application-Modules-Extending-User-Entity-ie-ApbUsers When I do this same logic in some application layer it works fine. I don't understand why I am getting this error here

    Note : My debugger was not hit for method PasswordSignInAsync()

  • User Avatar
    1
    maliming created
    Support Team Fullstack Developer

    hi Add ServiceLifetime.Scoped to DependencyAttribute.

    [Dependency(ServiceLifetime.Scoped, ReplaceServices = true)]
    [ExposeServices(typeof(AbpSignInManager), typeof(SignInManager<Volo.Abp.Identity.IdentityUser>))]
    public class LitmusSignInManager : AbpSignInManager
    
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11