Re: [grpc-io] Get google's from grpc C++

985 views
Skip to first unread message

Nicolas Noble

unread,
Aug 24, 2016, 10:09:54 PM8/24/16
to Manh Tran, grpc.io

It depends on your platform. But basically, you need to use and authenticate with the gcloud command line tool, which will create the token for you that will be read by grpc automatically.

See https://cloud.google.com/sdk/gcloud/reference/auth/login about how to do that.


On Wed, Aug 24, 2016, 18:43 Manh Tran <manht...@gmail.com> wrote:
Hi,

I'm writing a gRPC client connect to google cloud speech. I think it needs an access token to connect to google cloud. Please tell me how to get an access token OAuth2 on gRPC C++.

Thanks.

--
You received this message because you are subscribed to the Google Groups "grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+u...@googlegroups.com.
To post to this group, send email to grp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/25d7e7d5-8d67-4f0c-96bd-775a9397e4d4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Paul Grosu

unread,
Aug 24, 2016, 10:37:33 PM8/24/16
to grpc.io, manht...@gmail.com

To add to Nico's answer, you can directly fetch the token by using https://github.com/google/oauth2l for a specific scope you are interested in, like this for the cloud platform (which the Speech API is part of):

$ ~/.local/bin/oauth2l fetch -f bare cloud-platform


