Google ClientLogin Utility in Java

Authentication and Authorization for Google APIs is a common feature in today’s applications requiring integration and information exchange with Google services. while most of this Google authentication process is tailored for web applications, it is also available for desktop and installed applications. for Desktop applications Google recommends using an authentication method called ClientLogin.

ClientLogin method Caution:
Google no more recommands using ClientLogin method for Authorization. here is a quote from google documentation:

ClientLogin is a Google proprietary authorization API, available as an alternative to OAuth for most Google APIs. You should avoid using ClientLogin if possible. If you already have applications that use ClientLogin, you should migrate to OAuth or the hybrid protocol.

Thus, ClientLogin is for use only when there is a high level of trust between the application and the owner of the protected data. It is mostly commonly recommend for cases where the application owns the protected data. If users of your application are worried about supplying their passwords for security and privacy reasons then ClientLogin authorization method is not suited for this situation.

How ClientLogin authorization works?
The ClientLogin method works mainly by sending HTTP Post requests to Google service using specific parameters as described in Google documentation. In this article we will use a different approach to implement ClientLogin authorization process. We will use Google APIs Client Library for Java, which is a powerful java library for accessing Google’s HTTP-based API’s on the web. The most important class in this library is , Obviously, the ClientLogin class.

Anatomy of the ClientLogin class:
ClientLogin class provides a single method authenticate() which handles the details of authentication process. it also provides an important internal class ErrorInfo which could be used to handle authentication errors and captcha challenge logic.
In this post we present a clean wrapper class for ClientLogin which handles the complete ClientLogin authorization process including authentication errors parsing and captcha challenge handling.

google-api-java-client Maven Dependencies:
we chose to use maven for building our project example. Maven provides dependencies for the Google APIs Client Library for Java. just add the following maven dependencies to your pom.xml file:

 <dependency>
      <groupId>com.google.api.client</groupId>
      <artifactId>google-api-client-googleapis-auth-clientlogin</artifactId>
      <version>1.2.3-alpha</version>
    </dependency>
    <dependency>
    <groupId>com.google.api.client</groupId>
    <artifactId>google-api-client-javanet</artifactId>
    <version>1.2.3-alpha</version>
  </dependency>

after that use maven:install to install the required jars to be included in our project classpath.

GoogleClientLogin wrapper class:
Our wrapper class obviously contains a reference to ClientLogin . it provides public methods implementing the important functions of the authentication process.
GoogleClientLogin has a constructor that takes a String representing the Google service you’re requesting authorization for ( for example “cl” for Google Calendar). The constructor looks like this:

/**
	 * @param service
	 */
	public GoogleClientLogin(String service) {
		super();
		this.service = service;
		authenticator = new ClientLogin();
		transport = GoogleTransport.create();
		authenticator.authTokenType = service;
	}

The main method is authenticate(username,password) that takes two arguments representing the username and password input by user:

