Grpc-java: permit some services from custom authentication [need help]

Created on 8 Sep 2018  路  10Comments  路  Source: grpc/grpc-java

I need help with custom authentication

I know we can use metadata and inspectors to support custom authorizations like basic authentication but how we can exclude some services from being authenticated in inspectors.

is there something like @PermitAll in JAX-RS (jersey framework implementation) which we can use and check the destination endpoint has this annotation or not in provider?

Most helpful comment

The metadata example does use interceptor together:
https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples/header

The HeaderServerInterceptor.java in the example synthesizes the response headers, whereas your usecase is to inspect the request headers which is easier than the example. For authentication failure, in ServerInterceptor.interceptCall() method you can probably call

call.close(Status.UNAUTHENTICATED.withDescription("..."), new Metadata());
return next.startCall(call);

All 10 comments

You can implement

```
CallCredentials#applyRequestMetadata(
MethodDescriptor method, Attributes attrs, Executor appExecutor, MetadataApplier applier)
````

to differentiate the URI of services by MethodDescriptor, and use AbstractStub.withCallCredentials(CallCredentials credentials).

See https://grpc.io/grpc-java/javadoc/io/grpc/CallCredentials.html

For server side, use ServerInterceptor to inspect the request and apply authentication, and use ServerCall.getMethodDescriptor() to differentiate the URI of services.

@dapengzhang0 I saw Interceptor and Metadata example already but they were separated from each other, so is there any example about using these two for authorization matters available?

The metadata example does use interceptor together:
https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples/header

The HeaderServerInterceptor.java in the example synthesizes the response headers, whereas your usecase is to inspect the request headers which is easier than the example. For authentication failure, in ServerInterceptor.interceptCall() method you can probably call

call.close(Status.UNAUTHENTICATED.withDescription("..."), new Metadata());
return next.startCall(call);

what is the cleanest way to ignore some services for authentication (like a service for registering users)? (could u please give me a small example? a very simple service for user registering and login with serverincepter can be awesome)

@MetaiR in the grpc library we don't have out of box high level tools like @PermitAll. Here's an example using interceptor (with pseudocod needAuthentication(), authnPassed()):

public class AuthenticationServerInterceptor implements ServerInterceptor {
  @Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call,
      Metadata requestHeaders,
      ServerCallHandler<ReqT, RespT> next) {
    String methodName = call.getMethodDescriptor().getFullMethodName();
    if (needAuthentication(methodName) && !authnPassed(requestHeaders)) {
      call.close(Status.UNAUTHENTICATED.withDescription("..."), new Metadata());
    }
    return next.startCall(call);
  }
}

thanks a lot

An update on the example above: closing the call and then returning next.startCall does not populate Status.UNAUTHENTICATED to the client, because of a runtime exception thrown by next.startCall, so a graceful way is to return a noop listener instead:

if (needAuthentication(methodName) && !authnPassed(requestHeaders)) {
   call.close(Status.UNAUTHENTICATED.withDescription("..."), new Metadata());
   return new ServerCall.Listener() { 
      // noop for all the methods
   };
}
return next.startCall(call, requestHeaders);

can return null instead of a ServerCall Listener obj?
@dapengzhang0

@MetaiR the javadoc says must not return null.

Was this page helpful?
0 / 5 - 0 ratings