Warning: This page is about Google's older APIs, the Google Data APIs; it's relevant only to the APIs that are listed in the Google Data APIs directory, many of which have been replaced with newer APIs. For information about a specific new API, see the new API's documentation. For information about authorizing requests with a newer API, see Google Accounts Authentication and Authorization.
This document describes how to use the Google Data API client libraries to connect to Google's OAuth Authentication for Web Applications.
The OAuth interface allows a web-based application to access a Google service on behalf of a user. To maintain a high level of security, OAuth enables the application to get an access token without ever handling the user's account login information.
The Google Data API client libraries provide methods to help you use OAuth in your web application. Specifically, there are methods for constructing the acquiring a request token, authorizing the request token, and exchanging the authorized request token for an access token. The libraries also handle the necessary signing algorithms when making requests to a Google Data service.
Audience
This document is intended for programmers who want their web-based applications to access Google services on behalf of users, using the Google Data APIs client libraries.
This document assumes that you are familiar with the OAuth interface and the general process for incorporating OAuth into your web application. For a complete description of OAuth's protocol, see OAuth Authentication for Web Applications or the official specification at oauth.net.
Using 3-legged OAuth and Google Data APIs without the client libraries
If you want your web application to interact with a Google Data service using OAuth as an authorization method, then everything you need to know is in OAuth Authentication for Web Applications. There's no need to use the Google Data APIs client libraries if you don't want to.
Here's an outline of how your application might authenticate a user using OAuth:
- Your application makes a signed request to fetch an initial OAuth request token from the
OAuthRequestToken
endpoint. - Your application redirects the user to the appropriate
OAuthAuthorizeToken
URL to authorize the request token. - Upon granting access, the user is redirected back to your application (the
oauth_callback
url) - Your application sends a signed request to upgrade the authorized request token to an access token using the
OAuthGetAccessToken
endpoint.
The Google Data APIs client libraries simplify this authorization process by handling various details for you. This document explains how.
Registering your web application
OAuth requires that all API calls be digitally signed. Google supports the HMAC-SHA1
and RSA-SHA1
signature
methods. In order to sign requests, your application first needs to register with Google. Once you've registered, Google will provide
you with a consumer key (and secret for use with HMAC-SHA1
), and a place to upload a public certificate.
1. Registering your domain
Please follow the steps outlined in Registration for Web-Based Applications.
2. Creating a private key / public certificate pair (optional)
If you choose to use RSA-SHA1
as the oauth_signature_method
, you'll need to create a self-signing RSA
private key and public certificate pair. See Generating a self-signing private key and public certificate
(below) for examples on how to do that.
Working with 3-legged OAuth and the Google Data APIs: client library examples
The following sections show examples of using the Google Data APIs client library methods to follow the steps outlined in the
"Working With OAuth" section of the OAuth documentation. All examples in this document assume that your application host domain is example.com
.
Determining the scope of your data access
Each Google service defines a scope
value that determines a token's access to the user's data. The available scope values are listed in the Google Data FAQ. For example, to use the Documents List API, set the scope
to https://docs.google.com/feeds/
, as listed in the FAQ.
Note: Set the scope
value to the narrowest URL that permits the access you need. This lessens the chance of accidentally obtaining and leaking personal data. For example, if you want to access the current user's private Document List feed, use the scope https://docs.google.com/feeds/default/private/full
instead of a broader scope like https://docs.google.com/feeds/
, which provides access to all Document List feeds.
Multi-scoped tokens
To create tokens that access multiple Google Data APIs, separate each scope with a space character. The example below creates a token with access to both a user's Google Documents and Google Calendar data.
scope=https://www.google.com/calendar/feeds/ https://docs.google.com/feeds/
URL-encoding
Non-ASCII characters that appear in URLs, including colon, slash, and space, must be URL-encoded in order to be transmitted via HTTP. Google Data API client libraries automatically URL-encode parameters for you, so you can simply use non-URL-encoded strings when assigning values to parameters. For example, you can make the following assignment in your code:
scope=https://www.google.com/calendar/feeds/ https://docs.google.com/feeds/
When you call the client library, the
scope
parameter is then automatically URL-encoded to the following value:
https%3a%2f%2fwww.google.com%2fcalendar%2ffeeds%2f+https%3a%2f%2fdocs.google.com%2ffeeds%2f
Fetching a request token
Java
For HMAC-SHA1
, you need some way to persist the token secret (obtained in the response) in order to create an OAuth token object coming back
from the approval page. To do that, set a session variable or cookie.
import com.google.gdata.client.docs.*; import com.google.gdata.client.authn.oauth.*; String CONSUMER_KEY = "example.com"; String CONSUMER_SECRET = "abc123doremi"; GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET); oauthParameters.setScope("https://docs.google.com/feeds/"); oauthParameters.setOAuthCallback("http://www.example.com/UpgradeToken.jsp"); GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer()); oauthHelper.getUnauthorizedRequestToken(oauthParameters);
Using RSA-SHA1
, the oauth_token_secret
is unused so there's no need to persist the token secret.
import com.google.gdata.client.docs.*; import com.google.gdata.client.authn.oauth.*; String CONSUMER_KEY = "example.com"; GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); oauthParameters.setScope("https://docs.google.com/feeds/"); oauthParameters.setOAuthCallback("http://www.example.com/UpgradeToken.jsp"); PrivateKey privKey = getPrivateKey("/path/to/your/rsakey.pk8"); GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthRsaSha1Signer(privKey)); oauthHelper.getUnauthorizedRequestToken(oauthParameters); ... public static PrivateKey getPrivateKey(String privKeyFileName) { File privKeyFile = new File(privKeyFileName); FileInputStream fis = new FileInputStream(privKeyFile); DataInputStream dis = new DataInputStream(fis); byte[] privKeyBytes = new byte[(int) privKeyFile.length()]; dis.read(privKeyBytes); dis.close(); fis.close(); String BEGIN = "-----BEGIN PRIVATE KEY-----"; String END = "-----END PRIVATE KEY-----"; String str = new String(privKeyBytes); if (str.contains(BEGIN) && str.contains(END)) { str = str.substring(BEGIN.length(), str.lastIndexOf(END)); } KeyFactory fac = KeyFactory.getInstance("RSA"); EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(Base64.decode(str)); return fac.generatePrivate(privKeySpec); }
PHP
Using HMAC-SHA1
as the signature method:
require_once 'Zend/Oauth/Consumer.php'; session_start(); $CONSUMER_KEY = 'example.com'; $CONSUMER_SECRET = 'abc123doremi'; // Multi-scoped token. $SCOPES = array( 'https://docs.google.com/feeds/', 'https://spreadsheets.google.com/feeds/' ); $oauthOptions = array( 'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER, 'version' => '1.0', 'consumerKey' => $CONSUMER_KEY, 'consumerSecret' => $CONSUMER_SECRET, 'signatureMethod' => 'HMAC-SHA1', 'callbackUrl' => 'http://myapp.example.com/access_token.php', 'requestTokenUrl' => 'https://www.google.com/accounts/OAuthGetRequestToken', 'userAuthorizationUrl' => 'https://www.google.com/accounts/OAuthAuthorizeToken', 'accessTokenUrl' => 'https://www.google.com/accounts/OAuthGetAccessToken' ); $consumer = new Zend_Oauth_Consumer($oauthOptions); // When using HMAC-SHA1, you need to persist the request token in some way. // This is because you'll need the request token's token secret when upgrading // to an access token later on. The example below saves the token object as a session variable. if (!isset($_SESSION['ACCESS_TOKEN'])) { $_SESSION['REQUEST_TOKEN'] = serialize($consumer->getRequestToken(array('scope' => implode(' ', $SCOPES)))); }
Using RSA-SHA1
as the signature method:
require_once 'Zend/Crypt/Rsa/Key/Private.php'; require_once 'Zend/Oauth/Consumer.php'; session_start(); $CONSUMER_KEY = 'example.com'; $SCOPE = 'https://docs.google.com/feeds/'; $oauthOptions = array( 'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER, 'version' => '1.0', 'consumerKey' => $CONSUMER_KEY, 'consumerSecret' => new Zend_Crypt_Rsa_Key_Private(file_get_contents(realpath('/path/to/yourRSAPrivateKey.pem'))), 'signatureMethod' => 'RSA-SHA1', 'callbackUrl' => 'http://myapp.example.com/access_token.php', 'requestTokenUrl' => 'https://www.google.com/accounts/OAuthGetRequestToken', 'userAuthorizationUrl' => 'https://www.google.com/accounts/OAuthAuthorizeToken', 'accessTokenUrl' => 'https://www.google.com/accounts/OAuthGetAccessToken' ); $consumer = new Zend_Oauth_Consumer($oauthOptions); if (!isset($_SESSION['ACCESS_TOKEN'])) { $_SESSION['REQUEST_TOKEN'] = serialize($consumer->getRequestToken(array('scope' => $SCOPE))); }
Python
Using HMAC-SHA1
as the signature method:
If you're using the newer v2.0+ classes based on GDClient, use:
import gdata.gauth import gdata.docs.client CONSUMER_KEY = 'example.com' CONSUMER_SECRET = 'abc123doremi' SCOPES = ['https://docs.google.com/feeds/', 'https://www.google.com/calendar/feeds/'] # example of a multi-scoped token client = gdata.docs.client.DocsClient(source='yourCompany-YourAppName-v1') oauth_callback_url = 'http://%s/get_access_token' % self.request.host request_token = client.GetOAuthToken( SCOPES, oauth_callback_url, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET) # When using HMAC-SHA1, you need to persist the request_token in some way. # You'll need the token secret when upgrading to an access token later on. # In Google App Engine, you can use the AeSave helper: # gdata.gauth.AeSave(request_token, 'myKey')
Using RSA-SHA1
as the signature method:
... f = open('/path/to/yourRSAPrivateKey.pem') RSA_KEY = f.read() f.close() request_token = client.GetOAuthToken(SCOPES, oauth_callback_url, CONSUMER_KEY, rsa_private_key=RSA_KEY)
Alternatively, if you're using the older v1.0 classes based on GDataService, the calls are a bit different:
import gdata.auth import gdata.docs.service CONSUMER_KEY = 'example.com' CONSUMER_SECRET = 'abc123doremi' client = gdata.docs.service.DocsService(source='yourCompany-YourAppName-v1') client.SetOAuthInputParameters(gdata.auth.OAuthSignatureMethod.HMAC_SHA1, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET) req_token = client.FetchOAuthRequestToken() client.SetOAuthToken(req_token)
Using RSA-SHA1
as the signature method:
... f = open('/path/to/yourRSAPrivateKey.pem') RSA_KEY = f.read() f.close() client = gdata.docs.service.DocsService(source='yourCompany-YourAppName-v1') client.SetOAuthInputParameters(gdata.auth.OAuthSignatureMethod.RSA_SHA1, CONSUMER_KEY, rsa_key=RSA_KEY) SCOPES = ['https://docs.google.com/feeds/', 'https://www.google.com/calendar/feeds/'] # example of a multi-scoped token req_token = client.FetchOAuthRequestToken(scopes=SCOPES) client.SetOAuthToken(req_token)
.NET
Using HMAC-SHA1
as the signature method:
using Google.GData.Client; string CONSUMER_KEY = "example.com"; string CONSUMER_SECRET = "abc123doremi"; // Multi-scoped token. string SCOPE = "https://www.google.com/calendar/feeds/ https://www.google.com/m8/feeds/"; OAuthParameters parameters = new OAuthParameters() { ConsumerKey = CONSUMER_KEY, ConsumerSecret = CONSUMER_SECRET, Scope = SCOPE, Callback = "http://myapp.example.com/access_token", SignatureMethod = "HMAC-SHA1" } OAuthUtil.GetUnauthorizedRequestToken(parameters);
Using RSA-SHA1
as the signature method:
RSA-SHA1 is not supported yet.
Authorizing a request token
To authorize a request token, your application must redirect the user to the OAuthAuthorizeToken
URL, which prompts them to log into their Google account.
For more information on the OAuthAuthorizeToken
URL, see the
full OAuth Authentication for Web Applications.
To construct the OAuthAuthorizeToken
URL in your application, use the following for each client library. Note, these
samples build on the previous examples.
After constructing the approval page URL, your application can use it in a variety of ways to send the user to the
OAuthAuthorizeToken
handler. The most common approach is to redirect the user or display a link to that page.
Java
For HMAC-SHA1
:
String approvalPageUrl = oauthHelper.createUserAuthorizationUrl(oauthParameters); System.out.println(approvalPageUrl);
For RSA-SHA1
:
String approvalPageUrl = oauthHelper.createUserAuthorizationUrl(oauthParameters); System.out.println(approvalPageUrl);
PHP
// If on a G Suite domain, use your domain for the hd param (e.g. 'example.com'). $approvalUrl = $consumer->getRedirectUrl(array('hd' => 'default')); echo "<a href=\"$approvalUrl\">Grant access</a>";
Alternatively, you can simply redirect to the approval URL:
// If on a G Suite domain, use your domain for the hd param (e.g. 'example.com'). $consumer->redirect(array('hd' => 'default'));
Python
If you're using the newer v2.0+ classes based on GDClient, use:
# req_token is from previous call to client.GetOAuthToken() domain = None # If on a G Suite domain, use your domain (e.g. 'example.com'). self.redirect(request_token.generate_authorization_url(google_apps_domain=domain))
If you're using the older v1.0 classes based on GDataService, the process is a bit different.
# req_token is from previous call to client.FetchOAuthRequestToken() oauth_callback_url = 'http://%s/get_access_token' % self.request.host self.redirect(client.GenerateOAuthAuthorizationURL(callback_url=oauth_callback_url))
.NET
string authorizationUrl = OAuthUtil.CreateUserAuthorizationUrl(parameters); Console.WriteLine(authorizationUrl);
Extracting the token from the callback URL
When Google redirects back to your application, the oauth_token
is appended to the "oauth_callback_url
" URL as a query parameter.
Your application should then extract the token value from its URL query parameter and re-establish the oauth parameters.
The client libraries provide convenience methods for extracting the oauth_token
. These samples build on the previous examples.
Java
If you've chosen to persist the token secret in the callback URL (when using HMAC-SHA1
):
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET); GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer()); oauthHelper.getOAuthParametersFromCallback(request.getQueryString(), oauthParameters);
The only difference with RSA-SHA1
is the signing method:
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); PrivateKey privKey = getPrivateKey("/path/to/your/rsakey.pk8"); GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthRsaSha1Signer(privKey)); oauthHelper.getOAuthParametersFromCallback(request.getQueryString(), oauthParameters);
PHP
This step isn't necessary when using the PHP library.
Python
If you're using the newer v2.0+ classes based on GDClient, use:
# Recall request_token. In Google App Engine, use AeLoad(): # saved_request_token = gdata.gauth.AeLoad('myKey') request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, self.request.uri)
If you're using the older v1.0 classes based on GDataService, use:
oauth_token = gdata.auth.OAuthTokenFromUrl(self.request.uri) if oauth_token: oauth_token.secret = # TODO: recall saved request_token and set the token secret here. oauth_token.oauth_input_params = gdata.auth.OAuthInputParams( gdata.auth.OAuthSignatureMethod.HMAC_SHA1, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET) client.SetOAuthToken(oauth_token) else: print 'No oauth_token found in the URL'
The process is similar for RSA-SHA1
, but without the token secret:
oauth_token = gdata.auth.OAuthTokenFromUrl(self.request.uri) if oauth_token: oauth_token.oauth_input_params = gdata.auth.OAuthInputParams( gdata.auth.OAuthSignatureMethod.RSA_SHA1, CONSUMER_KEY, rsa_key=RSA_KEY) client.SetOAuthToken(oauth_token) else: print 'No oauth_token found in the URL'
.NET
If you've chosen to persist the token secret in the callback URL:
OAuthUtil.UpdateOAuthParametersFromCallback(url, parameters);
Upgrading to an access token
The last step in the OAuth token dance is to upgrade the authorized request token to a long-lived access token using the
OAuthGetAccessToken
URL, as described
in the full OAuth Authentication for Web Applications documentation.
Here are some examples using each of the client libraries:
Java
String accessToken = oauthHelper.getAccessToken(oauthParameters); // You can also pull the OAuth token string from the oauthParameters: // String accessToken = oauthParameters.getOAuthToken(); System.out.println("OAuth Access Token: " + accessToken); String accessTokenSecret = oauthParameters.getOAuthTokenSecret(); System.out.println("OAuth Access Token's Secret: " + accessTokenSecret);
PHP
if (!isset($_SESSION['ACCESS_TOKEN'])) { if (!empty($_GET) && isset($_SESSION['REQUEST_TOKEN'])) { $_SESSION['ACCESS_TOKEN'] = serialize($consumer->getAccessToken($_GET, unserialize($_SESSION['REQUEST_TOKEN']))); } }
Python
If you're using the newer v2.0+ classes based on GDClient, use:
# Upgrade the token and save in the user's datastore access_token = client.GetAccessToken(request_token) # If you're using Google App Engine, you can call the AeSave() method to save # the access token under the current logged in user's account. #gdata.gauth.AeSave(access_token, token_key)
If you're using the older v1.0 classes based on GDataService, use:
access_token = client.UpgradeToOAuthAccessToken() # calls SetOAuthToken() for you
If you're using gdata.gauth.AeSave()
on App Engine, the token and token secret will be stored for you under the current logged in user.
.NET
OAuthUtil.GetAccessToken(parameters); // If you want to extract the OAuth Token/TokenSecret from the OAuthParameters instance: string accessToken = parameter.Token; Console.WriteLine("OAuth Access Token: " + accessToken); string accessTokenSecret = parameter.TokenSecret; Console.WriteLine("OAuth Access Token's Secret: " + accessTokenSecret);
Note: If you're using HMAC-SHA1
, be sure to save the access token's token secret
alongside the token value in your database, otherwise you won't be able to properly reconstruct the oauth parameters for later use.
Using an access token
After you've obtained an access token, use the standard Google Data APIs client library calls to interact with the service. The library will take care of signing the requests and including the correct Authorization header for you. Typically, you'll be recalling the user's token from a cookie or database. These examples demonstrate how to reconstruct the oauth parameters and make a client library call.
Java
If you're using HMAC-SHA1
:
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET); oauthParameters.setOAuthToken(ACCESS_TOKEN); oauthParameters.setOAuthTokenSecret(TOKEN_SECRET); DocsService client = new DocsService("yourCompany-YourAppName-v1"); client.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer()); URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full"); DocumentListFeed resultFeed = client.getFeed(feedUrl, DocumentListFeed.class); for (DocumentListEntry entry : resultFeed.getEntries()) { System.out.println(entry.getTitle().getPlainText()); }
The difference with RSA-SHA1
is that you don't need to set the access token's secret and constructing the signer object is different:
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET); oauthParameters.setOAuthToken(ACCESS_TOKEN); PrivateKey privKey = getPrivateKey("/path/to/your/rsakey.pk8"); // See above for the defintion of getPrivateKey() DocsService client = new DocsService("yourCompany-YourAppName-v1"); client.setOAuthCredentials(oauthParameters, new OAuthRsaSha1Signer(privKey)); URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full"); DocumentListFeed resultFeed = client.getFeed(feedUrl, DocumentListFeed.class); for (DocumentListEntry entry : resultFeed.getEntries()) { System.out.println(entry.getTitle().getPlainText()); }
PHP
require_once 'Zend/Gdata/Docs.php'; if (isset($_SESSION['ACCESS_TOKEN'])) { $accessToken = unserialize($_SESSION['ACCESS_TOKEN']); } else { exit; } /* Or, you could set an existing token (say one stored from your database). For HMAC-SHA1: $accessToken = new Zend_Oauth_Token_Access(); $accessToken->setToken('1/AQfoI-qJDqkvvkf216Gc2g'); $accessToken->setTokenSecret('2c26GLW250tZiQ'); */ $httpClient = $accessToken->getHttpClient($oauthOptions); $client = new Zend_Gdata_Docs($httpClient, "yourCompany-YourAppName-v1"); // Retrieve user's list of Google Docs $feed = $client->getDocumentListFeed(); foreach ($feed->entries as $entry) { echo "$entry->title\n"; }
Python
This snippet assumes that you have already fetched an access token (using HMAC-SHA1
) and
are recalling that token key/secret for later use.
If you're using the newer v2.0+ classes based on GDClient, use:
client = gdata.docs.client.DocsClient(source='yourCo-yourAppName-v1') client.auth_token = gdata.gauth.OAuthHmacToken(CONSUMER_KEY, CONSUMER_SECRET, TOKEN, TOKEN_SECRET, gdata.gauth.ACCESS_TOKEN) feed = client.GetDocList() for entry in feed.entry: print entry.title.text
If you're using the older v1.0 classes based on GDataService, use:
client = gdata.docs.service.DocsService(source='yourCompany-YourAppName-v1') client.SetOAuthInputParameters(SIG_METHOD, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET) # the token key and secret should be recalled from your database client.SetOAuthToken(gdata.auth.OAuthToken(key=TOKEN, secret=TOKEN_SECRET)) feed = client.GetDocumentListFeed() for entry in feed.entry: print entry.title.text
.NET
If you're using HMAC-SHA1
:
OAuthParameters parameters = new OAuthParameters() { ConsumerKey = CONSUMER_KEY, ConsumerSecret = CONSUMER_SECRET, Token = ACCESS_TOKEN, TokenSecret = TOKEN_SECRET } GOAuthRequestFactory requestFactory = new GOAuthRequestFactory("writely", APPLICATION_NAME, parameters); DocsService service = new DocsService(APPLICATION_NAME); service.RequestFactory = requestFactory; DocumentsListQuery query = new DocumentsListQuery(); DocumentsFeed feed = service.Query(query); foreach (DocumentEntry entry in feed.Entries) { Console.WriteLine(entry.Title.Text); }
The difference with RSA-SHA1
is that you don't need to set the access token's secret and constructing the signer object is different:
RSA-SHA1 is not supported yet.
Additional 3-Legged OAuth Resources and Samples
- OAuth examples on the Google Data API Tips Blog
- Article: Using OAuth with the Google Data APIs
- Python client library sample
- Python client library Google App Engine sample
- Java client library sample
- Java client library Google App Engine sample
- Zend PHP client library sample
- OAuth Authentication for Web Applications documentation
- OAuth.net documentation
2 Legged OAuth
2 legged OAuth allows trusted applications to access users' Google Data without their direct involvement. Two key groups can use two-legged OAuth:
G Suite domain administrators: Administrators can build scripts and custom applications that manage the user data for their domain through Google Data APIs. To learn about managing the key and secret that's associated with your G Suite domain, and granting global access control, see "Managing the OAuth key and secret".
Third-party software vendors: Vendors may offer applications that use two-legged OAuth to integrate with G Suite. Access for the 3rd party applications can be granted on the Manage API client page or by installing from the G Suite Marketplace.
An access token is not required as per the normal authorization flow (also referred to as 3-legged OAuth).
The following client library samples demonstrate how to setup your client to use 2 Legged OAuth using HMAC-SHA1
.
Java
import com.google.gdata.client.docs.*; import com.google.gdata.client.authn.oauth.*; String CONSUMER_KEY = "example.com"; String CONSUMER_SECRET = "abc123doremi"; GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); oauthParameters.setOAuthConsumerKey(CONSUMER_KEY); oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET); DocsService client = new DocsService("yourCompany-YourAppName-v1"); client.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer()); // Retrieve user's list of Google Docs String user = "any.user@anydomain.com"; URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full" + "?xoauth_requestor_id=" + user); DocumentListFeed resultFeed = client.getFeed(feedUrl, DocumentListFeed.class); for (DocumentListEntry entry : resultFeed.getEntries()) { System.out.println(entry.getTitle().getPlainText()); }
PHP
require_once 'Zend/Oauth/Consumer.php'; require_once 'Zend/Gdata/Docs.php'; $CONSUMER_KEY = 'example.com'; $CONSUMER_SECRET = 'abc123doremi'; $USER = 'any.user@anydomain.com'; $oauthOptions = array( 'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER, 'version' => '1.0', 'signatureMethod' => 'HMAC-SHA1', 'consumerKey' => $CONSUMER_KEY, 'consumerSecret' => $CONSUMER_SECRET ); $consumer = new Zend_Oauth_Consumer($oauthOptions); $token = new Zend_Oauth_Token_Access(); $httpClient = $token->getHttpClient($oauthOptions); $client = new Zend_Gdata_Docs($httpClient); // Retrieve user's list of Google Docs $feed = $client->getDocumentListFeed('https://docs.google.com/feeds/default/private/full?xoauth_requestor_id=' . urlencode($USER)); foreach ($feed->entries as $entry) { echo "$entry->title\n"; }
Python
If you're using the newer v2.0+ classes based on GDClient, use:
import gdata.gauth import gdata.docs.client CONSUMER_KEY = 'example.com' CONSUMER_SECRET = 'abc123doremi' requestor_id = 'any.user@anydomain.com' client = gdata.docs.client.DocsClient(source='yourCompany-YourAppName-v1') client.auth_token = gdata.gauth.TwoLeggedOAuthHmacToken( CONSUMER_KEY, CONSUMER_SECRET, requestor_id) # Retrieve user's list of Google Docs feed = client.GetDocList() for entry in feed.entry: print entry.title.text
If you're using the older v1.0 classes based on GDataService, use:
import gdata.auth import gdata.docs.service CONSUMER_KEY = 'example.com' CONSUMER_SECRET = 'abc123doremi' SIG_METHOD = gdata.auth.OAuthSignatureMethod.HMAC_SHA1 requestor_id = 'any.user@anydomain.com' client = gdata.docs.service.DocsService(source='yourCompany-YourAppName-v1') client.SetOAuthInputParameters(SIG_METHOD, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET, two_legged_oauth=True, requestor_id=requestor_id) # Retrieve user's list of Google Docs feed = client.GetDocumentListFeed() for entry in feed.entry: print entry.title.text # Change to another user on your domain client.GetOAuthInputParameters().requestor_id = 'another.user@example.com'
.NET
using Google.GData.Client; using Google.GData.Documents; // Create an OAuth factory to use GOAuthRequestFactory requestFactory = new GOAuthRequestFactory("writely", "yourCompany-YourAppName-v1"); requestFactory.ConsumerKey = "example.com"; requestFactory.ConsumerSecret = "abc123doremi"; String user = "any.user@anydomain.com"; DocumentsService client = new DocumentsService("yourCompany-YourAppName-v1"); client.RequestFactory = requestFactory; // Retrieve user's list of Google Docs DocumentsListQuery query = new DocumentsListQuery(); query.Uri = new OAuthUri("https://docs.google.com/feeds/default/private/full", user, requestFactory.ConsumerKey); DocumentsFeed feed = client.Query(query); foreach (DocumentEntry entry in feed.Entries) { Console.WriteLine(entry.Title.Text); }
Additional 2-Legged OAuth Resources and Samples
- 2 legged OAuth examples on the Google Data API Tips Blog
- Java client library 2-Legged OAuth sample
- Python client library TwoLeggedOAuthExample (for client.py classes) or 2_legged_oauth sample (for service.py classes)
- .NET client library 2-Legged OAuth sample
- 2 legged OAuth documentation
Generating a self-signing private key and public certificate
The private key is used to generate a signature, which must be included with each request. The public key embedded in the certificate is used by Google to verify the signature. The public key must be a 1024-bit RSA key encoded in an X.509 certificate in PEM format. The certificate should be sent to Google at time of registration.
The following sections provide examples of how to generate keys and certificates using two particular tools: the OpenSSL
utility and Java's keytool
utility.
These examples are not specific to the Google Data APIs; you can use the same utilities to generate keys for any purpose.
The examples assume that your company is named My_Company, and is located in Mountain View, California, US, with domain name example.com.
Generating keys using OpenSSL
To create a pair of RSA keys and the corresponding certificate, you could use the following command:
# Generate the RSA keys and certificate openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \ '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \ myrsakey.pem -out /tmp/myrsacert.pem
Warning: Including the -nodes
parameter creates a private key without a password to protect it.
However, you should consider omitting this parameter for added security.
The -sha1
parameter specifies that the key will be used to generate SHA1 signatures.
The -subj
parameter specifies the identity of the application that the certificate represents.
The -keyout
parameter specifies the file that will contain the keys.
This file contains sensitive information and should be protected and not shared with anyone.
The -out
parameter specifies the file that will contain the certificate in PEM format
(which can be sent to Google while registering).
Generating keys for the .NET client
The .NET framework doesn't understand keys or certificates stored in the PEM format. Therefore, an additional step is needed once you have created the .pem file:
openssl pkcs12 -export -in test_cert.pem -inkey myrsacert.pem -out myrsacert.pfx -name "Testing Certificate"
This step generates a PFX file from your private key and certificate. This file can be imported into the .NET client library to digitally sign requests made to the Google Data APIs.
Generating keys for the Java client
The Java client accepts private keys in the PKCS#8 format. After generating a key/cert using the directions above, create a .pk8 file from your generated .pem file:
openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8
Alternatively, you can use the Java key store and the keytool utility to create a pair of RSA keys and the corresponding certificate. Use the following command:
# Generate the RSA keys and certificate keytool -genkey -v -alias Example -keystore ./Example.jks\ -keyalg RSA -sigalg SHA1withRSA\ -dname "CN=www.example.com, OU=Engineering, O=My_Company, L=Mountain View, ST=CA, C=US"\ -storepass changeme -keypass changeme
Warning: "changeme
" is not a good password; this is just an example.
The -dname
parameter specifies the identity of the application that the certificate represents. The -storepass
parameter specifies the password to protect the keystore. The -keypass
parameter specifies the password to protect the private key.
To write the certificate to a file that can be used in the ManageDomains tool, use the following command:
# Output the public certificate to a file keytool -export -rfc -keystore ./Example.jks -storepass changeme \ -alias Example -file mycert.pem