Google APIs Client Library for C++ A C++ library for client applications to access Google APIs.
Using OAuth 2.0

This document discusses how to obtain and use OAuth 2.0 credentials using the Google APIs Client Library for C++. It provides a high level overview of the components involved and some basic use cases.

The document Using OAuth 2.0 to Access Google APIs may provide useful supplemental material to understand how to use OAuth 2.0 for authorization works in general.

Contents

  1. Typical use case examples
    1. Creating and configuring an OAuth2AuthorizationFlow
    2. Obtaining an initial access code without a webserver
    3. Obtaining an initial access code with an embedded webserver
    4. Obtaining and refreshing credentials
  2. About authorization codes

Typical use case examples

These examples show how to use the core OAuth 2.0 components to make authorized calls into cloud APIs. The following snippet applies to all the examples in this section.

#include "googleapis/client/auth/file_credential_store.h"
#include "googleapis/client/auth/oauth2_authorization.h"
#include "googleapis/client/transport/http_authorization.h"

using googleapis_client::CredentialStore;
using googleapis_client::FileCredentialStoreFactory;
using googleapis_client::OAuth2AuthorizationFlow;
using googleapis_client::OAuth2Credential;
using googleapis_client::OAuth2RequestOptions;

Creating and configuring an OAuth2AuthorizationFlow

Typically flows are created from client secrets files. The Preparing to use the SDK section of the Getting Started document discusses how to obtain a client_secrets file. The Google APIs Console Help may also be of use for more information on creating a client secrets file.

The following snippet:

// We're passing in NULL here assuming that you have set
// HttpTransport::default_transport_factory. Otherwise instead pass
// a transport, such as CurlHttpTransportFactory::New().
flow_.reset(
    OAuth2AuthorizationFlow::MakeFlowFromClientSecretsPath(
        client_secrets_path, transport, &status));
CHECK(status.ok()) << status.error_message();

util::Status store_status;
string dir;
store_status
    = FileCredentialStoreFactory::GetSystemHomeDirectoryStorePath(&dir);
if (store_status.ok()) {
  FileCredentialStoreFactory store_factory(dir);
  flow_->ResetCredentialStore(
      store_factory.NewCredentialStore("CalendarSample", &store_status));
}
if (!store_status.ok()) {
  LOG(WARNING) << "Not adding a credential store: "
               << store_status.error_message();
}

flow_->set_default_scopes(CalendarService::SCOPES::CALENDAR);
flow_->mutable_client_spec()->set_redirect_uri(
    OAuth2AuthorizationFlow::kOutOfBandUrl);
flow_->set_authorization_code_callback(
    NewPermanentCallback(&PromptShellForAuthorizationCode, flow_.get()));

Getting an initial access code without a webserver

The following example is the most primitive way to obtain an authorization code where your application does not have an embedded web server to handle a redirect. It uses the OAuth2AuthorizationFlow::kOutOfBandUrl redirect, which just gives the resulting access token directly to the user to copy and paste back into the application.

static util::Status PromptShellForAuthorizationCode(
    OAuth2AuthorizationFlow* flow,
    const OAuth2RequestOptions& options,
    string* authorization_code) {
  string url = flow->GenerateAuthorizationCodeRequestUrlWithOptions(options);
  cout << "Enter the following url into a browser:\n" << url << endl;
  cout << endl;
  cout << "Enter the browser's response to confirm authorization: ";

  authorization_code->clear();
  cin >> *authorization_code;
  if (authorization_code->empty()) {
    return StatusCanceled("Canceled");
  } else {
    return StatusOk();
  }
}

Getting an initial access code with an embedded webserver

If your application has a webserver then you can have the OAuth 2.0 server give you the authorization code as a GET request to a URL served by your embedded server. You must register that URL with the application in the Google APIs Console.

The Google APIs Client Library for C++ comes with an embeddable HTTP server and some support for the time being, however these will likely change in future releases. It is expected that you have your own server or will have your own needs so the provided code is for testing, samples, and illustrative purposes. These classes have MongooseWebServer in the name and depend on the Mongoose web server.

Obtaining and refreshing credentials

The following snippet refreshes a credential for the given user.

util::Status RefreshCredentialForUser(
     const string& id, OAuth2Credential* credential) {
  OAuth2RequestOptions options;
  options.user_id = id;
  return flow_->RefreshCredentialWithOptions(options, credential);
}

About authorization codes

The OAuth 2.0 protocol requires a one-time Authorization Code confirming user consent -- the degree of access that the user has granted permission for the application to access. The OAuth 2.0 server can turn the authorization code into a temporary access token and permanent refresh token. Your application will be able to use the refresh token to automatically obtain access tokens the next time the user uses your program. However the first time, you will need to interact with the user to get explicit permission.

Users interact directly with the OAuth 2.0 server to grant permissions to your application. The OAuth2AuthorizationFlow::GenerateAuthorizationCodeRequestUrl method will return a suitable URL with all the necessary information encoded into it identifying your application and the desired permissions. The user will authenticate themselves with the OAuth 2.0 server using the Google Account that they are granting access to. When the user consents (or rejects) permission, the OAuth 2.0 server will inform you through the redirect_uri in the OAuth2ClientSpecthat you configured the flow with. For multi-user applications, you can add a state query parameter to the authorization code request URL and correlate the state parameter in the redirect response with your request so that you know which user the authorization code is for.