I have a grpc server hosted in a Windows Service based on the grpc sample Greeter.
Server Code:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseWindowsService(options =>
{
options.ServiceName = "WindowsGreeter8";
});
builder.WebHost.ConfigureKestrel(kestrel =>
{
kestrel.Listen(IPAddress.Any, 7042, listenOptions =>
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly);
X509Certificate2Collection cers = store.Certificates.Find(X509FindType.FindByIssuerName, "acme.com", false);
X509Certificate2Collection serverCers = store.Certificates.Find(X509FindType.FindByIssuerName, "localhost", false);
if ((cers.Count > 0) && (serverCers.Count > 0))
{
listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2;
listenOptions.UseHttps(serverCers[0], options =>
{
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
options.ClientCertificateValidation = (certificate, chain, errors) => certificate.Issuer == cers[0].Issuer;
options.SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12;
});
}
});
});
// Add services to the container.
builder.Services.AddGrpc();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
app.Run();
The server requires the client to have a specific certificate.
Client code:
var handler = new HttpClientHandler();
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly);
X509Certificate2Collection cers = store.Certificates.Find(X509FindType.FindByIssuerName, "acme.com", false);
if (cers.Count > 0)
{
Console.WriteLine("Found Certificate");
handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12;
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(cers[0]);
handler.UseProxy = false;
}
using var channel = GrpcChannel.ForAddress("https://localhost:7042", new GrpcChannelOptions()
{
HttpHandler = handler,
DisposeHttpClient = true
});
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
If the client is run as admin the grpc call works correctly.

However, if it is not run with admin rights the SSL connection fails with the exception: System.ComponentModel.Win32Exception (0x8009030D): The credentials supplied to the package were not recognized
Why doesn't this work?
See runtime output below.