Hope it helps,
`p

Manh Tran

unread,
Aug 25, 2016, 1:05:08 AM8/25/16
to grpc.io
Are there any way to get token within my C++ program?

Thanks.

Manh Tran

unread,
Aug 25, 2016, 1:07:07 AM8/25/16
to grpc.io, manht...@gmail.com
Are there any way to get token within my C++ program?

Thanks.

Paul Grosu

unread,
Aug 25, 2016, 1:16:13 AM8/25/16
to grpc.io

Of course :)  You have two options:

1) Use the Google APIs Client Library for C++:

  https://google.github.io/google-api-cpp-client/latest/guide/oauth2.html

2) Or just use execve system call to run an external program to provide the token :)

~p

Manh Tran

unread,
Aug 25, 2016, 3:29:47 AM8/25/16
to grpc.io
Could you show me detail using the Google APIs Client Library for C++?

Thank you so much.

Paul Grosu

unread,
Aug 25, 2016, 5:10:02 PM8/25/16
to grpc.io
Gladly :)  Check out webflow_sample_main.cc example on line 386:

   string new_access_token = credential->access_token().as_string();

Hope it helps,
~p

Manh Tran

unread,
Aug 25, 2016, 10:54:35 PM8/25/16
to grpc.io
It seem only read access_token from OAuth2Credential* credential. Currently, I've credentials-key.json. Are there any way using this credentials-key.json file to get access token from google's server.

Thanks.

Paul Grosu

unread,
Aug 26, 2016, 1:40:43 AM8/26/16
to grpc.io
Hi Manh,

By the way gRPC does this automatically via the GOOGLE_APPLICATION_CREDENTIALS environment variable defined in grpc_security_constants.h:

  /* Environment variable that points to the google default application
  credentials json key or refresh token. Used in the
  grpc_google_default_credentials_create function. */
  #define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"

Keep in mind if you go via the the GoogleDefaultCredentials() function - as Yang previously suggested - it basically performs several checks to find a way to authenticate you.  Basically the call in secure_credentials.cc calls grpc_google_default_credentials_create()as such:

  std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
    GrpcLibraryCodegen init;  // To call grpc_init().
    return WrapChannelCredentials(grpc_google_default_credentials_create());
  }


Which  grpc_google_default_credentials_create() goes through a multitude of checks in google_default_credentials.c:

  grpc_channel_credentials *grpc_google_default_credentials_create(void) {
    ...
    /* First, try the environment variable. */
    err = create_default_creds_from_path(
        gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR), &call_creds);
        ...

    /* Then the well-known file. */
    err = create_default_creds_from_path(
        grpc_get_well_known_google_credentials_file_path(), &call_creds);
        ...

    /* At last try to see if we're on compute engine (do the detection only once
       since it requires a network test). */
    if (!compute_engine_detection_done) {
      int need_compute_engine_creds = is_stack_running_on_compute_engine();
      compute_engine_detection_done = 1;
      if (need_compute_engine_creds) {
        call_creds = grpc_google_compute_engine_credentials_create(NULL);
      ...
  }

Then create_default_creds_from_path() performs these two checks:

  /* First, try an auth json key. */
  key = grpc_auth_json_key_create_from_json(json);
  ...

  /* Then try a refresh token if the auth json key was invalid. */
  token = grpc_auth_refresh_token_create_from_json(json);
  ...


And the last function above looks up the stored gcloud credentials:

  char *grpc_get_well_known_google_credentials_file_path(void) {
    if (creds_path_getter != NULL) return creds_path_getter();
    return grpc_get_well_known_google_credentials_file_path_impl();
  }

The returned function call is in credentials_posix.c:

  gpr_asprintf(&result, "%s/.config/%s/%s", home,
               GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY,
               GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE);

And the two above variables are stored in google_default_credentials.h:

  #define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud"
  #define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \
    "application_default_credentials.json"


If you tried to see if you have this file - which you will by running gcloud beta auth application-default login - you will see the following directory as constructed above (the one below is for how it looks for me):

  $ ls ~/.config/gcloud/application_default_credentials.json
  /home/pgrosu/.config/gcloud/application_default_credentials.json
  $


And sure it is possible via the Google APIs Client Library for C++.  In the example file you'll notice the following on lines 657-661:

    googleapis::util::Status status;
    flow_.reset(OAuth2AuthorizationFlow::MakeFlowFromClientSecretsPath(
        FLAGS_client_secrets_path,
        config_->NewDefaultTransportOrDie(),
        &status));

I think you might also find the following links helpful:

https://developers.google.com/identity/protocols/OAuth2

http://google.github.io/google-api-cpp-client/latest/doxygen/classgoogleapis_1_1client_1_1OAuth2AuthorizationFlow.html

http://google.github.io/google-api-cpp-client/latest/doxygen/classgoogleapis_1_1client_1_1OAuth2Credential.html

Hope it helps,
Paul
Message has been deleted

Paul Grosu

unread,
Aug 26, 2016, 4:27:40 AM8/26/16
to grpc.io
Dear Manh,

I'm assuming you got the JSON file from the Google console, so just assign the path of the file to the environmental variable like this in shell - as described here:

  export GOOGLE_APPLICATION_CREDENTIALS=/path/to/keyfile.json

And your gRPC application will take care of the rest by looking for this environment variable.  You don't need to specify a token - it really is that simple.

Paul


On Friday, August 26, 2016 at 3:49:26 AM UTC-4, Manh Tran wrote:
Dear Paul,

The my credentials-key.json have format:
{
  "type": "service_account",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
}

In my C++ program, I would like to using directly this information to get token from google's. Please show me how to do it.

Thanks.

Manh Tran

unread,
Aug 26, 2016, 4:46:22 AM8/26/16
to grpc.io
Dear Paul,

I've got JSON file from Google console. I've also export GOOGLE_APPLICATION_CREDENTIALS and use the code following to connect google cloud speech to recognize streaming audio. But it seem google cloud not response.
..
using google::cloud::speech::v1beta1::Speech;

class GoogleClient {
 public:
GoogleClient(std::shared_ptr<Channel> channel)
      : stub_(Speech::NewStub(channel)) {}
 private:
  std::unique_ptr<Speech::Stub> stub_;
};

int main(int argc, char** argv) {

auto channel_creds = grpc::GoogleDefaultCredentials();
auto channel = grpc::CreateChannel("speech.googleapis.com:443", channel_creds);
GoogleClient ggclient(channel);
..
}

I think, it need use the code:

grpc::Status GetMetadata(
      grpc::string_ref service_url, grpc::string_ref method_name,
      const grpc::AuthContext& channel_auth_context,
      std::multimap<grpc::string, grpc::string>* metadata) override {
    metadata->insert(std::make_pair("Authorization", ticket_));
    return grpc::Status::OK;
  }

 private:
  grpc::string ticket_;
};
..
auto ssl_channel = grpc::SslCredentials(grpc::SslCredentialsOptions());
//get Access Token?
auto call_creds = grpc::MetadataCredentialsFromPlugin(
   std::unique_ptr<grpc::MetadataCredentialsPlugin>(
       new MyCustomAuthenticator("Access Token")));
//# CompositeChannelCredentials
auto channelComposite = grpc::CompositeChannelCredentials(ssl_channel, call_creds);
//# Create channel
auto channel = grpc::CreateChannel("speech.googleapis.com:443", channelComposite);

But I don't know how to get access token. Please help me.

Thanks.

Paul Grosu

unread,
Aug 26, 2016, 4:59:21 PM8/26/16
to grpc.io

Dear Manh,

I have never worked with the Speech APIs, but after downloading, compiling the googleapis on GitHub for the Speech API - and studying the proto-generated code - I was able to put together and compile the following client.cc code with no problem.

#include <google/cloud/speech/v1/cloud_speech.pb.h>
#include <google/cloud/speech/v1/cloud_speech.grpc.pb.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include <grpc++/support/status.h>
#include <grpc/grpc.h>
#include <iostream>


int main(int argc, char** argv) {
  auto stub = ::google::cloud::speech::v1::Speech::NewStub(
      ::grpc::CreateChannel("speech.googleapis.com:443",
                          ::grpc::GoogleDefaultCredentials()));

  ::grpc::ClientContext context;

  return 0;
}

Here's how I downloaded, compiled the proper protos and then the client.cc code:

$ git clone https://github.com/googleapis/googleapis
$ cd googleapis
$ make
$ cd gens
$ g++ -c -std=c++11 -I/home/pgrosu/apps/protobuf/include -I../../include -I. ./google/genomics/v1/*cc
$ g++ -c -std=c++11 -I/home/pgrosu/apps/protobuf/include -I../../include -I. ./google/rpc/*cc
$ g++ -c -std=c++11 -I/home/pgrosu/apps/protobuf/include -I../../include -I. ./google/api/*cc
$ cd ..
$ g++ -std=c++11 -L/usr/lib -L../libs/opt -L/home/pgrosu/apps/protobuf/lib -I./gens -I/home/pgrosu/apps/protobuf/include -I../include -lgrpc++ -lprotobuf -lgrpc -lgpr -lboringssl client.cc gens/*.o -o client


You might benefit from also combining what you see in the examples provided at the following link in Java, with the protobuf generated code for the Speech API from googleapis:

https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/speech/grpc

Now for some tough love, and please don't take this the wrong way since it will help you - as it was a hard lesson I had to learn myself.  Having worked with public Google APIs/tools/etc expect things to change a lot, and less so the standards they are based on (i.e. HTTP/2, RPC lifecycle, etc.).  Sometimes things will change with or without documentation - and sometimes with reasons not publicly disclosed - and you should feel comfortable with that.  Having access to the code is a blessing - and a wonderful service by the Google team - so take it as a way to learn and infer the design that the API might have been based on.  Try to only rely on the standards and code.  Though we as a community would be happy to help you here, it would be good if you could try to figure things on your own first.  Try to study any/all piece(s) of code and why they were implemented and work a certain way.  After trying many times and have exhausted all possibilities then ask, but try to get into the habit when working with Google APIs/tools to figure out many things on your own, by changing code, testing endpoints, etc.  Keep in mind that it took me more than a year of studying the gRPC code to put some of the pieces together, as many things were only documented in the code and sometimes not even that.  The Google Team is fantastic in helping us with this project, but many times they are working on overdrive to just get things done, and might not always have the time.  Keep in mind that this project recently jumped from version 0.15 to 1.0, and it has many layers of complexity.  So take this as a positive challenge for yourself :)

Hope it helps,
Paul
Reply all
Reply to author
Forward
0 new messages