I'm interested in configuring Identity outside of my source code to make life easier once my application reaches production, however I'm having some problems applying configuration to IdentityOptions in Startup.cs.
I've tried the pattern:
services.Configure<IdentityOptions>(Configuration);
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders()
.AddUserStore<ApplicationUserStore<ApplicationDbContext>>()
.AddRoleStore<RoleStore<ApplicationRole, ApplicationDbContext, Guid>>();
using the following JSON config file:
{
"IdentityOptions": {
"Lockout": {
"MaxFailedAccessAttempts": 10,
"DefaultLockoutTimeSpan": "00:20:00"
}
}
}
but the settings don't seem to be applied. I've only had any success by indexing Configuration directly which feels a bit clunky:
services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
options.Lockout.MaxFailedAccessAttempts = int.Parse(Configuration["Lockout:MaxFailedAccessAttempts"])
)
Is there a way of configurating Identity using the Options Pattern?
Thanks,
Paul
First define 2 new classes:
public class SiteSettings
{
public Identityoptions IdentityOptions { get; set; }
}
public class Identityoptions
{
public LockoutOptions Lockout { get; set; }
}
Then to access SiteSettings from the ConfigureServices method, we should BuildServiceProvider first:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfigurationRoot>(provider => { return Configuration; });
services.Configure<SiteSettings>(options => Configuration.Bind(options));
var provider = services.BuildServiceProvider();
var siteSettingsOptions = provider.GetService<IOptions<SiteSettings>>();
// now use siteSettingsOptions.Value
Tip
An standard TimeSpan value should be defined this way in appsettings.json file:
"DefaultLockoutTimeSpan": "0.00:05:00.0000",
Thanks Vahid,
I think the question was not so much accessing the IConfigurationRoot in ConfigureServices, and more how to avoid explicitly transferring every setting manually into the AddIdentity Action.
I've used your suggestion of Configuration.Bind(options) as follows in ConfigureServices:
services.AddIdentity<ApplicationUser, ApplicationRole>(options => Configuration.Bind(options))
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders()
.AddUserStore<ApplicationUserStore<ApplicationDbContext>>()
.AddRoleStore<RoleStore<ApplicationRole, ApplicationDbContext, Guid>>();
This works nicely and transfers my settings from my JSON config file:
{
"Lockout": {
"MaxFailedAccessAttempts": 5,
"DefaultLockoutTimeSpan": "0.00:05:00.0000"
}
}
@PaulRReynolds @VahidN this usage of Configuration.Bind() in the lambda is pretty cool (cc @HaoK @glennc).
FWIW if your projects includes the Microsoft.Extensions.Options.ConfigurationExtensions package you should be able to use a Configure<T>() overload that takes an IConfiguration directly which I believe looks slightly simpler and should do the same thing, e.g. something like this:
C#
services.Configure<IdentityOptions>(Configuration);
This actually is already what services.Configure<IdentityOptions>(IConfiguration) does (its sugar for bind). The error in your first attempt @PaulRReynolds was that you needed to get to the right section, Configuration.GetSection("IdentityOptions"). That's really all the SiteSettings poco is doing here