AuthSub in the Google Data Protocol Client Libraries

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 AuthSub Authentication for Web Applications.

The AuthSub interface allows a web-based application to access a Google service on behalf of a user. To maintain a high level of security, the AuthSub interface enables the application to get an authentication token without ever handling the user's account login information.

The Google Data API client libraries provide methods to help you use AuthSub in your web application. Specifically, there are methods for constructing the request URL, acquiring a single-use authentication token, exchanging the single-use token for a session token, and signing the request.

Note: The JavaScript client library has its own flavor of AuthSub, called AuthSubJS. For information on how to use AuthSubJS in your JavaScript applications, see Using "AuthSub" Authentication with the JavaScript Client Library.

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 AuthSub interface and the general process for incorporating AuthSub into your web application. For a complete description of AuthSub's protocol, see AuthSub Authentication for Web Applications.

Using AuthSub and Google Data APIs without the client libraries

If you want your web application client to interact with a Google Data service using AuthSub as an authentication system, then everything you really need to know is in AuthSub Authentication for Web Applications. You don't 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 AuthSub:

Your application constructs the appropriate AuthSub URL and then sends the user to that URL so they can log in; the AuthSub system sends the user back to the URL on your site that you specified, and returns a one-time-use token; your application optionally exchanges that token for a session token; then your application sends the token in the Authorization header with each request that the application sends to the service.

The Google Data APIs client libraries simplify this authorization process by handling various details for you. This document explains how.

Working with AuthSub and the Google Data APIs: client library examples

This section shows an example of using the Google Data APIs client library methods to follow the steps outlined in the "Working With AuthSub" section of the AuthSub documentation.

In this example, we're integrating the AuthSub interface into a web application that interacts with Google Calendar (although you don't need to know anything about Google Calendar to follow the example). The example assumes the web application is hosted at example.com.

Decide what type of token to use (session=0 or session=1)

You can choose to use single-use tokens (session=0) or session tokens (session=1). This document will use session tokens, as they are more useful in applications that will make multiple API requests. As discussed in the AuthSub documentation, if you decide to use session tokens in your web application, you'll need to manage token storage yourself. This document does not cover token management. Also note that tokens requested with session=0 can't be later exchanged (upgraded) to a long-lived session token.

Decide whether to register your web application (secure=0 or secure=1)

AuthSub can be used in three different modes, unregistered, registered, and registered with enchanced security. The remainder of this document will refer to the last option as secure AuthSub. Though unregistered/registered mode is simpler to set up than secure AuthSub, Google encourages you to use secure tokens for their enchanced security.

How to register

Choosing Registration for Web-Based Applications gives your application the following benefits:

  1. A higher level of security.
  2. Being trusted by Google (no warning is displayed to the user on the Google Authorization page).

Registered + Secure AuthSub

If you decide on secure AuthSub, you'll need to create a self-signing RSA private key and public certificate pair in addition to registering your web application. See Generating keys and certificates for use with registered mode (below) for examples of creating X.509 certificates.

Determine the scope of your data access

Each Google service defines a scope value which determines (and possibly narrows) a token's access to the user's data. See the FAQ for the list of available scope values.

Since we decided to interact with the Google Calendar API, the scope should be http://www.google.com/calendar/feeds/.

Note: Always set the scope value to the broadest URL possible unless you have need for a finer restriction. For example, a narrower scope like scope=http://www.google.com/calendar/feeds/default/allcalendars/full will restrict the token's access to just the allcalendars/full feed. Using scope=http://www.google.com/calendar/feeds/ will allow access to all of Calendar's feeds: http://www.google.com/calendar/feeds/*.

Multi-scoped tokens

To create tokens that access multiple Google Data APIs, seperate each scope with a url-encoded space. The example below creates a token which will have access to both a user's Google Contacts and Google Calendar data.

scope=http://www.google.com/calendar/feeds/%20http://www.google.com/m8/feeds/

Request a single-use authentication token

To acquire an AuthSub token for a given user and a given service, your application must redirect the user to the AuthSubRequest URL, which prompts them to log into their Google account. (For more information on the AuthSubRequest URL, see the full AuthSub Authentication for Web Applications.)

To construct the AuthSubRequest URL in your application, use the following for each client library:

Java

import com.google.gdata.client.*;

String nextUrl = "http://www.example.com/RetrieveToken.jsp";
String scope = "http://www.google.com/calendar/feeds/";
boolean secure = false;  // set secure=true to request secure AuthSub tokens
boolean session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);

If you want to authenticate users on your G Suite domain:

import com.google.gdata.client.*;

String hostedDomain = "example.com";
String nextUrl = "http://www.example.com/RetrieveToken.jsp";
String scope = "http://www.google.com/calendar/feeds/";
boolean secure = false;  // set secure=true to request AuthSub tokens
boolean session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);

