Autenticação e autorização no gRPC para ASP.NET Core
Observação
Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Exibir ou baixar código de exemplo (como baixar)
Autenticar usuários chamando um serviço do gRPC
O gRPC pode ser usado com autenticação do ASP.NET Core para associar um usuário a cada chamada.
Veja a seguir um exemplo do Program.cs
, o qual usa a autenticação do gRPC e do ASP.NET Core:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGrpcService<GreeterService>();
Observação
A ordem na qual você registra o middleware de autenticação do ASP.NET Core é importante. Sempre chame UseAuthentication
e UseAuthorization
depois de UseRouting
e antes de UseEndpoints
.
O mecanismo de autenticação que seu aplicativo usa durante uma chamada precisa ser configurado. A configuração de autenticação é adicionada no Program.cs
e será diferente dependendo do mecanismo de autenticação que seu aplicativo usa.
Depois que a autenticação tiver sido configurada, o usuário poderá ser acessado em métodos de serviço do gRPC por meio do ServerCallContext
.
public override Task<BuyTicketsResponse> BuyTickets(
BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
// ... access data from ClaimsPrincipal ...
}
Autenticação de token de portador
O cliente pode fornecer um token de acesso para autenticação. O servidor valida o token e o utiliza para identificar o usuário.
No servidor, a autenticação do token de portador é configurada usando o middleware do Portador JWT.
No cliente gRPC do .NET, o token pode ser enviado com chamadas usando a coleção Metadata
. As entradas na coleção Metadata
são enviadas com uma chamada do gRPC como cabeçalhos HTTP:
public bool DoAuthenticatedCall(
Ticketer.TicketerClient client, string token)
{
var headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");
var request = new BuyTicketsRequest { Count = 1 };
var response = await client.BuyTicketsAsync(request, headers);
return response.Success;
}
Definir o token de portador com CallCredentials
A configuração ChannelCredentials
em um canal é uma maneira alternativa de enviar o token para o serviço com chamadas do gRPC. Um ChannelCredentials
pode incluir CallCredentials
, que fornece uma maneira de definir automaticamente Metadata
.
Benefícios do uso de CallCredentials
:
- A autenticação é configurada centralmente no canal. O token não precisa ser fornecido manualmente para a chamada gRPC.
- O retorno de chamada
CallCredentials.FromInterceptor
é assíncrono. As credenciais de chamada podem buscar um token de credencial de um sistema externo, se necessário. Os métodos assíncronos dentro do retorno de chamada devem usar oCancellationToken
emAuthInterceptorContext
.
Observação
CallCredentials
só serão aplicados se o canal for protegido com TLS. O envio de cabeçalhos de autenticação por uma conexão insegura tem implicações de segurança e não deve ser feito em ambientes de produção. Um aplicativo pode configurar um canal para ignorar esse comportamento e sempre usar CallCredentials
definindo UnsafeUseInsecureChannelCallCredentials
em um canal.
A credencial no exemplo a seguir configura o canal para enviar o token a cada chamada do gRPC:
private static GrpcChannel CreateAuthenticatedChannel(ITokenProvder tokenProvider)
{
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
var token = await tokenProvider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
});
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
Token de portador com fábrica de clientes do gRPC
A fábrica de clientes do gRPC pode criar clientes que enviam um token de portador usando AddCallCredentials
. Esse método está disponível no Grpc.Net.ClientFactory versão 2.46.0 ou posterior.
O representante aprovado para AddCallCredentials
é executado para cada chamada do gRPC:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
A injeção de dependência (ID) pode ser combinada com AddCallCredentials
. Uma sobrecarga aprova o IServiceProvider
para o representante, que pode ser usado para obter um serviço construído a partir da ID usando serviços com escopo e transitórios.
Considere um aplicativo que tenha:
- Um
ITokenProvider
definido pelo usuário para obter um token de portador.ITokenProvider
é registrado em ID com um tempo de vida com escopo. - A fábrica de cliente do gRPC é configurada para criar clientes injetados em serviços do gRPC e controladores de API Web.
- As chamadas do gRPC devem usar o
ITokenProvider
para obter um token de portador.
public interface ITokenProvider
{
Task<string> GetTokenAsync(CancellationToken cancellationToken);
}
public class AppTokenProvider : ITokenProvider
{
private string _token;
public async Task<string> GetTokenAsync(CancellationToken cancellationToken)
{
if (_token == null)
{
// App code to resolve the token here.
}
return _token;
}
}
builder.Services.AddScoped<ITokenProvider, AppTokenProvider>();
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials(async (context, metadata, serviceProvider) =>
{
var provider = serviceProvider.GetRequiredService<ITokenProvider>();
var token = await provider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
}));
O código anterior:
- Define
ITokenProvider
eAppTokenProvider
. Esses tipos lidam com a resolução do token de autenticação para chamadas do gRPC. - Registra o tipo
AppTokenProvider
com ID em um tempo de vida com escopo.AppTokenProvider
armazena em cache o token para que apenas a primeira chamada no escopo seja necessária para calculá-lo. - Registra o tipo
GreeterClient
com fábrica de cliente. - Configura
AddCallCredentials
para esse cliente. O representante é executado sempre que uma chamada é feita e adiciona o token retornado peloITokenProvider
para os metadados.
Autenticação de certificado do cliente
Como alternativa, um cliente pode fornecer um certificado de cliente para autenticação. A autenticação de certificado ocorre no nível do TLS, muito antes de chegar ao ASP.NET Core. Quando a solicitação entra no ASP.NET Core, o pacote de autenticação de certificado do cliente permite que você resolva o certificado para um ClaimsPrincipal
.
Observação
Configure o servidor para aceitar certificados de cliente. Para obter informações sobre como aceitar certificados de cliente no Kestrel, no IIS e no Azure, consulte Configurar a autenticação de certificado no ASP.NET Core.
No cliente gRPC do .NET, o certificado do cliente é adicionado ao HttpClientHandler
que é usado para criar o cliente gRPC:
public Ticketer.TicketerClient CreateClientWithCert(
string baseAddress,
X509Certificate2 certificate)
{
// Add client cert to the handler
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
// Create the gRPC channel
var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
{
HttpHandler = handler
});
return new Ticketer.TicketerClient(channel);
}
Outros mecanismos de autenticação
Muitos mecanismos de autenticação com suporte do ASP.NET Core funcionam com gRPC:
- Microsoft Entra ID
- Certificado do Cliente
- IdentityServer
- JWT Token
- OAuth 2.0
- OpenID Connect
- O certificado do provedor de identidade do Web Services Federation
Para obter mais informações sobre como configurar a autenticação no servidor, consulte autenticação do ASP.NET Core.
Configurar o cliente gRPC para usar a autenticação dependerá do mecanismo de autenticação que você está usando. Os exemplos anteriores de token de portador e certificado do cliente mostram algumas maneiras pelas quais o cliente gRPC pode ser configurado para enviar metadados de autenticação com chamadas gRPC:
- Clientes gRPC fortemente tipados usam
HttpClient
internamente. A autenticação pode ser configurada no HttpClientHandlerou adicionando instâncias personalizadas HttpMessageHandler aoHttpClient
. - Cada chamada do gRPC tem um argumento opcional
CallOptions
. Cabeçalhos personalizados podem ser enviados usando a coleção de cabeçalhos da opção.
Observação
A Autenticação do Windows (NTLM/Kerberos/Negotiate) não pode ser usada com gRPC. GRPC requer HTTP/2 e HTTP/2 não dá suporte à Autenticação do Windows.
Autorizar usuários a acessar serviços e métodos de serviço
Por padrão, todos os métodos em um serviço podem ser chamados por usuários não autenticados. Para exigir autenticação, aplique o atributo [Authorize]
ao serviço:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Você pode usar os argumentos do construtor e as propriedades do atributo [Authorize]
para restringir o acesso somente a usuários que correspondem a políticas de autorização específicas. Por exemplo, se você tiver uma política de autorização personalizada chamada MyAuthorizationPolicy
, verifique se somente os usuários correspondentes a essa política poderão acessar o serviço usando o seguinte código:
[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}
Métodos de serviço individuais também podem ter o atributo [Authorize]
aplicado. Se o usuário atual não corresponder às políticas aplicadas a ambos oa métodos e à classe, um erro será retornado ao chamador:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
public override Task<AvailableTicketsResponse> GetAvailableTickets(
Empty request, ServerCallContext context)
{
// ... buy tickets for the current user ...
}
[Authorize("Administrators")]
public override Task<BuyTicketsResponse> RefundTickets(
BuyTicketsRequest request, ServerCallContext context)
{
// ... refund tickets (something only Administrators can do) ..
}
}
Recursos adicionais
Exibir ou baixar código de exemplo (como baixar)
Autenticar usuários chamando um serviço do gRPC
O gRPC pode ser usado com autenticação do ASP.NET Core para associar um usuário a cada chamada.
Veja a seguir um exemplo do Startup.Configure
, o qual usa a autenticação do gRPC e do ASP.NET Core:
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
Observação
A ordem na qual você registra o middleware de autenticação do ASP.NET Core é importante. Sempre chame UseAuthentication
e UseAuthorization
depois de UseRouting
e antes de UseEndpoints
.
O mecanismo de autenticação que seu aplicativo usa durante uma chamada precisa ser configurado. A configuração de autenticação é adicionada no Startup.ConfigureServices
e será diferente dependendo do mecanismo de autenticação que seu aplicativo usa.
Depois que a autenticação tiver sido configurada, o usuário poderá ser acessado em métodos de serviço do gRPC por meio do ServerCallContext
.
public override Task<BuyTicketsResponse> BuyTickets(
BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
// ... access data from ClaimsPrincipal ...
}
Autenticação de token de portador
O cliente pode fornecer um token de acesso para autenticação. O servidor valida o token e o utiliza para identificar o usuário.
No servidor, a autenticação do token de portador é configurada usando o middleware do Portador JWT.
No cliente gRPC do .NET, o token pode ser enviado com chamadas usando a coleção Metadata
. As entradas na coleção Metadata
são enviadas com uma chamada do gRPC como cabeçalhos HTTP:
public bool DoAuthenticatedCall(
Ticketer.TicketerClient client, string token)
{
var headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");
var request = new BuyTicketsRequest { Count = 1 };
var response = await client.BuyTicketsAsync(request, headers);
return response.Success;
}
Definir o token de portador com CallCredentials
A configuração ChannelCredentials
em um canal é uma maneira alternativa de enviar o token para o serviço com chamadas do gRPC. Um ChannelCredentials
pode incluir CallCredentials
, que fornece uma maneira de definir automaticamente Metadata
.
Benefícios do uso de CallCredentials
:
- A autenticação é configurada centralmente no canal. O token não precisa ser fornecido manualmente para a chamada gRPC.
- O retorno de chamada
CallCredentials.FromInterceptor
é assíncrono. As credenciais de chamada podem buscar um token de credencial de um sistema externo, se necessário. Os métodos assíncronos dentro do retorno de chamada devem usar oCancellationToken
emAuthInterceptorContext
.
Observação
CallCredentials
só serão aplicados se o canal for protegido com TLS. O envio de cabeçalhos de autenticação por uma conexão insegura tem implicações de segurança e não deve ser feito em ambientes de produção. Um aplicativo pode configurar um canal para ignorar esse comportamento e sempre usar CallCredentials
definindo UnsafeUseInsecureChannelCallCredentials
em um canal.
A credencial no exemplo a seguir configura o canal para enviar o token a cada chamada do gRPC:
private static GrpcChannel CreateAuthenticatedChannel(ITokenProvder tokenProvider)
{
var credentials = CallCredentials.FromInterceptor(async (context, metadata) =>
{
var token = await tokenProvider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
});
var channel = GrpcChannel.ForAddress(address, new GrpcChannelOptions
{
Credentials = ChannelCredentials.Create(new SslCredentials(), credentials)
});
return channel;
}
Token de portador com fábrica de clientes do gRPC
A fábrica de clientes do gRPC pode criar clientes que enviam um token de portador usando AddCallCredentials
. Esse método está disponível no Grpc.Net.ClientFactory versão 2.46.0 ou posterior.
O representante aprovado para AddCallCredentials
é executado para cada chamada do gRPC:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
A injeção de dependência (ID) pode ser combinada com AddCallCredentials
. Uma sobrecarga aprova o IServiceProvider
para o representante, que pode ser usado para obter um serviço construído a partir da ID usando serviços com escopo e transitórios.
Considere um aplicativo que tenha:
- Um
ITokenProvider
definido pelo usuário para obter um token de portador.ITokenProvider
é registrado em ID com um tempo de vida com escopo. - A fábrica de cliente do gRPC é configurada para criar clientes injetados em serviços do gRPC e controladores de API Web.
- As chamadas do gRPC devem usar o
ITokenProvider
para obter um token de portador.
public interface ITokenProvider
{
Task<string> GetTokenAsync(CancellationToken cancellationToken);
}
public class AppTokenProvider : ITokenProvider
{
private string _token;
public async Task<string> GetTokenAsync(CancellationToken cancellationToken)
{
if (_token == null)
{
// App code to resolve the token here.
}
return _token;
}
}
services.AddScoped<ITokenProvider, AppTokenProvider>();
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials(async (context, metadata, serviceProvider) =>
{
var provider = serviceProvider.GetRequiredService<ITokenProvider>();
var token = await provider.GetTokenAsync(context.CancellationToken);
metadata.Add("Authorization", $"Bearer {token}");
}));
O código anterior:
- Define
ITokenProvider
eAppTokenProvider
. Esses tipos lidam com a resolução do token de autenticação para chamadas do gRPC. - Registra o tipo
AppTokenProvider
com ID em um tempo de vida com escopo.AppTokenProvider
armazena em cache o token para que apenas a primeira chamada no escopo seja necessária para calculá-lo. - Registra o tipo
GreeterClient
com fábrica de cliente. - Configura
AddCallCredentials
para esse cliente. O representante é executado sempre que uma chamada é feita e adiciona o token retornado peloITokenProvider
para os metadados.
Autenticação de certificado do cliente
Como alternativa, um cliente pode fornecer um certificado de cliente para autenticação. A autenticação de certificado ocorre no nível do TLS, muito antes de chegar ao ASP.NET Core. Quando a solicitação entra no ASP.NET Core, o pacote de autenticação de certificado do cliente permite que você resolva o certificado para um ClaimsPrincipal
.
Observação
Configure o servidor para aceitar certificados de cliente. Para obter informações sobre como aceitar certificados de cliente no Kestrel, no IIS e no Azure, consulte Configurar a autenticação de certificado no ASP.NET Core.
No cliente gRPC do .NET, o certificado do cliente é adicionado ao HttpClientHandler
que é usado para criar o cliente gRPC:
public Ticketer.TicketerClient CreateClientWithCert(
string baseAddress,
X509Certificate2 certificate)
{
// Add client cert to the handler
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(certificate);
// Create the gRPC channel
var channel = GrpcChannel.ForAddress(baseAddress, new GrpcChannelOptions
{
HttpHandler = handler
});
return new Ticketer.TicketerClient(channel);
}
Outros mecanismos de autenticação
Muitos mecanismos de autenticação com suporte do ASP.NET Core funcionam com gRPC:
- Microsoft Entra ID
- Certificado do Cliente
- IdentityServer
- JWT Token
- OAuth 2.0
- OpenID Connect
- O certificado do provedor de identidade do Web Services Federation
Para obter mais informações sobre como configurar a autenticação no servidor, consulte autenticação do ASP.NET Core.
Configurar o cliente gRPC para usar a autenticação dependerá do mecanismo de autenticação que você está usando. Os exemplos anteriores de token de portador e certificado do cliente mostram algumas maneiras pelas quais o cliente gRPC pode ser configurado para enviar metadados de autenticação com chamadas gRPC:
- Clientes gRPC fortemente tipados usam
HttpClient
internamente. A autenticação pode ser configurada no HttpClientHandlerou adicionando instâncias personalizadas HttpMessageHandler aoHttpClient
. - Cada chamada do gRPC tem um argumento opcional
CallOptions
. Cabeçalhos personalizados podem ser enviados usando a coleção de cabeçalhos da opção.
Observação
A Autenticação do Windows (NTLM/Kerberos/Negotiate) não pode ser usada com gRPC. GRPC requer HTTP/2 e HTTP/2 não dá suporte à Autenticação do Windows.
Autorizar usuários a acessar serviços e métodos de serviço
Por padrão, todos os métodos em um serviço podem ser chamados por usuários não autenticados. Para exigir autenticação, aplique o atributo [Authorize]
ao serviço:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
}
Você pode usar os argumentos do construtor e as propriedades do atributo [Authorize]
para restringir o acesso somente a usuários que correspondem a políticas de autorização específicas. Por exemplo, se você tiver uma política de autorização personalizada chamada MyAuthorizationPolicy
, verifique se somente os usuários correspondentes a essa política poderão acessar o serviço usando o seguinte código:
[Authorize("MyAuthorizationPolicy")]
public class TicketerService : Ticketer.TicketerBase
{
}
Métodos de serviço individuais também podem ter o atributo [Authorize]
aplicado. Se o usuário atual não corresponder às políticas aplicadas a ambos oa métodos e à classe, um erro será retornado ao chamador:
[Authorize]
public class TicketerService : Ticketer.TicketerBase
{
public override Task<AvailableTicketsResponse> GetAvailableTickets(
Empty request, ServerCallContext context)
{
// ... buy tickets for the current user ...
}
[Authorize("Administrators")]
public override Task<BuyTicketsResponse> RefundTickets(
BuyTicketsRequest request, ServerCallContext context)
{
// ... refund tickets (something only Administrators can do) ..
}
}
Métodos de extensão de autorização
A autorização também pode ser controlada com métodos padrão de extensão de autorização do ASP.NET Core, como AllowAnonymous
e RequireAuthorization
.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<TicketerService>().RequireAuthorization("Administrators");
app.Run();