I have Blazor server app to use Identity Server 4 for authentication and authorization purposes. And, I have a protected api (JWT token) to provide data to Blazor server app.
I have followed this post to get access token and pass it to HttpClient
during service registration as below,
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAntDesign();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<TokenProvider>(); <--
ApplicationInitializer.Initialize(Configuration, services);
}
ApplicationInitializer.cs
public static class ApplicationInitializer
{
public static void Initialize(IConfiguration configuration, IServiceCollection services)
{
var installers = typeof(Startup).Assembly.ExportedTypes
.Where(w => typeof(IInstaller).IsAssignableFrom(w) && !w.IsInterface && !w.IsAbstract)
.Select(Activator.CreateInstance)
.Cast<IInstaller>()
.ToList();
installers.ForEach(installer => installer.InstallServices(services, configuration));
}
}
ServiceCollectionRegistration.cs
public class ServiceCollectionRegistration : IInstaller
{
public void InstallServices(IServiceCollection services, IConfiguration configuration)
{
//Register api (NSwag generated) clients with HttpClient from HttpClientFactory
var apiOptions = new ApiOptions();
configuration.GetSection(nameof(ApiOptions)).Bind(apiOptions);
services.AddHttpClient("api", (provider, client) =>
{
client.BaseAddress = new Uri(apiOptions.ApiUrl);
//This is not working as expected. Access Token is always null
var tokenProvider = services.BuildServiceProvider().GetRequiredService<TokenProvider>();
var accessToken = tokenProvider.AccessToken;
if (accessToken != null)
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
});
var asm = Assembly.GetExecutingAssembly();
var interfaces = asm.GetInterfaces();
foreach (var interfaceType in interfaces.Where(x => x.Name.EndsWith("Client")))
{
var currentInterfaceType = interfaceType;
var implementations = asm.GetImplementationsOfInterface(interfaceType);
implementations.ToList().ForEach(i =>
{
services.AddScoped(currentInterfaceType, ctx =>
{
var clientFactory = services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();
var httpClient = clientFactory.CreateClient("api");
return Activator.CreateInstance(i, httpClient);
});
});
}
//Register all provider type to their interface type using reflection
foreach (var interfaceType in interfaces.Where(x => !x.Name.EndsWith("Client")))
{
var currentInterfaceType = interfaceType;
var implementations = asm.GetImplementationsOfInterface(interfaceType);
if (implementations.Count > 1)
implementations.ToList().ForEach(i => services.AddScoped(currentInterfaceType, i));
else
implementations.ToList().ForEach(i => services.AddScoped(currentInterfaceType, i));
}
new AutoMapperConfiguration().RegisterProfiles(services);
}
}
I am unable to assign access token to HttpClient
object since it was null always. Did I miss anything?