I followed the instructions of generating a Python gPRC client from here but struggle to provide a token to the request
Insecure Channel does not work
auth_creds = grpc.access_token_call_credentials(TOKEN)
channel = grpc.insecure_channel('localhost:10000', auth_creds)
>> TypeError: 'CallCredentials' object is not iterable
Secure Channel does not work either
auth_creds = grpc.access_token_call_credentials(TOKEN)
channel = grpc.secure_channel('localhost:10000', auth_creds)
>> TypeError: Argument 'channel_credentials' has incorrect type (expected grpc._cython.cygrpc.ChannelCredentials, got grpc._cython.cygrpc.MetadataPluginCallCredentials)
According to python gRPC documentation
A CallCredentials has to be used with secure Channel, otherwise the metadata will not be transmitted to the server.
However, how do I create a secure channel, since methods which create these ChannelCredentials correspond to ssl or similar, no?
In addition to that, it seems to be possible to simply parse the tuple {'Authorization':'Bearer <TOKEN>'} as meta data like here. However, I noticed - as in the comment raised - upper case characters are not allowed.
with_call Method with credentials does not also not work
auth_creds = grpc.access_token_call_credentials(TOKEN)
channel = grpc.secure_channel('localhost:10000', auth_creds)
stub = foo_bar_pb2_grpc.ServiceStub(channel)
response = stub.Get.with_call(message_pb2.Message(), credentials=auth_creds)
>> TypeError: Argument 'channel_credentials' has incorrect type (expected grpc._cython.cygrpc.ChannelCredentials, got grpc._cython.cygrpc.MetadataPluginCallCredentials)
with_call Method with metadata does not also not work
metadata = 'Authorization', 'Bearer <TOKEN>'
channel = grpc.insecure_channel('localhost:10000')
stub = foo_bar_pb2_grpc.ServiceStub(channel)
response = stub.Get.with_call(message_pb2.Message(), metadata=metadata))
>> ValueError: too many values to unpack (expected 2)
Summarized: How do I authenticate my client with an access token?
As stated by the same docstring:
A CallCredentials may be composed with ChannelCredentials to always assert identity for every call over that Channel.
and a ChannelCredentials object is what your type error from grpc.secure_channel was screaming for.
To do that composition, you need to encrypt the channel with SSL/TLS.
Here is a client example with a token:
with open("server.crt", 'rb') as fd:
root_c = fd.read()
scc = grpc.ssl_channel_credentials(root_certificates=root_c)
tok = grpc.access_token_call_credentials("super-secret-token")
ccc = grpc.composite_channel_credentials(scc, tok)
with grpc.secure_channel("localhost:8080", ccc) as channel:
#... create stub and do the call
pass
For some more complete examples with SSL checkout this https://github.com/joekottke/python-grpc-ssl or this https://www.sandtable.com/using-ssl-with-grpc-in-python/. The official doc might also be helpful to look at.
A token is something you don't want anyone to sniff and I guess that's why you are required to use it in a secure_channel by the gRPC library.
I had a similar issue trying to send a custom header in a secure channel.
In my case, the problem came from using:
metadata = (('my-header-key', 'my-header-value'))
Instead of:
metadata = [('my-header-key', 'my-header-value')]
My code:
credentials = grpc.ssl_channel_credentials()
with grpc.secure_channel("<HOST>:<PORT>", credentials) as channel:
rpc_service = my_pb2_grpc.MyServiceStub(channel)
request = my_pb2.MyData(my_data='data')
metadata = [('my-header-key', 'my-header-value')]
response = rpc_service.MyMethod(request=request, metadata=metadata)
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