/**
	 * @param username
	 * @param password
	 * @throws ClientLoginException
	 */
	public void authenticate(String username, String password)
			throws ClientLoginException {

		try {

			// authenticate with ClientLogin
			authenticator.username = username;
			authenticator.password = password;
			Response response = authenticator.authenticate();
			this.authToken = response.auth;

		} catch (HttpResponseException e) {
			parseError(e);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

this method sets ClientLogin variables (username and password) then calls ClientLogin.authenticate() which returns a Response instance. if the ClientLogin.authenticate() call is successful we store the Authentication token ‘Response.auth’. The advantage of the authenticate(username,password) wrapper method is its intelligent handling of authentication errors.

Parsing Authentication errors:
We distinguish two Error categories that could be thrown during the call to Clientlogin.authenticate(): a-unrecoverable Errors for which we use a ClientLoginException class
b-a recoverable error thrown when Google service requires a captcha challenge. for this later we use a separate Exception class CaptchaRequiredException which extends the first ClientLoginException class.
Clientlogin.authenticate() throws a HttpResponseException if the authentication response has an error code. we provide a helper method for parsing this exception class as follows:

/**
	 * @param e
	 * @throws ClientLoginException
	 */
	private void parseError(HttpResponseException e)
			throws ClientLoginException {
		try {

			ClientLogin.ErrorInfo errorInfo = e.response.parseAs(ClientLogin.ErrorInfo.class);
			errorMessage = errorMsg.get(errorInfo.error);
			if (errorInfo.error.equals(CaptchaRequired)) {
				captchaToken = errorInfo.captchaToken;
				captchaUrl = errorInfo.captchaUrl;
				throw new CaptchaRequiredException(errorMessage, e);

			} else
				throw new ClientLoginException(errorMessage, e);
		} catch (IOException e1) {

			throw new ClientLoginException(e1);
		}
	}

we Call HttpResponseException.response.parseAs(ClientLogin.ErrorInfo.class) to parse the response. if the error code is “CaptchaRequired” we store errorInfo.captchaToken and errorInfo.captchaUrl then throw CaptchaRequiredException. for the rest of Error codes we just throw ClientLoginException.

Authentication with CAPTCHA Challenge:
in the case of a CAPTCHA challenge we provide a second authenticate() method which provides an extra argument ‘captchaAnswer’ representing the captcha key entered by user during a CAPTCHA challenge:

/**
	 * @param username
	 * @param password
	 * @param captchaAnswer
	 * @throws ClientLoginException
	 */
	public void authenticate(String username, String password,
			String captchaAnswer) throws ClientLoginException {
		authenticator.username = username;
		authenticator.password = password;
		authenticator.captchaToken = this.captchaToken;
		authenticator.captchaAnswer = captchaAnswer;
		try {
			Response response = authenticator.authenticate();
			this.authToken = response.auth;
		} catch (HttpResponseException e) {
			parseError(e);
		} catch (IOException e) {
			throw new ClientLoginException(e);
		}
	}

before calling authenticator.authenticate() this method sets two extra fields authenticator.captchaToken and authenticator.captchaAnswer. Error handling for this method is the same as the main authenticate(username,password) method.
Finally we provide a method to retrieve the CAPTCHA image that will be displayed to user:

/**
	 * @return the captchaImage
	 */
	public BufferedImage getCaptchaImage() {

		BufferedImage image = null;
		try {
			URL url = new URL("https://www.google.com/accounts/"+ getCaptchaUrl());
			image = ImageIO.read(url);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

		return image;
	}

You can view the complete GoogleClientLogin class source file here.

Testing GoogleClientLogin wrapper class:
GoogleClientLoginDialog is a swing Dialog which presents an example of how to use GoogleClientLogin wrapper class. It provides a feature to force Google service to send a CAPTCHA challenge. we implement this test using a thread that keeps sending random passwords until Google responds with a CAPTCHA challenge:

 private class ForceCaptchaRunnable implements Runnable{

		public void run() {
			Random r = new Random();
			boolean isCaptcha = false;
			while (!isCaptcha) {
				try {
					client.authenticate(textField.getText().trim(),
							passwordField.getText().trim()+ r.nextInt(100));
					showMessage("Auth Token: "+client.getAuthToken());
				} catch (CaptchaRequiredException e1) {

					isCaptcha = true;
					showCaptcha(true);

				} catch (ClientLoginException e1) {

				}
			}

		}

	}


Source code:

Advertisements

Overcomming MS’s Local Machine Zone Lockdown in GWT

GWT developers will notice an annoying problem running the basic default GWT app locally in web mode in IE every time i try this I get a red warning message: “Your web browser must have JavaScript enabled in order for this application to display correctly”. I had to allow the active content  in order to see the web app screen. running in GWT dev mode seems not to raise this warning message. So what’s this all about? it seems IE doesn’t like people opening JavaScript-laced web pages from the local drive for security concern. there is a detailed article here that speaks about this issue  of Microsoft blocking local domain for web applications .

The article above speaks about a new concept introduced by Microsoft called Mark of the web. i tried the method of Mark of the web by adding these two lines at the begining of my GWT html file :

 
<!-- saved from url=(0014)about:internet -->
<!-- saved from url=(0016)http://localhost --> 

but when i add these two lines and then compile GWT app and open the html file with IE the web app doesn’t show even though the warning message is gone . The reason probably is that -by default- a GWT app is loaded within an iframe, i.e. as another HTML page (*.cache.html), which doesn’t contain the MotW (Mark of the web).
to overcome this problem we can try using the “xs” or “xsiframe” linker, i.e. add one of these lines to our *.gwt.xml:

<add-linker name="xs" />
<add-linker name="xsiframe" />

Those linkers use *.cache.js” files, so the MotW in our host page should be enough. adding the linker to GWT xml module file makes IE warning message go away and I can run the GWT web app locally with IE.
but The “xs” linker has one drawback : it prevents us from using GWT DevMode . another annoyance that we can overcome by using two *.gwt.xml module files: one for web mode testing with ‘xs’ linker and the other without the linker for testing in GWT DevMode.

This may give you an Idea about the coding acrobatics one should go through to overcome the weired Microsoft decision to block totally the Machine local zone for web applications!

GWT KeyPressHandler getCharCode issues

Like hundreds of GWT developers I stepped into the annoying GWT KeyPressEvent.getCharCode() bug problem described here
To turn around this bug i tried using:

event.getNativeEvent().getKeyCode()

the purpose is to access the native event to get the unprocessed code. However if you try the

event.getNativeEvent().getKeyCode()

you will knock your head against browser-specific inconsistencies. For example the getCharCode() from NativeEvent works for me in FireFox 3 but it doesn’t work in Chrome . in Chrome if i press “ENTER” key

 event.getNativeEvent().getKeyCode()=10

But

 KeyCodes.KEY_ENTER=13

in FF3 the two values are equal (’13’).
It appears that a fix for KeyPressHandler was completed and reviewed for this issue . but it is not clear when we could expect it to be released. The fix appears fairly complex, with different browser-specific implementations.
it turns out that this change set is actually exactly what causes the current behavior in Firefox. See the rationale and a workaround/fix (i.e. only use getNativeEvent() when getCharCode returns 0).
the workaround above works but we need to replace ’13’ with ’10’ in the fix code portion below :

} else if (charCode == 13) {

    doOnEnterKeyPressed();
  }

using ’10’ instead of ’13’ in the else if conditional:

} else if (charCode == 10) {

    doOnEnterKeyPressed();
  }

with this new change code works both in chrome and FF3.

Hope this could be helpful for anyone experiencing these GWT keyPress getCharCode() problems.

Eclipse GWT plugin Installation issue

I have been encountering a problem installing GWT eclipse plugin using the update site :

http://dl.google.com/eclipse/plugin/3.6

using this update url seems to raise an error:

Unable to Read repository at http://dl.google.com/eclipse/plugin/3.6/content.xml.
Connection reset

A workaround that works for me is to replace gwt eclipse update site with:

https://dl-ssl.google.com/eclipse/plugin/3.6

Eclipse Helios Crash on Linux

I have eclipse Helios installed in a opensuse 10.3 box. it seems the eclipse editor keeps crashing eclipse application every time i type a dot ‘.’ to access object methods.
if you experience same problem you can try the following two fixes:

  • if you don’t have xulrunner package then install it (example using Yast2 in opensuse).
    make sure you only install latest xulrunner version. if you install two different xulrunner versions in your linux OS the two versions might conflict and cause eclipse to crash again. this was my problem. when i removed old xulrunner 191 and only kept xulrunner 192 then eclipse helios stops crashing and works well.
  • The second fix (that doesn’t require to install xulrunner but seamonkey) is to specify to the Java VM the location of xulrunner .
    To do this :
    1-Edit file : ~/eclipse/eclipse.ini
    2- add the following text below the ‘-vmargs’ line :

    -Dorg.eclipse.swt.browser.XULRunnerPath=/usr/lib/seamonkey 

    For further information on this second fix see this thread discussion.

The move from OpenOffice To LibreOffice For Java Developers

After Sun Inc had been acquired by Oracle ; and because of some clashes between Sun’s open source projects communities and the -somewhat unfriendly- Oracle attitude towards Sun’s open source projects; OpenOffice has been forked to LibreOffice. This Effort is being Led by document foundation probably with joint efforts to come from major Linux companies Like Novel ,Ubuntu and RedHat .

For Java OpenOffice API developers , the move to Libreoffice should be straightforward. the basic idea is just replace OpenOffice installation and sdk with corresponding Libreoffice ones. If you consider doing serious Java Libreoffice extension development it is advised to use an IDE plugin for Libreoffice.

The only two available Libreoffice/openoffice java IDE plugins are OOEclipseIntegration and Netbeans 6.8 OpenOffice.org API Plugin . While the eclipse OO plugin is available in eclipse marketplace repos from eclipse IDE (3.6+) and is still undergoing active development; It seems the netbeans OO plugin doesn’t get upgraded into higher netbeans versions anymore. So you are stuck using the old netbeans version 6.8.

To set up your Netbeans OpenOffice.org development environment with Libreoffice do the following steps:

  1.   Get netbeans IDE 6.8 and then install plugin “OpenOffice.org API Plugin” from netbeans IDE plugins dialog.
  2.   Downlaod and Install Libreoffice and Libreoffice SDK.
  3. In Netbeans IDE select “Tools->Options->Miscellaneous”. select Tab “OOo API Plugin”. then in fields “Openoffice.org installation” and “Openoffice.org SDK installation” browse to the folder where you installed Libreoffice and libreoffice SDK respectively as described in image below:

When you create a new Project for OpenOffice.org API the currently specified Libreoffice sdk library will be automatically added to your Netbeans OpenOffice Project classpath (for example Libreoffice 3.4 library )

For a Detailed tutorial on java netbeans OpenOffice API development refer to Kay Kroll on Netbeans OpenOffice integration .  I have also included a presentation by jurgen Shmidt included in the ‘Additional Resources’ section at the bottom of this post. These two tutorials although for OpenOffice.org they also apply to Libreoffice java development in Netbeans as the same process applies for both OpenOffice and LibreOffice.

UPDATE:

For people using linux (specifically opensuse 12.+) upgrading to Libreoffice version 3.5+ causes some issues. In  netbeans 6.8 IDE the automatically added  library ‘LibreOffice 3.5 or 3.6’ to the project classpath  misses other important jars for some unknown reasons. I had to manually add the following jars from the directory ‘Your_LO_Home/ure/share/java’ :


	juh.jar
	jurt.jar
	ridl.jar
	unoloader.jar

For some unkown reason the netbeans library LibreOffice 3.5 doesn’t contains these jars and i had to add them manually to project classpath.

Another issue with netbeans OO plugin and LO sdk 3.5+ is when you clean and build your OO project and try ‘debug extension in OO Target’ there is a wiered error massage stating:

‘user doesn’t have write permission to install this extension’.

you simply overcome this error message by running again the ‘debug extension in OO Target’.


Additional Resources: