locked
How to set IdentityOptions Dynamically from database RRS feed

  • Question

  • User818337214 posted

    how to set IdentityOptions Dynamically from database asp.net core 2?

    I can set it statically

    services.Configure<IdentityOptions>(options =>
    {
    // Password settings.
    options.Password.RequireDigit = true; 
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;
    
    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    
    options.Lockout.MaxFailedAccessAttempts = 2;
    options.Lockout.AllowedForNewUsers = true;
    
    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = true;
    });

    But I wanna configure it from database. I have some columns about that.

    var staticSetting = _unitOfWork.StaticSettings.GetAll().FirstOrDefault();
    staticSetting.RequireDigit
    staticSetting.RequireLowercase
    staticSetting.RequireNonAlphanumeric
    staticSetting.RequireUppercase 
    staticSetting.RequiredLength 
    staticSetting.RequiredUniqueChars 
    staticSetting.DefaultLockoutTimeSpanFromMinutes
    staticSetting.MaxFailedAccessAttempts
    staticSetting.AllowedForNewUsers

    how and where can I set it from database?

    Saturday, August 24, 2019 10:45 AM

Answers

  • User711641945 posted

    Hi suat_suphi,

    NullReferenceException: Object reference not set to an instance of an object. 

    You could configure IdentityOptions like below:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
         //...
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<IdentityOptions> identityOptions)
        {
            this.staticSetting = app.ApplicationServices.CreateScope().ServiceProvider
                            .GetRequiredService<ApplicationDbContext>().StaticSettings.FirstOrDefault();
            identityOptions.Value.Password.RequireDigit = staticSetting.RequireDigit;
        }
    }

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, August 27, 2019 4:49 AM

All replies

  • User-474980206 posted

    use closure and assignment:

    var staticSetting = _unitOfWork.StaticSettings.GetAll().FirstOrDefault();
    services.Configure<IdentityOptions>(options =>
    {
       // Password settings.
       options.Password.RequireDigit = staticSetting.RequireDigit; 
       ...
    });
    

    Sunday, August 25, 2019 12:32 AM
  • User818337214 posted

    thank you

    how can I get _unitOfWork. I tried it but I get an error 

        public class Startup
        {
            public IConfiguration Configuration { get; }
            private readonly ILogger _logger;
            private readonly IUnitOfWork _unitOfWork;
      
            public Startup(IConfiguration configuration, ILogger<Startup> logger, IUnitOfWork unitOfWork)
            {
                Configuration = configuration;
                _logger = logger;
                _unitOfWork = unitOfWork;
            }
            public void ConfigureServices(IServiceCollection services, IUnitOfWork unitOfWork)
            {
    ...
            }
    
        }

    InvalidOperationException: Unable to resolve service for type 'Test.Repository.Abstract.IUnitOfWork' while attempting to activate 'Test.WebUI.Startup'.

    Sunday, August 25, 2019 12:55 AM
  • User711641945 posted

    Hi suat_suphi,

    suat_suphi

    InvalidOperationException: Unable to resolve service for type 'Test.Repository.Abstract.IUnitOfWork' while attempting to activate 'Test.WebUI.Startup'.

    You could resolve the IUnitOfWork like below:

    public class Startup
    {
    private StaticSetting staticSetting; public void ConfigureServices(IServiceCollection services) { services.Configure<IdentityOptions>(options => { options.Password.RequireDigit = staticSetting.RequireDigit; //more settings.. }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { this.staticSetting = app.ApplicationServices .GetRequiredService<IUnitOfWork>().StaticSettings.GetAll().FirstOrDefault();
    //... }
    }

    Best Regards,

    Rena

    Monday, August 26, 2019 5:21 AM
  • User818337214 posted

    First step is ConfigureServices... so I get this error 

    NullReferenceException: Object reference not set to an instance of an object. 

    Inoticed that there is a event for ConfigureApplicationCookie, but there is no event for IdentityOptions

    Feature request: https://github.com/aspnet/AspNetCore/issues/13439

                services.ConfigureApplicationCookie(options =>
                {
                    options.EventsType = typeof(CustomCookieAuthenticationEvents);
                });

    I noticed that other one: these settings is necessary for login, register and new password

            [HttpPost]
            [ValidateAntiForgeryToken]
            [ServiceFilter(typeof(ValidateReCaptchaAttribute))]
            public async Task<IActionResult> Login([Bind("LoginInput")][FromForm] AccountModel model, [FromQuery] string returnUrl)
            {
                #region Set IdentityOptions
    
                var staticSettings = _unitOfWork.StaticSettings.GetAll().FirstOrDefault();
                _identityOptions.Value.Lockout = new LockoutOptions
                {
                    AllowedForNewUsers = staticSettings.AllowedForNewUsers,
                    DefaultLockoutTimeSpan = TimeSpan.FromMinutes(staticSettings.DefaultLockoutTimeSpanFromMinutes),
                    MaxFailedAccessAttempts = staticSettings.MaxFailedAccessAttempts
                };
                _identityOptions.Value.Password = new PasswordOptions
                {
                    RequireDigit = staticSettings.RequireDigit,
                    RequiredLength = staticSettings.RequiredLength,
                    RequiredUniqueChars = staticSettings.RequiredUniqueChars,
                    RequireLowercase = staticSettings.RequireLowercase,
                    RequireNonAlphanumeric = staticSettings.RequireNonAlphanumeric,
                    RequireUppercase = staticSettings.RequireUppercase
                };

    #endregion
    ... }

    how can I get or achieve IUnitOfWork in override method ? 

    services.AddScoped<IOptions<IdentityOptions>, CustomIdentityOptions>();

    public class CustomIdentityOptions : IOptions<IdentityOptions>
        {
            public IdentityOptions Value { get; private set; }
            public CustomIdentityOptions()
            {
                Value = new IdentityOptions
                {
                    Lockout = new LockoutOptions
                    {
                        AllowedForNewUsers = true,
                        DefaultLockoutTimeSpan = TimeSpan.FromMinutes(1),
                        MaxFailedAccessAttempts = 1
                    }
                };
            }
        }

    Monday, August 26, 2019 9:19 AM
  • User711641945 posted

    Hi suat_suphi,

    NullReferenceException: Object reference not set to an instance of an object. 

    You could configure IdentityOptions like below:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
         //...
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<IdentityOptions> identityOptions)
        {
            this.staticSetting = app.ApplicationServices.CreateScope().ServiceProvider
                            .GetRequiredService<ApplicationDbContext>().StaticSettings.FirstOrDefault();
            identityOptions.Value.Password.RequireDigit = staticSetting.RequireDigit;
        }
    }

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, August 27, 2019 4:49 AM
  • User818337214 posted

    thank you Rena Ni,

    I noticed that these settings are necessary for login, register and new password.

    so I must use it when it is necessary.

    If I use it in startup, I will get a delay. So I change my logic. 

    Friday, August 30, 2019 9:32 AM