Google AuthSub follows a common oAuth style handshake flow. Unfortunately, it is not immediately clear how to implement this flow with the AuthSub GData JavaScript Library using their documentation examples or the library’s API.
I recently implemented the flow for a Google Contacts viewer that we are working on here at Bocoup, and thought I would share the boilerplate I came up with.
In the boilerplate below, I am specifically focusing on authenticating users with AuthSub Gdata Library and getting their Google Contacts data using the Google Contacts GData JavaScript API.
You can download the full code here to get started. Note: this code needs to be served by HTTPS. I’ll work on getting a live demo up.
The JavaScript Code:
The JavaScript code below creates login
, logout
, and getContacts
buttons which allow the user to AuthSub into Google, grant access to their Google contacts to the current domain, get their contacts, and revoke access to the current domain. Read through the inline comments in the JavaScript code to see how everything works.
// Load in the gdata library
// This page must be served over HTTPS to work
google.load( 'gdata', '1.x' );
// Wait for the document to be ready
$(function(){
// Define a controls object with
// properties for each control in the demo: login, logout and getcontacts.
// Controls will be iterated over, and <buttons> will be added to the
// DOM for each control
var controls = {
login: {
label: 'Login to google',
action: function(){
// Google authSub login code scoped to the google gdata contacts feeds api
// When the user is brought to google to grant grant your app permission
// it will say you are requesting contacts data based on this scope.
// If the user grants permission to use their data, a two year cookie
// will be set on the current domain.
google.accounts.user.login('https://www.google.com/m8/feeds');
}
},
logout: {
label: 'Logout from google',
action: function(){
// log user out from google authSub to your app by deleting the
// authSub cookie
google.accounts.user.logout();
}
},
getContacts: {
label: 'Get contacts',
action: function(){
// instantiate google gdata contacts api,
// and call the gdata list all contacts code
// Note: user must be logged in for this to work
// Instantiate a new ContactsService which we will use to
// request the users contacts
var contactsService = new google.gdata.contacts.ContactsService( 'Contacts Viewer' ),
// Create a query for the full contacts list
query = new google.gdata.contacts.ContactQuery( 'https://www.google.com/m8/feeds/contacts/default/full' );
// Limit the query to the number of results in the numContacts
// input (25 by default)
query.setMaxResults( $('#numContacts').val() );
// Request the contacts feed with
// getContactFeed( query, successCallback, errorCallback )
contactsService.getContactFeed(
// query
query,
// successCallback
function( result ){
// Destroy existing contactsHolder if it already exists
$('#contacts').remove();
// Create <ul> to store our contacts in before we
// append them to the DOM
var $contactsHolder = $('<ul>', {
id: 'contacts'
});
// Iterate over the entries that came back
$.each( result.feed.entry, function( i, entry ){
// Call getEmailAddresses() on each entry, and iterate
$.each( entry.getEmailAddresses(), function( j, address ){
// Append each address to the off DOM <ul> we made
$contactsHolder.append( '<li>' + address.address + '</li>' );
});
});
// Add the contacts list to the DOM
$contactsHolder.appendTo( 'body');
},
// errorCallback
function( result ){
// Log the error
console.log('error: ', result);
}
);
}
}
};
// Iterate over the controls and add them to the DOM
$.each( controls, function( propertyName, control ){
$( '<button>', {
html: control.label,
id: propertyName
})
.appendTo( 'nav' );
});
// Delegate click handlers to all buttons in our <nav> element.
$( 'nav' ).delegate('button', 'click', function(){
// Since we gave an id to each button name based on it's property name
// in the controls object, we can use that use that id to dereference the
// correct controls property and call it's action method
controls[ this.id ].action();
})
});
The HTML Document:
And here is a look at the HTML document that the above JavaScript initializes on:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="http://google.com/jsapi"></script>
<script src="google-contacts-authsub.js"></script>
</head>
<body>
<!-- Google requires an image to be on the page -->
<img src="https://localhost/img/1px.png">
<!-- Input to be used for deciding how many contacts to fetch -->
<input id="numContacts" placeholder="number of contacts" type="text">
<!-- Container to be filled with buttons by our JavaScript Code -->
<nav></nav>
</body>
</html>