Define the Metadata

All Metadata is strongly typed and keyed. That means, rather than using a string as a key you pass into a Map, you have to create a Metadata Key.

Open chat-service/src/main/java/com/example/chat/grpc/Constant.java to define a new metadata for transferring JWT token between services:

// TODO Add a JWT_METADATA_KEY
public static final Metadata.Key<String> JWT_METADATA_KEY =
  Metadata.Key.of("jwt", ASCII_STRING_MARSHALLER);

Using Interceptors to pass Metadata

Capture Metadata from Server Interceptor

On the server side, metadata can only be captured from a server interceptor. Open chat-service/src/main/java/com/example/chat/grpc/JwtServerInterceptor.java.

Capture the JWT token and print it out:

public class JwtServerInterceptor implements ServerInterceptor {
  ...

  @Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
    // TODO Get token from Metadata
    String token = metadata.get(Constant.JWT_METADATA_KEY);
    System.out.println("Token: " + token);

    return serverCallHandler.startCall(serverCall, metadata);
  }
}

Attach Server Interceptor

Open chat-service/src/main/java/com/example/chat/grpc/ChatServer.java. The JwtServerInterceptor is already instantiated. However, we need to add it into the interceptor chain:

In the ServerBuilder, where we register existing service instances, we can modify it to apply interceptors for each of the service:

// TODO Add JWT Server Interceptor, then later, trace interceptor
final Server server = ServerBuilder.forPort(9092)
  .addService(ServerInterceptors
    .intercept(chatRoomService, jwtServerInterceptor))
  .addService(ServerInterceptors
    .intercept(chatStreamService, jwtServerInterceptor))
  .build();

Now, every request sent to these services will first be intercepted by the JWTServerInterceptor.

Run the server:

$ cd chat-service
$ mvn install exec:java