Skip to content
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 add Channel Credentials? #84

Closed
maitham opened this issue Jul 22, 2019 · 3 comments
Closed

How to add Channel Credentials? #84

maitham opened this issue Jul 22, 2019 · 3 comments

Comments

@maitham
Copy link

maitham commented Jul 22, 2019

I currently have the following code:

composite_credentials = grpc.composite_channel_credentials(
            ssl_credentials, google_auth_credentials
        )
Channel(host, port, ssl=composite_credentials, loop=loop)

This doesn't work as this returns a composite ChannelCredentials object as per https://www.grpc.io/docs/guides/auth/ . Is this currently supported? Or should I try to get the headers required for authenticating requests to google?

@vmagamedov
Copy link
Owner

grpclib currently has only basic building blocks to perform authentication. Vendor-specific auth mechanisms (Google) aren't supported because I'm not using these services and I don't know the best way to implement this functionality.

If you want to use certificate-based auth – use ssl option when create Channel:

Channel(..., ssl=custom_ssl_context)

This ssl option can be True or instance of the ssl.SSLContext class. So it is not possible to pass your composite_credentials to this option. I have an example of how to perform mutual TLS auth: examples/mtls/client.py, maybe this will help. And probably I have to add more documentation about TLS authentication.

If you want to use token-based auth – make sure you're using secure connection (Channel(..., ssl=True)), and send auth token with request metadata. There is two ways to send auth token in request metadata:

Can you provide an example of how to authenticate with Google using existing functionality in grpclib I mentioned above? Maybe I can add more helpers into grpclib and/or document this properly with examples.

@maitham
Copy link
Author

maitham commented Jul 23, 2019

I'm trying to use the auth token method. However with and without a token I get the following error (<Status.UNIMPLEMENTED: 12>, "Received :status = '404'") .

Proto File - which I have regenerated using the python3 -m grpc_tools.protoc -I. --python_out=. --mypy_out=. --python_grpc_out=. cloud_speech.proto

import asyncio
import grpc
import wave
from grpclib.client import Channel, Stream
from cloud_speech_grpc import SpeechStub
from cloud_speech_pb2 import (
    RecognitionConfig,
    RecognitionAudio,
    RecognizeRequest,
)
from gjwt import get_token


class GoogleGrpcClient():
    def __init__(
        self, loop: asyncio.AbstractEventLoop
    ) -> None:
        self.channel = Channel("speech.googleapis.com",
                               "443", ssl=True, loop=loop)
        fn = ./creds.json"
        err, token = get_token(fn)
        self.token = token

    @property
    def _grpc_stub(self):
        return SpeechStub(self.channel)

    @property
    def grpc_config(self) -> RecognitionConfig:
        return RecognitionConfig(encoding=1,
                                 sample_rate_hertz=16000,
                                 language_code="en-GB"
                                 )

    def grpc_audio(self, audio: bytes) -> RecognitionAudio:
        return RecognitionAudio(content=audio)

    async def recognize(self, audio: bytes) -> str:
        return await self._grpc_stub.Recognize(
            RecognizeRequest(
                config=self.grpc_config,
                audio=self.grpc_audio(audio),
            ),
            metadata={"authorization": "Bearer " + self.token}
        )


async def get_transcription():
    fn = "../trimmed.wav"
    fp = wave.open(fn)
    frames = fp.getnframes()
    data = fp.readframes(frames)
    loop = asyncio.get_event_loop()
    client = GoogleGrpcClient(loop)
    try:
        resp = await client.recognize(data)
        print("RESPONSE", resp)
    except Exception as e:
        print("ERROR", e)

loop = asyncio.get_event_loop()
loop.run_until_complete(get_transcription())

@vmagamedov
Copy link
Owner

Turns out that Google detects gRPC protocol by reading content-type header:

  • I'm getting :status 404 when I send content-type application/grpc+proto
  • I'm getting proper grpc-status when I send content-type application/grpc

But gRPC protocol says that both variants are valid: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md

Unfortunately grpclib doesn't allow you to set your custom content-type header value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants