Instead of using ConfigurationDbContext directly, there's a handy interface in the IdentityServer project that's more abstract: namely IClientStore. This interface itself contains a single function: FindClientByIdAsync, which can be used for obtaining a Client. Client includes a number of properties, including:
- ClientName
- LogoUri
- Properties
You can get an instance of IClientStore using DI (I expect you're already doing this for ConfigurationDbContext). Once you have this, just call FindClientByIdAsync accordingly:
var yourClient = await clientStore.FindClientByIdAsync(clientId);
When using this approach, Properties will be populated, as expected.
In order to explain why your original approach isn't giving the expected results, we need to understand how Entity Framework Core handles loading related data. Simply put, when retrieving a Client entity (this a different Client class to that I've used above), the navigation properties (e.g. Properties) are not populated by default, which is why you see null. I strongly recommend that you read the Loading Related Data docs if you're more interested in how this works.
The Entity Framework Core implementation of IClientStore (ClientStore) handles this loading of related data for you. Here's a code snippet from the source itself:
public Task<Client> FindClientByIdAsync(string clientId)
{
var client = _context.Clients
// ...
.Include(x => x.Properties)
.FirstOrDefault(x => x.ClientId == clientId);
var model = client?.ToModel();
return Task.FromResult(model);
}
The Include(x => x.Properties) is what takes care of fetching the Properties from the database.