I have tried to implement and client/server gRPC with Bearer token authorization. When I send an invalid token, the token itself is rejected, but the business part of the gRPC executes anyway. Once the token is rejected, the pipeline should return with a 401/403 status code with no further execution.
Here is an example with the problem.
https://github.com/damienbod/Secure_gRpc
If you replace these 2 lines, and send a invalid access token, you can reproduce the problem on the server.
https://github.com/damienbod/Secure_gRpc/blob/master/Secure_gRpc/Secure_gRpc.Client/Program.cs#L24-L25
Greetings Damien
Thanks for trying it out. I'll look into.
I ran your sample and I get into GreeterService.SayHello.
Is it possible that Authorization/Authentication has not been configured correctly to reject the token? I'm not an expert in that area so I can't say with certainty.
We have some function tests that use authorization and it returns a 401 error: https://github.com/grpc/grpc-dotnet/blob/24ecde24012ba2c475368e297463c4b8fea82932/test/FunctionalTests/AuthorizationTests.cs
Related Startup.cs configuration code:
services.AddAuthorization(options =>
{
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireClaim(ClaimTypes.NameIdentifier);
});
});
services.AddAuthorizationPolicyEvaluator();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateActor = false,
ValidateLifetime = true,
IssuerSigningKey = SecurityKey
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var token = context.Request.Headers["access_token"];
if (!string.IsNullOrEmpty(token))
{
context.Token = token;
}
return Task.CompletedTask;
}
};
});
I tried the test example and it works, so I switched the server code to use AddJwtBearer and it still did not work with my client.
I do not set the context.Token in the JwtBearerEvents, because I believe the Authorization header should be used. The token gets validated and is logged in the console as invalid, but the pipeline continues to execute.
I figured it out. The code that shipped in preview 3 does not support attributes on the service or methods. This isn't doing anything: [Authorize(Policy = "protectedScope")]
Change your Startup.cs code to this and you're good to go:
app.UseRouting(routes =>
{
routes.MapGrpcService<GreeterService>().RequireAuthorization("protectedScope");
});
This is already fixed and will be in the next preview.
@damienbod Do you have the authorization middleware configured? https://github.com/grpc/grpc-dotnet/blob/71ccbfd5d3aad1d9d90e6d98d75e8eb833c86769/testassets/FunctionalTestsWebsite/Startup.cs#L151
excellent, this works
routes.MapGrpcService
Thanks
@davidfowl Yes the authorization middleware is configured.https://github.com/damienbod/Secure_gRpc/blob/master/Secure_gRpc/Secure_gRpc.Server/Startup.cs#L64-L65
So once the Attributes are supported, this will work.