New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to pass a header to a CallCredentials? #7415
Comments
That's probably by design: the interceptors are run with a
That's correct. What is your question?
The comment for |
@sanjaypujare Thanks for your response, but it doesn't answer the basic question: if One way to get around this problem could be replacing the |
Yes I was thinking the same. If you need access to the original headers, then a regular client interceptor is the way to go.
The CallCredentials code could be 3rd party code that should not have access to the headers and payload coming from the client. So that might be the reason for this design decision. CC @ejona86 for comments. |
Why? That is really strange. Why wouldn't you just pass what identity you wanted to the CallCredentials when creating them?
Not at all. It was a conscious decision not to support HMAC (much at all and) in CallCredentials. HMAC via headers is incompatible with streaming. If you want HMAC, you have to put the HMAC in the message itself. HMAC is mostly dead for general-purpose authentication; it was mainly for the plaintext HTTP days. CallCredentials is designed for bearer tokens over a secure connection. HMAC is still useful, but for application-specific uses. |
@ejona86 I maintain
If there's a better way to do this, I'd love to know. |
Good. That's what I'd expect.
That's fine if you are doing a one-off. However, this pattern you're doing is fairly common, and would more commonly be accomplished with CallCredentials: ClientIdentity identity = getIdentityFromContext();
stub.withCallCredentials(new ClientIdentityCredentials(identity))
.theRpcMethod(...); Or something closer to maybe what you want: // The credentials themselves will call getIdentityFromContext()
stub = stub.withCallCredentials(new AmbientClientIdentityCredentials());
// reuse stub across RPCs I do think Context is provided to CallCredentials. So if we go and look at your original code: val userId = headers.get(USER_ID_HEADER_KEY)
val ctx = Context.current().withValue(USER_ID_CONTEXT_KEY, userId)
ctx.run { super.start(responseListener, headers) } You are changing the context for start(). The context used is the one from We discourage ClientInterceptors from modifying Context, as that mutation will be visible in StreamObserver callbacks which may then perform additional RPCs and then you get into a confusing situation. If the application itself modifies the context before calling the stub, then it is obvious the context will have those modifications for the callbacks and newCall() or start() have the same context exposed to them. |
I can confirm that doing so makes the context available to the
However, I ended up not using the In the end, I still don't see any good reason in a design that goes out of its way to hide the headers from the |
I've a
CallCredentials
that uses a header value to do a look up in the DB, and then apply the result as an extra header.Since
CallCredentials
doesn't have access to metadata, I wrote aClientInterceptor
; inForwardingClientCall.start
, I get the header value and copy it to theContext
.In the
CallCredentials
, I get the value set before.However, this is coming out as
null
.My questions:
ClientInterceptor
and theCallCredentials
are running on the same thread. However, I've noticed that theContext
object id changes.MetadataApplier
doesn't have public access to the headers,MetadataApplierImpl
does as fieldorigHeaders
. The latter isn't a public class, so there's no way to get the headers without reflection trickery.Contexts.interceptCall
method meant for intercepting aServerCall
with aContext
parameter; why is there no equivalent method for intercepting aClientCall
?The text was updated successfully, but these errors were encountered: