I am looking to customise IdentityServer4 to load external identity providers from the database. I would like to extend ConfigurationDBContext to include a DbSet of Saml2Provider. In my startup I'd like to then add the Saml2Provider automatically. Ideally, I would like an easy way for the list of providers available to be refreshed in the idsvr4 login page without having to restart the application.
I have been able to load my Saml2Providers from the DB and register them as external providers. However, this is using the ApplicationDbcontext, and it is not being refreshed on each request to idsvr.
This is my configureServices that is working (using ApplicationDbContext to retrieve providers from the DB):
public void ConfigureServices(IServiceCollection services)
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.Client.Schema = "config";
options.DefaultSchema = "config";
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
})
.AddAspNetIdentity<ApplicationUser>()
.AddProfileService<CustomProfileService>();
......
var context = serviceProvider.GetService<ApplicationDbContext>();
var saml2Providers = context.Saml2Providers.ToList();
foreach(var provider in saml2Providers)
{
provider.RegisterService(services);
}
}
This is my attempt at extending ConfigurationDbContext:
public class IdSrvConfigurationDbContext : ConfigurationDbContext<IdSrvConfigurationDbContext>
{
public DbSet<Saml2Provider> Saml2Providers { get; set; }
public IdSrvConfigurationDbContext(DbContextOptions<IdSrvConfigurationDbContext> options, ConfigurationStoreOptions storeOptions)
:base(options, storeOptions)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//mylogic here
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Saml2Provider>().ToTable("Saml2ProviderConfigContext", schema: "config");
}
}
I am wanting the external providers to be refreshed in the login screen automatically when they are updated in the database. I also want to load the external provider information via the ConfigurationDbContext if possible, as it makes sense to be there.
There are 2 issues extending ConfigurationDbContext:
Migrations don't build correctly:
Unable to create an object of type 'IdSrvConfigurationDbContext'. Add an implementation of 'IDesignTimeDbContextFactory' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
I can't access the extended context from startup correctly. I'm not sure how to wire it up correctly.
I'm sure there is a correct way to wire this up by extending the Identity options builder, but I've no idea how to do this. Any help would be greatly appreciated.