Reputation: 1041
I've implemented a gRPC server in golang that requires custom authorization information, i.e. email and api_key (over a TLS-encrypted connection). In golang, I can easily implement the client using PerRPCCredentials, which simply creates a metadata map like {"email": email, "api_key": apiKey}. (Then I use a StreamInterceptor on the server side to extract them from the incoming context and then validate them). However, I can't figure out how to do the equivalent for a python client. I have tried implementing an AuthMetadataPlugin as documented here https://github.com/grpc/grpc/tree/master/examples/python/auth and exemplified here: https://github.com/grpc/grpc/blob/master/examples/python/auth/customized_auth_client.py
class AuthMetadataPlugin:
def __init__(self, email, api_key):
self.email = email
self.api_key = api_key
def __call__(self, context, callback):
callback((('email', self.email), ('api_key', self.api_key)), None)
But I get the following error: TypeError: Cannot convert grpc._cython.cygrpc.MetadataPluginCallCredentials to grpc._cython.cygrpc.ChannelCredentials
when I call grpc.metadata_call_credentials(AuthMetadataPlugin(email, api_key))
.
What's more confusing is that a lot of the documentation seems to talk about adding custom HTTP headers, but I only want this authorization information to be sent once per (streaming) RPC call, not with every HTTP frame for these calls. (Admittedly, I'm not sure how it works in golang, but I do know my StreamInterceptor is only called once per streaming RPC call).
How can I add this authorization information to my RPC calls in python so that my golang gRPC server can pull it out of the incoming context?
Upvotes: 2
Views: 1128
Reputation: 1041
That actually worked, I was passing the credentials to the composite composer in the wrong order - tls credentials must come first.
Upvotes: 0