Home > Mobile >  How do I pass bearer token and other info from Spring Service to Grpc Interceptor?
How do I pass bearer token and other info from Spring Service to Grpc Interceptor?

Time:02-02

I have a Spring GraphQL application that calls the other internal microservice using the gRPC protocol. I need to set the bearer token and other information to the gRPC header, I believe we can set it up using the gRPC interceptor (ClientInterceptor implementation).

I tried the below approach:

Based on How to Access attributes from grpc Context.current()? I created a key so that we can refer it in spring-service and interceptor

public class ContextKeyHolder {
  public static Context.Key<String> USER_INFO = Context.key("USER");
  public static Context.Key<String> BEARER = Context.key("BEARER");
}

// spring-service method
public Employee getEmployee() {
  ...
  Context.current().withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername());
  Context.current().withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken());
  return grpcClient.getEmployee(...);
}

// interceptCall implementation
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor,
    CallOptions callOptions, Channel channel) {
    return new ForwardingClientCall.SimpleForwardingClientCall<>(
      channel.newCall(methodDescriptor, callOptions)) {
     
      @Override
      public void start(Listener<RespT> responseListener, Metadata headers) {
        ...
        
        String userInfo = ContextKeyHolder.USER_INFO.get(Context.current());
        System.out.println("user => "   userInfo);
        
        ...
        super.start(responseListener, headers);
      }
    };
  }

Here I am getting null userInfo in the interceptor method. am I missing something here?

The other option is to use ThreadLocal to hold the context but I am kind of not sure if it's the right choice here.

CodePudding user response:

The context you created needs to be used when you make the call. So your code should be:

return Context.current()
   .withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
   .withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken())
   .call(() -> { return grpcClient.getEmployee(...);});

Alternatively:

  Context oldContext = 
   Context.current()
     .withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
     .withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken())
     .attach();
  
  Employee valueToReturn = grpcClient.getEmployee(...);
  Context.current().detach(oldContext);
  return valueToReturn;
  • Related