Contents

Audience

This document is intended for Apex Developers who want to write Force.com Apps that can interact with Google Data APIs.

This document assumes that you understand the general ideas behind the Google Data APIs protocol.

Getting started

Set up your Force.com Development environment.

The Force.com platform is the most scalable, secure and popular on-demand platform in the world today. You can develop and instantaneously deploy applications without any infrastructure - 100% on-demand

Install the latest version of the Force.com IDE

The Force.com IDE allows developers a full-featured, Eclipse-based coding environment, with capabilities like code completion, version control,collaborative development, and project sharing.

Create a Google Account

Google Data APIs are associated with Google Accounts, so a Google Account will be required in order to proceed. To view your Google data without using the Google Data APIs, you can log in to Gmail.

Check out the source code

Check out the Force.com Toolkit for Google Data APIs from the Google repository.

Apex Code Examples

The following examples show how to establish a connection from Force.com to the Google Data APIs.

Authenticating to the Google Data APIs service

Before your application can make any callouts to google you must configure your remote sites to allow http and https to google, please see this help location:Configure Remote Proxy

All Google Data API feeds require authentication. Thus, your force.com application needs to authenticate before accessing a calendar, contact, spreadsheet or other google data feed. To use the Apex Code library you must use the AuthSub proxy authentication.

For more information about authentication with Google Data APIs in general, see the authentication documentation. AuthSub proxy authentication

AuthSub proxy authentication is used by web applications that need to authenticate their users to Google Accounts. The website operator and the client code do not have access to the username and password for the user; instead, the application obtains special AuthSub tokens that allow the application to act on a particular user's behalf. For more detailed information, see the AuthSub documentation.

Request a Token : Step 1

When a user first visits your application, they have not yet been authenticated. In this case, you need to display some information and a link directing the user to a Google page to authenticate your request for access to their contacts. The following Visualforce page will construct the url required to begin the two step process. The process begins by constructing a url, specifying the scope which selects which API this token will be good for as well as the destination or Visualforce page that the token will be sent back to.

This page, called /apex/authsub as an example, will send the user to Google, and print the step 1 token after it is granted.

Note: this is called with the record ID for a googsession__c object where it will store the token, the object definition for googsession__c is included at the end of this page for your reference.

Note: this sample hard codes the SCOPE for a calendar API, you must gather tokens for each service, for each user.

 
<apex:page controller="AuthSubController">
<apex:form >
<!--  if we are missing a token, ask for one -->

<apex:outputPanel rendered="{!requestToken}">
<script> 
var scope = 'http://www.google.com/calendar/feeds/';
// var scope = 'http://spreadsheets.google.com/feeds/'; 
// var scope = 'http://docs.google.com/feeds/documents';
// see Google Data API reference for other valid SCOPE paramaters

var forceReDirect = '/_ui/core/google/GoogleAuthSubCallback?url=' ;
var googleRedir = 'https://www.google.com/accounts/AuthSubRequest?next=';
 					
// destination (relateive path) that will capture the token and store it for your app	
// you can pass your own query string parms
var myApp = encodeURIComponent( 
		window.location.pathname + "?id={!$CurrentPage.parameters.id}" ) ;
	
   var nextUrl = window.location.protocol + '//' + window.location.host + 
		forceReDirect + myApp ;  
      
  var tokenRequestUrl  = googleRedir + 
	        encodeURIComponent( nextUrl ) + 
	        "&session=1&secure=0&scope="+ scope;

// go there now
   window.location.href = tokenRequestUrl;
</script>
</apex:outputPanel>
<apex:outputPanel rendered="{!$CurrentPage.parameters.token != null}"> 
The one time use token is :<b>{!$CurrentPage.parameters.token}</b>
<br />
Record to update is {!$CurrentPage.parameters.id}
<apex:commandbutton action="{!exchangeRequestToken}"
	oncomplete="window.close();" value="Request Session token" />
		</apex:outputPanel>
	</apex:form>
</apex:page>

The user follows the link to Google's site and authenticates to their Google Account. The resulting token is returned to your app.

Request a session token : Step 2

After the user authenticates, the AuthSub system redirects them to the URL you specified in the next query parameter of the AuthSubRequest URL. This should be a Visualforce page within your app that will process the returned token. The AuthSub system appends an authentication token to that URL, as the value of the token query parameter. For example:

http://na5.salesforce.com/apex/authsub?token=yourAuthToken

This token value represents a single-use AuthSub token. In this example, since session = true was specified, this token can be exchanged for an AuthSub session token by calling the AuthSubSessionToken service with the single-use token in an Authorization header, as follows, where urlFromAuthSub is the URL that AuthSub appended the token to:

 
String token = ApexPages.currentPage().getParameters().get('token');
String sessionToken = AuthSubUtil.exchangeForSessionToken(token);

