Closed alphajoza closed 1 year ago
services.AddScoped<IClientFactory>(serviceProvider =>
{
// new CallOptions for each grpc call
CallOptions DefaultCallOptionsFactory()
{
var provider = serviceProvider.GetRequiredService<TokenProviderService>();
var token = provider.GetToken();
var metadata = new Metadata();
if (!string.IsNullOrEmpty(token))
{
metadata.Add("Authorization", token);
}
return new CallOptions(metadata);
}
return new ClientFactory(new ServiceModelGrpcClientOptions
{
DefaultCallOptionsFactory = DefaultCallOptionsFactory
});
});
as an alternative, you can try passing token via the custom HttpClientHandler:
// TokenProviderService lifetime should match GrpcChannel lifetime
services.AddSingleton<TokenProviderService>();
// GrpcChannel lifetime should match TokenProviderService lifetime
services.AddSingleton(provider =>
{
var baseAddress = provider.GetRequiredService<IWebAssemblyHostEnvironment>().BaseAddress;
var tokenProvider = provider.GetRequiredService<TokenProviderService>();
var httpHandler = new GrpcWebHandler(
GrpcWebMode.GrpcWebText,
// inject the handler into the chain
new HttpClientHandlerWithAuthorization(tokenProvider));
return GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions { HttpHandler = httpHandler });
});
// ClientFactory with default options
builder.Services.AddScoped<IClientFactory, ClientFactory>();
internal sealed class HttpClientHandlerWithAuthorization : HttpClientHandler
{
private readonly TokenProviderService _tokenProvider;
public HttpClientHandlerWithAuthorization(TokenProviderService tokenProvider)
{
_tokenProvider = tokenProvider;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// pass the token for each http call
var token = _tokenProvider.GetToken();
if (!string.IsNullOrEmpty(token))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
return base.SendAsync(request, cancellationToken);
}
}
I used an Interceptor
for adding the header, and it worked just fine.
Your solution is working fine too.
thanks.
Context: .net 7.0
My server side is done in asp.net core and the client side is done in Blazer webassembly as following (
Program.cs
):The implementation of
TokenProviderService
is such that it uses theAuthenticationStateProviderService
for setting the various states of authentication (anonymous, authenticated):Obviously, the application (Blazor wasm) starts as a anonymous user and then gets authenticated. My problem is that the process of setting the
Authorization
header is done only once when creating theClientFactory
.How can I make sure that for every grpc request,
GetToken()
gets called or recreate theClientFactory
when authentication state changes (anonymous becomes authenticated)?