Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python gRPC client request only with bearer token

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?

like image 509
patientCoder Avatar asked Oct 27 '25 14:10

patientCoder


2 Answers

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.

like image 194
Smiths Avatar answered Oct 30 '25 13:10

Smiths


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)
like image 22
josmaf Avatar answered Oct 30 '25 15:10

josmaf