We have a gPRC service that needs to set auth/identity information in a ThreadLocal variable in a class for it to correctly call another service. The gPRC service gets the auth/identiy information from request so I am thinking to use interceptor.
To start, I have some code looking as follows.
public class ImpersonationInterceptor {
public <ReqT, RespT> interceptCall(
ServerCall<ReqT, RespT> serverCall, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
Principal principal = ... // get the identify from the request
AuthContext.setPrincipal(principal); // underneath it uses a ThreadLocal.
return next.startCall(
new SimpleForwardingServerCall<>(call) {
public void close(Status status, Metadata trailers) {
AuthContext.setPrincipal(null); // clear the identity
}
}
)
}
}
Questions.
Thanks very much in advance.
You must be very careful with ThreadLocals for this type of context information, because you don't want to accidentally use the wrong identity for the client.
Every callback from gRPC can occur on a different thread, and callbacks for multiple RPCs can occur on the same thread.
You need to follow a pattern like Contexts.interceptCall(). You have to set/unset after each call:
public class ImpersonationInterceptor {
public <ReqT, RespT> interceptCall(
ServerCall<ReqT, RespT> serverCall, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
Principal principal = ...;
AuthContext.setPrincipal(principal);
try {
return new WrappingListener<>(next.startCall(call, headers), principal);
} finally {
AuthContext.clearPrincipal();
}
}
private static class WrappingListener<ReqT> extends
ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT> {
private final Principal principal;
public WrappingListener(ServerCall.Listener<ReqT> delegate, Principal principal) {
super(delegate);
this.principal = principal;
}
@Override
public void onMessage(ReqT message) {
AuthContext.setPrincipal(principal);
try {
super.onMessage(message);
} finally {
AuthContext.clearPrincipal();
}
}
... repeat for each method
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With