I'm using grpc code-first for my blazor-wasm app and I can't understand how I should handle token expiration.
As I understand it, I need an client side interceptor that will check the expiration time and make a request to the server to update.
public static WebAssemblyHostBuilder AddGrpc(this WebAssemblyHostBuilder builder)
{
builder.Services
.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient(BaseClient));
builder.Services.AddScoped(services =>
{
var baseAddressMessageHandler = services.GetRequiredService<AuthenticationHeaderHandler>(); // <= adds the authorization header
baseAddressMessageHandler.InnerHandler = new HttpClientHandler(); // <= I tried adding a custom handler, but it didn't work either
var grpcWebHandler = new GrpcWebHandler(GrpcWebMode.GrpcWeb, baseAddressMessageHandler);
var channel = GrpcChannel.ForAddress(builder.HostEnvironment.BaseAddress, new GrpcChannelOptions { HttpHandler = grpcWebHandler });
return channel;
});
return builder;
}
How to solve this problem correctly?
Solution:
builder.Services.AddScoped(services =>
{
var authManager = services.GetRequiredService<IAuthenticationManager>();
var navManager = services.GetRequiredService<NavigationManager>();
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
try
{
await authManager.TryRefreshToken();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
navManager.NavigateTo("/login");
}
});
var baseAddressMessageHandler = services.GetRequiredService<AuthenticationHeaderHandler>();
baseAddressMessageHandler.InnerHandler = new HttpClientHandler();
var grpcWebHandler = new GrpcWebHandler(GrpcWebMode.GrpcWeb, baseAddressMessageHandler);
var channel = GrpcChannel.ForAddress(builder.HostEnvironment.BaseAddress, new GrpcChannelOptions
{
HttpHandler = grpcWebHandler,
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
});
In CallCredentials.FromInterceptor
we can check token and update it.