That is, you pass your one-time-use token to the exchangeForSessionToken method, and the AuthSub interface returns a session token.

The above code can be executed from a Visualforce controller after the requesting page has a single use token.

Here is a visualforce controller that can perform the exchange. This assumes a you store tokens in a custom object, there is an example of such an object at the end of this page.

public class AuthSubController {
	
 	public pagereference exchangeRequestToken() {
 		if ( ApexPages.currentPage().getParameters().get('token') != null) { 
 			string sessToken = 
 			 AuthSubUtil.exchangeForSessionToken( 
 			 	ApexPages.currentPage().getParameters().get('token'));
 			// store the token 
 			// this assumes a you store tokens in a custom object
 			GoogSession__c session = new googSession__c(id=
				ApexPages.currentPage().getParameters().get('id'),
				 AuthSubSessionToken__c = sessToken );
 			
 			update session; 
 		}
 		return null;
 	}
    public boolean getRequestToken() {
    	return (ApexPages.currentPage().getParameters().get('token') == null
    	&& ApexPages.currentPage().getParameters().get('id') != null);
    }
}

Google allows 10 valid tokens, after that you will not be able to gain new ones. Unless you store tokens you may run out of the allowed 10 tokens. See Google AuthSub reference for details on how to revoke tokens from your account.

Retrieving token info

At any time you can take a valid token and fetch information about that token using AuthSub.getTokenInfo( );

 
system.assert(  AuthSubUtil.getTokenInfo( 'badtoken' ) == null ); 
Map<String, String> tokenInfo =  AuthSubUtil.getTokenInfo( 'goodvalidtoken' ); 
system.assert(  tokenInfo != null ); 
system.debug ( tokenInfo);  // dump the map

Revoking a token

At any time you can take a valid token and revoke it such that it cannot be used. This is done with the revokeToken method on the AuthSubUtil class.

   AuthSubUtil.revokeToken( 'soongoingtobeinvalid' );

Storing the session token

Your application can then use the session token value in subsequent interactions with Google Data API's exposed by the Apex Toolkit. The Apex Toolkit class library automatically sends the token along with requests after you set the token into the service class within your app.

You must store the session token, usually within your Force.com application. This can be done using a custom object so that it will be available for future use when the same user returns to your app, or a custom field on the user object.

Token Storage

Your application may need a place to store tokens for reuse, the following custom object definition is a simple implementation of such an object.

In this example this file defines the meta-data for the object named googSession__c, which in eclipse is named

  • src/unpackaged/objects/googSession__c.object

The object :

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <deploymentStatus>Deployed</deploymentStatus>
    <description>Holds a google session id for a user and app combo</description>
    <fields>
        <fullName>AuthSubSessionToken__c</fullName>
        <label>AuthSubSessionToken</label>
        <length>128</length>
        <type>Text</type>
    </fields>
    <fields>
        <fullName>Scope__c</fullName>
        <label>Scope</label>
        <picklist>
            <picklistValues>
                <fullName>http://spreadsheets.google.com/feeds/</fullName>
                <default>false</default>
            </picklistValues>
            <picklistValues>
                <fullName>http://www.google.com/calendar/feeds/</fullName>
                <default>true</default>
            </picklistValues>
            <picklistValues>
                <fullName>http://docs.google.com/feeds/documents</fullName>
                <default>false</default>
            </picklistValues>
            <sorted>false</sorted>
        </picklist>
        <type>Picklist</type>
    </fields>
    <label>Google Auth Token</label>
    <nameField>
        <label>Token Name</label>
        <type>Text</type>
    </nameField>
    <pluralLabel>Google Auth Token</pluralLabel>
    <sharingModel>ReadWrite</sharingModel>
    <webLinks>
        <fullName>Request_Token</fullName>
        <availability>online</availability>
        <displayType>button</displayType>
        <hasScrollbars>true</hasScrollbars>
        <height>600</height>
        <isResizable>true</isResizable>
        <linkType>url</linkType>
        <masterLabel>Request Token</masterLabel>
        <openType>newWindow</openType>
        <position>none</position>
        <url>/apex/authsub?id={!googSession__c.Id}</url>
    </webLinks>
</CustomObject>

Setting up the new Custom Object

After creating this object using eclipse and the meta-data above, you can create a Custom Object Tab, then you can create an instance of this object, by clicking on that tab and clicking New.

The object also contains a button definition, if you add this to page layout of this object it will invoke the page with the required ID passed in

Related Content