Reputation: 117
I have an existing REST API running on ASP.NET Core 3.0. It uses MVC filter to perform an authorization check based on a header value and returns error in case of authorization failure so that the request is not passed to the controller.
Now, I am experimenting with gRPC and trying to port this API to a gRPC service. However, I do not see any obvious solutions that might act as an MVC filter replacement.
Is there some way to achieve similar authorization checking functionality, perhaps using metadata?
Upvotes: 1
Views: 3447
Reputation: 30046
For MVC and gRpc, they are different. ActionFilter is not exist under gRpc.
If you want to apply checking request header for all actions, you could try implement your custom middleware before app.UseEndpoints
and check the request header.
For another way, you could try Policy
like below:
GrpcRequireemnt
and GrpcHandler
public class GrpcRequirement : IAuthorizationRequirement
{
}
public class GrpcHandler : AuthorizationHandler<GrpcRequirement>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GrpcHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GrpcRequirement requirement)
{
var headers = _httpContextAccessor.HttpContext.Request.Headers;
StringValues token;
if (!headers.TryGetValue("token", out token))
{
context.Fail();
return Task.CompletedTask;
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
Register required services
services.AddAuthorization(options =>
{
options.AddPolicy("TokenAuthorize", policy =>
{
policy.AddRequirements(new GrpcRequirement());
});
});
services.AddHttpContextAccessor();
services.AddSingleton<IAuthorizationHandler, GrpcHandler>();
UseCase
[Authorize("TokenAuthorize")]
public override Task<BuyTicketsResponse> BuyTickets(BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
return Task.FromResult(new BuyTicketsResponse
{
Success = _ticketRepository.BuyTickets(user.Identity.Name!, request.Count)
});
}
Upvotes: 3
Reputation: 380
This will have slightly different answers depending on if you're using Grpc.Core, which is a wrapper around the C GRPC library initially developed at Google, which has been available for a while and supports a variety of .Net targets (including Framework), or if you're using the new Grpc.AspNetCore which launched with .Net Core 3.0 and is built on Kestrel and ASP.NET Core internals.
For Grpc.Core you would want to pass your header value as metadata, and then create a server-side Interceptor to handle the metadata and the request. You can also consider using the AsyncAuthInterceptor, however the core Grpc implementation on the client side will not send credentials over insecure (non-TLS) connections.
Grpc.AspNetCore is built on ASP.NET and can use ASP.NET middleware, including the default ASP.NET authentication. If you can convert your filter into a middleware, you would be able to share the authentication between both implementations.
Upvotes: 3