Using Google Oauth2 to Access Google User Data from Client Application

As a part of my 3rd year CSE project for Software Engineering module I have implemented a voice based email client which operates in a desktop based environment. Using this application users are able to register using their google accounts. In addition they can send emails, view their Gmail inbox, view their contact list and send mails to their contacts etc. In addition to UI based application it provides voice based assistance especially for visually impaired which uses previously configured set of commands and IVR for helping the user for sending mails and reading inbox etc. However in this article I have described the integration of Google Oauth2 in my client application for user authentication and authorization. Using Google Oauth2 users can register to your applications using their Google accounts and access resources by authorizing your application at Google. Also, this entrusts the confidentiality of the user’s sensitive data such as passwords.

The authentication and authorization functionalities were developed based on google OAuth 2.0 protocols which uses access tokens and relies on Oauth 2 API. Using the oauth access tokens we can access relevant google APIs such as Gmail API, google contacts API for mail handling and contact retrieval.

Initially we have to obtain OAuth 2.0 client credentials from the Google API Console. Google provides a client ID and a client secret for our application, which can be embedded in the source code of our application. Then using the client credentials our client application can request an access token from the Google Authorization Server, extracts a token from the response, and sends the token to the Google API that we want to access. The following diagram depicts how this process takes place.

In the following section I have included the Email Client implementation in .NET to fetch user resources such as mails, contact list for users with Google accounts. It uses Google Oauth2 API for authentication and authorization. I have used a GoogleWebAuthorizationBroker to send authorization requests to google authorization server asynchronously since this is a desktop based application. It requires your applications client credentials and scopes as parameters to construct http requests.

using System;
using System.Threading;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Oauth2.v2;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Oauth2.v2.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Contacts;
using Google.Contacts;
namespace EmailClient
{

public class GmailLogin {
private static string xoauthKey;
private static string userEmail;
private static string userName;
private static UserCredential credential;
private static string[] contacts;
private static string[,]contactDetails;
private static int totContacts;
private static ContactsRequest cr;
private static readonly GmailLogin
m_Instance =new

GmailLogin();

// Prevent instance creation from other classes using singleton design pattern
private GmailLogin() {
}

public static GmailLogin Instance

{
get {
return m_Instance;
}
}

public bool GoogleLogin() {
// Request Gmail IMAP/SMTP scope and the e-mail address scope.
string[] scopes = new string[]{ “https:
//mail.google.com/”, Oauth2Service.Scope.UserinfoEmail, Oauth2Service.Scope.UserinfoProfile, “https://www.google.com/m8/feeds/" };
Console.WriteLine(“Requesting authorization”);
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = “specify your client_ID here”,
ClientSecret = “specify your client_secret here”,
},
scopes,
“user”,
CancellationToken.None).Result;
Console.WriteLine(“Authorization granted or not required( if the saved access token
already available)”);
/*
*
* access token is also saved locally in a persistent location
* C:\Users\UserName\AppData\Roaming\Google.Apis.Auth\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user
* for later use.
*/
if (credential.Token.IsExpired(credential.Flow.Clock)) {
Console.WriteLine(“The access token has expired, refreshing it”);
try {
if (credential.RefreshTokenAsync(CancellationToken.None).Result) {
Console.WriteLine(“The access token is now refreshed”);
return true;
} else {
Console.WriteLine(“The access token has expired but we can’t refresh it”);
return false;
}
} catch (Exception ex) {
Console.WriteLine(ex.Message);
return false;
}
} else {
Console.WriteLine(“The access token is OK, continue”);
return true;
}
}

public void RequestEmail() {
Console.WriteLine(“Requesting the e - mail address of the user from Google”);

Oauth2Service oauthService = new Oauth2Service(
new BaseClientService.Initializer() {
HttpClientInitializer =GmailLogin.getCredential()
});
Userinfoplus userInfo = oauthService.Userinfo.Get().ExecuteAsync().Result;
userEmail = userInfo.Email;
userName = userInfo.Name;
Console.WriteLine(“E - mail address is “ + userEmail);
//to access user’s contact list
RequestSettings settings = new RequestSettings(“Google Sync.”, GmailLogin.getCredential().Token.AccessToken) {
AutoPaging =true,
UseSSL =true
};
cr = new ContactsRequest(settings);
FetchAllContacts(cr, userEmail);


// Build XOAUTH2 token to use Gmail IMAP or SMTP.
xoauthKey = OAuth2.GetXOAuthKeyStatic(userEmail, GmailLogin.getCredential().Token.AccessToken);
// return true;
}

public void RevokeAccessToken() {
FileDataStore ds = new FileDataStore(GoogleWebAuthorizationBroker.Folder);
ds.DeleteAsync<TokenResponse> (“user”).Wait();
}

public static string getUserEmail() {
return userEmail;
}

public void FetchAllContacts(ContactsRequest cr, String email) {
Feed<Contact> feed = cr.GetContacts(email);
int i = 0;
Console.WriteLine(feed.TotalResults);
contacts = new string[feed.TotalResults];
contactDetails = new string[feed.TotalResults, 3];
totContacts = feed.TotalResults;
foreach(Contact entry in feed.Entries)
{
//Console.WriteLine(entry.Name.FullName);
//entry.Id
contactDetails[i, 0] =entry.Id;
contactDetails[i, 1] =entry.Name.FullName;

foreach(EMail e in entry.Emails)
{
Console.WriteLine(“\t” + e.Address);
contacts[i] = e.Address;
// Console.WriteLine(contacts[i]);
contactDetails[i, 2] =e.Address;
i++;
}
}
}

public static string[] getContacts() {
return contacts;
}

public static string[,]

getContactDetails() {
return contactDetails;
}

public static string getUserName() {
return userName;
}

public static string getOauthKey() {
return xoauthKey;
}

public static int getTotContacts() {
return totContacts;
}

public static bool DeleteContact(Uri contactURL) {
// Retrieving the contact is required in order to get the Etag.
Contact contact = cr.Retrieve < Contact > (contactURL);
try {
cr.Delete(contact);
return true;
} catch (GDataVersionConflictException e) {
Console.WriteLine(e.Message);
return false;
}
}

public static UserCredential getCredential() {
return credential;
}
}
}
Show your support

Clapping shows how much you appreciated Sathya Bandara’s story.