I am trying to follow this example to how to use JWT authentication.
But I get the error: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot.
This is my code:
The server:
using GestorOrdenadores.Service.Grpc.DotNet.Services;
using ProtoBuf.Grpc.Server;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(options =>
{
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireClaim(ClaimTypes.Name);
});
});
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateActor = false,
ValidateLifetime = true,
IssuerSigningKey = GestorOrdenadores.Service.Grpc.DotNet.Autenticacion.SecurityKey
};
});
builder.Services.AddCodeFirstGrpc();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGrpcService<GreeterService>();
app.MapGet("/generateJwtToken", context =>
{
GestorOrdenadores.Service.Grpc.DotNet.Autenticacion miAutenticador = new GestorOrdenadores.Service.Grpc.DotNet.Autenticacion();
return context.Response.WriteAsync(miAutenticador.GenerateJwtToken(context.Request.Query["name"]));
});
app.Run();
The client:
public class ClienteGrpcDotNet
{
#region constructores
private ClienteGrpcDotNet() { }
private ClienteGrpcDotNet (IGreeterService paramIServicio)
{
_client = paramIServicio;
}
public static async Task<ClienteGrpcDotNet> Create()
{
string miStrRootAddress = "https://localhost:5001";
IGreeterService miCliente = await GetServiceWithJwtAuthentication(miStrRootAddress);
return new ClienteGrpcDotNet(miCliente);
}
private static async Task<IGreeterService> GetServiceWithJwtAuthentication(string paramStrRootAddress)
{
GrpcChannel miCanal = await CreateAuthenticatedChannel(paramStrRootAddress);
IGreeterService miServicio = miCanal.CreateGrpcService<IGreeterService>();
return miServicio;
}
#endregion constructores
private readonly IGreeterService _client;
#region métodos del servicio
public async Task<string?> SayHelloAsync()
{
HelloReply miRespuesta = await _client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
return miRespuesta.Message;
}
#endregion métodos del servicio
#region autenticación
private static async Task<string> Authenticate(string paramAddress)
{
using var httpClient = new HttpClient();
using var request = new HttpRequestMessage
{
RequestUri = new Uri($"{paramAddress}/generateJwtToken?name={HttpUtility.UrlEncode(Environment.UserName)}"),
Method = HttpMethod.Get,
Version = new Version(2, 0)
};
using var tokenResponse = await httpClient.SendAsync(request);
tokenResponse.EnsureSuccessStatusCode();
var token = await tokenResponse.Content.ReadAsStringAsync();
return token;
}
private static async Task<GrpcChannel> CreateAuthenticatedChannel(string paramAddress)
{
string miToken = await Authenticate(paramAddress);
CallCredentials credentials = CallCredentials.FromInterceptor((context, metadata) =>
{
if (!string.IsNullOrEmpty(miToken))
{
metadata.Add("Authorization", $"Bearer {miToken}");
}
return Task.CompletedTask;
});
GrpcChannel channel = GrpcChannel.ForAddress(paramAddress, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
#endregion autenticación
}
Thanks so much.