.NET

using Google.GData.Client;

String nextUrl = "http://www.example.com/RetrieveToken.aspx";
String scope = "http://www.google.com/calendar/feeds/";
bool secure = false; // set secure=true to request secure AuthSub tokens
bool session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);

If you want to authenticate users on your G Suite domain:

using Google.GData.Client;

String hostedDomain = "example.com";
String nextUrl = "http://www.example.com/RetrieveToken.aspx";
String scope = "http://www.google.com/calendar/feeds/";
bool secure = false; // set secure=true to request secure AuthSub tokens
bool session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);

PHP

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');

$nextUrl = 'http://www.example.com/RetrieveToken.php';
$scope = 'http://www.google.com/calendar/feeds/';
$secure = 0;  // set $secure=1 to request secure AuthSub tokens
$session = 1;
$authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session);

If you want to authenticate users on your G Suite domain:

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');

$hostedDomain = 'example.com';
$nextUrl = 'http://www.example.com/RetrieveToken.php';
$scope = 'http://www.google.com/calendar/feeds/';
$secure = 0;  // set $secure=1 to request secure AuthSub tokens
$session = 1;
$authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session) . '&hd=' . $hostedDomain;

Python

import gdata.auth

next = 'http://www.example.com/RetrieveToken.pyc'
scope = 'http://www.google.com/calendar/feeds/'
secure = False  # set secure=True to request secure AuthSub tokens
session = True
auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session)

If you want to authenticate users on your G Suite domain:

import gdata.auth

hosted_domain = 'example.com'
next = 'http://www.example.com/RetrieveToken.pyc'
scope = 'http://www.google.com/calendar/feeds/'
secure = False  # set secure=True to request secure AuthSub tokens
session = True
auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session, domain=hosted_domain)

After constructing the "next" URL, your application can use it in a variety of ways to send the user to the AuthSubRequest handler. The most common approach is to display a page that tells the user that they need to follow a link to authorize your application to access their Google account; then attach the request URL to the link. For example, you could output the following string in your web app:

String authorizationUrl =
        "<p>MyApp needs access to your Google Calendar account to read your Calendar feed. " +
        "To authorize MyApp to access your account, <a href=\"" + authSubUrl + "\">log in to your account</a>.</p>";

The user follows the link to the AuthSub page at Google, and logs in. The AuthSub system then redirects the user back to your application, using the "next" URL you provided.

Extract the single-use token

When Google redirects back to your application, the token is appended to the "next" URL as a query parameter. In the case of the examples above, after the user logs in, Google redirects to a URL like http://www.example.com/RetrieveToken?token=DQAADKEDE. Your application should extract the token value from its URL query parameter.

If your application set an authentication cookie in the user's browser before sending them to the AuthSub system, then when Google redirects back to the "next" URL, your application can read the authentication cookie to recognize which user has arrived at that URL. You can use such a cookie to associate a user ID in your application with the AuthSub token retrieved from Google.

The client libraries provide convenience methods for extracting the single-use token:

Java

String singleUseToken = AuthSubUtil.getTokenFromReply(httpServletRequest.getQueryString());

.NET

String singleUseToken = Request.QueryString["token"];
// or
String singleUseToken = AuthSubUtil.getTokenFromReply(new Uri(Request.QueryString));

PHP

$singleUseToken = $_GET['token'];

Python

current_url = 'http://' + req.hostname + req.unparsed_uri
# Unlike the other calls, extract_auth_sub_token_from_url() will create an AuthSubToken or SecureAuthSubToken object.
# Use str(single_use_token) to return the token's string value.
single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url)

If you are using secure AuthSub, be sure to set your RSA private key so a SecureAuthSubToken is created:

f = open('/path/to/yourRSAPrivateKey.pem')
rsa_key = f.read()
f.close()
current_url = 'http://' + req.hostname + req.unparsed_uri
# Unlike the other calls, extract_auth_sub_token_from_url() will create an AuthSubToken or SecureAuthSubToken object.
# Use str(single_use_token) to return the token's string value.
single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url, rsa_key=rsa_key)

Request a session token

The token you retrieve from the URL is always a single-use token. The next step is to upgrade that token for a long-lived session token using the AuthSubSessionToken URL, as described in the full AuthSub Authentication for Web Applications documentation. If you are using secure AuthSub, you'll need to set your RSA private key before making the exchange. Here are some examples using each of the client libraries:

Java

import com.google.gdata.client.*;
import com.google.gdata.client.calendar.*;

String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null);

CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0");
calendarService.setAuthSubToken(sessionToken, null);

// ready to interact with Calendar feeds

For secure AuthSub, pass your RSA private key to exchangeForSessionToken instead of pasing null:

import com.google.gdata.client.*;
import com.google.gdata.client.calendar.*;

