Search code examples
c#authenticationgrpccode-firstblazor-webassembly

Grpc token expiration handling


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

  • 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.