Search code examples
identityserver4

Its is Possible to use .AddOperationalStore for PersistedGrants with .InMemoryResources/Cients?


I would like to store PersistedGrants in the database for the purpose of Azure Scale Out.

I prefer to read IdentityResources/ApiResources/Clients(Config) from appsettings.json rather than from database.

From the How To on IdentityServer4's doc site an example is shown to persist both to database.

Is it possible to not load configuration data into Database while storing Grants? If so how?

This works:

        services.AddIdentityServer((options) =>
        {
            options.UserInteraction = new UserInteractionOptions
            {
                LoginUrl = "/login",
                LogoutUrl = "/api/Account/Logout",
                ErrorUrl = "/error"
            };
        })
       .AddSigningCredential(X509CertificateHelper.getCert(_env))            
       .AddOperationalStore(builder => builder.UseSqlServer(connectionString,
           options => options.MigrationsAssembly(migrationsAssembly)))           
       .AddConfigurationStore(builder => builder.UseSqlServer(connectionString,
           options => options.MigrationsAssembly(migrationsAssembly)))
       .AddAspNetIdentity<ApplicationUser>();

This doesn't. Specifically I cannot run dotnet ef database update -c PersistedGrantDbContext.

        services.AddIdentityServer((options) =>
        {
            options.UserInteraction = new UserInteractionOptions
            {
                LoginUrl = "/login",
                LogoutUrl = "/api/Account/Logout",
                ErrorUrl = "/error"
            };
        })
        .AddSigningCredential(X509CertificateHelper.getCert(_env))           
        .AddOperationalStore(builder => builder.UseSqlServer(connectionString,
            options => options.MigrationsAssembly(migrationsAssembly)))
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients(AppSettingsHelper.GetIdSrvrSettings()))
        .AddAspNetIdentity<ApplicationUser>();

For the latter I get the following error:

An error occurred while calling method 'ConfigureServices' on startup class 'Startup'. Consider using IDbContextFactory to override the initialization of the DbContext at design-time. Error: Cannot perform runtime binding on a null reference


Solution

  • "Is it possible to not load configuration data into Database while storing Grants? If so how?"

    Yes it is. You're using EntityFrame work for your persistence so the info I give may not be fully compatible ... we use something else to manage db persistence.

    Our ConfigureServices looks something like this:

    services.AddIdentityServer(x =>
                {
                    x.IssuerUri = webServerSettings.Host;
                })
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddInMemoryIdentityResources(Config.GetIdentityResources());
    
    services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
    

    In this way our IdentityResources, ApiResources and Clients are pulled in from config files, and our Grants are managed with our own implementation of the IPersistedGrantStore. We're not doing anything special with that interface: it is a very straight-forward interface to implement with only a handful of simple methods to wire up.