java.security.PrivateKey privateKey =
    AuthSubUtil.getPrivateKeyFromKeystore("AuthSubExample.jks", "privKeyPa$$word", "AuthSubExample", "privKeyPa$$word");
String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, privateKey);

CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0");
calendarService.setAuthSubToken(sessionToken, privateKey);

// ready to interact with Calendar feeds

.NET

using Google.GData.Client;
using Google.GData.Calendar;

String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString();

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0");
authFactory.Token = (String) sessionToken;

CalendarService calendarService = new CalendarService(authFactory.ApplicationName);
calendarService.RequestFactory = authFactory;

// ready to interact with Calendar feeds

For secure AuthSub, pass your RSA private key to exchangeForSessionToken instead of pasing null:

using Google.GData.Client;
using Google.GData.Calendar;

protected AsymmetricAlgorithm getRsaKey()
{
  X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx", "privKeyPa$$word");
  RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;
  return privateKey;
}

AsymmetricAlgorithm rsaKey = getRsaKey();
String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, rsaKey).ToString();

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0");
authFactory.Token = (String) sessionToken;
authFactory.PrivateKey = rsaKey;

CalendarService calendarService = new CalendarService(authFactory.ApplicationName);
calendarService.RequestFactory = authFactory;

// ready to interact with Calendar feeds

PHP

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

$sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken);

// Create a Calendar service object and set the session token for subsequent requests
$calendarService = new Zend_Gdata_Calendar(null, 'google-ExampleApp-v1.0');
$calendarService->setAuthSubToken($sessionToken);

// ready to interact with Calendar feeds

For secure AuthSub, the exchange requires you to first setup a Zend_Gdata_HttpClient and set your RSA private key using setAuthSubPrivateKeyFile():

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

$client = new Zend_Gdata_HttpClient();
$client->setAuthSubPrivateKeyFile('/path/to/myrsakey.pem', null, true);
$sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken, $client);

$calendarService = new Zend_Gdata_Calendar($client, 'google-ExampleApp-v1.0');
$calendarService->setAuthSubToken($sessionToken);

// ready to interact with Calendar feeds

Python

import gdata.calendar
import gdata.calendar.service

calendar_service = gdata.calendar.service.CalendarService()
calendar_service.UpgradeToSessionToken(single_use_token)  # calls gdata.service.SetAuthSubToken() for you

# ready to interact with Calendar feeds

Note: The process is the same for secure AuthSub as long as you have used gdata.auth.extract_auth_sub_token_from_url(url, rsa_key=rsa_key) to extract the single-use token.

Note: When using secure AuthSub, your private key itself is not sent over the network. The client libraries send the unique signature generated by signing the request with your key, not the key itself.

Use the session token

You can use the session token to authenticate requests to the server by placing the token in the Authorization header, as described in the AuthSub documentation.

After you've set your session token, you can use the standard Google Data APIs client library calls to interact with the service, without having to think about the token. For details, see the client library documentation and the Google Data APIs developer guide for the service and language you're interacting with.

Retrieving information about a session token

If you want to test that your client and the server agree on the token's parameters, you can pass the token to the AuthSubTokenInfo handler, which returns a set of name-value pairs containing information about the token.

Java

Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, null);

If you're using secure AuthSub, pass in your RSA private key:

Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, privateKey);

.NET

Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, null);

If you're using secure AuthSub, pass in your RSA private key:

Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, privateKey);

PHP

$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken);

If you're using secure AuthSub, pass in your Zend_Gdata_HttpClient so the request is signed with your RSA private key:

$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken, $client);

Python

token_info = calendar_service.AuthSubTokenInfo()

Revoke a session token

AuthSub session tokens don't expire; your client can store the session token for as long as needed.

Therefore, when your client is done using the session token, it can revoke the token using the AuthSubRevokeToken handler, as described in the AuthSub documentation.

For example, if you want to manage tokens in a traditional session-like way, then your client can get a token at the beginning of a user's session and revoke it at the end of the user's session.

To revoke a token use the following in each client library:

Java

AuthSubUtil.revokeToken(sessionToken, null);

If you're using secure AuthSub, pass in your RSA private key:

AuthSubUtil.revokeToken(sessionToken, privateKey);

.NET

AuthSubUtil.revokeToken(sessionToken, null);

If you're using secure AuthSub, pass in your RSA private key:

AuthSubUtil.revokeToken(sessionToken, privateKey);

PHP

$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken);

If you're using secure AuthSub, pass in your Zend_Gdata_HttpClient so the request is signed with your RSA private key:

$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken, $client);

Python

calendar_service.RevokeAuthSubToken()

Additional Resources and Samples

Back to top

Generating a self-signing private key and public certificate for use with secure AuthSub

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

Back to top