Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of ConfigurationDbContext in IndetityServer4 from different API's

After solving my initial problem with adding UserManager to an API (User creation with IdentityServer4 from multiple API's) that does not initialize IdentityServer4 (which in turn is initialized inside a web app only responsible for registration and login of users) I have run to another problem. From the same API I wish to also get the Clients and Resources from the IConfigurationDbContext of IdentityServer4.

What I am trying so far is the following: I am adding the ConfigurationDbContext in the startup of the API and then through the ClientsController and ClientsRepository I am trying to access the clients as shown below.

Startup.cs

 services.AddDbContext<ApplicationDbContext>(options =>
        options.UseNpgsql(defaultConnection, db => db.MigrationsAssembly("XXXXXXX"))
    );

 services.AddDbContext<ConfigurationDbContext>(options =>
        options.UseNpgsql(defaultConnection, db => db.MigrationsAssembly("XXXXXXXX"))
    );

  services.AddIdentityCore<ApplicationUser>(options => {
        options.Password.RequireNonAlphanumeric = false;
    });
    new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole), services)
        .AddRoleManager<RoleManager<IdentityRole>>()
        .AddSignInManager<SignInManager<ApplicationUser>>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

ClientsRepository.cs (in .DataAccess):

private readonly IConfigurationDbContext _context;
public bool AutoSaveChanges { get; set; } = true;

public ClientRepository(IConfigurationDbContext context)
{
    _context = context;
}

public Task<Client> GetClientAsync(int id)
{
    return _context.Clients
        .Include(x => x.AllowedGrantTypes)
        .Include(x => x.RedirectUris)
        .Include(x => x.PostLogoutRedirectUris)
        .Include(x => x.AllowedScopes)
        .Include(x => x.ClientSecrets)
        .Include(x => x.Claims)
        .Include(x => x.IdentityProviderRestrictions)
        .Include(x => x.AllowedCorsOrigins)
        .Include(x => x.Properties)
        .Where(x => x.Id == id)
            .SingleOrDefaultAsync();
 }

However, I am getting the following error:

System.InvalidOperationException: Unable to resolve service for type 'IdentityServer4.EntityFramework.Interfaces.IConfigurationDbContext' while attempting to activate 'XXXXXX.Data.Repositories.ClientRepository'. 

I am guessing it has again to do something with the services Startup, but I cannot seem to find it.

Has anyone solved something similar?

Best, Marios.

like image 666
mkanakis Avatar asked Feb 08 '19 10:02

mkanakis


1 Answers

Just use the ServicesCollection extensions that are already in the IDS4.EFCore package if you want to use these:

        services.AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder => builder.UseNpgsql(defaultConnection, db => db.MigrationsAssembly("XXXXXXXX"));
        });

This will add you the IConfigurationDbContext so that it can later be used in other services through DI.

Use the below static methods if you want to add it directly to the ServicesCollection:

    public static IServiceCollection AddConfigurationStore(this IServiceCollection services,
        Action<ConfigurationStoreOptions> storeOptionsAction = null)
    {
        return services.AddConfigurationStore<ConfigurationDbContext>(storeOptionsAction);
    }

    public static IServiceCollection AddConfigurationStore<TContext>(this IServiceCollection services,
    Action<ConfigurationStoreOptions> storeOptionsAction = null)
    where TContext : DbContext, IConfigurationDbContext
    {
        var options = new ConfigurationStoreOptions();
        services.AddSingleton(options);
        storeOptionsAction?.Invoke(options);

        if (options.ResolveDbContextOptions != null)
        {
            services.AddDbContext<TContext>(options.ResolveDbContextOptions);
        }
        else
        {
            services.AddDbContext<TContext>(dbCtxBuilder =>
            {
                options.ConfigureDbContext?.Invoke(dbCtxBuilder);
            });
        }
        services.AddScoped<IConfigurationDbContext, TContext>();

        return services;
    }
like image 148
Vidmantas Blazevicius Avatar answered Oct 25 '22 11:10

Vidmantas Blazevicius