Channels ▼
RSS

Web Development

Getting Started With the Cloud: Logging On With Google OAuth


Accessing GWT Hosted Mode from the Internet

The final network-related issue is really a Google-Web-Toolkit issue. First some background: The test application I put together is a Google Web Toolkit (GWT) application, and you test GWT applications by running them as "Web Applications" from the Eclipse debugger. If you've never worked with GWT, this one feature should be enough for you to check it out.

In GWT, the client side of your web application is written in Java, but translated to JavaScript by the GWT compiler. That is, you're deploying JavaScript, but you're both writing and testing in Java. The client side of the application runs in the Eclipse debugger just like any other Java application.

GWT works this magic in two ways. First of all, when you test a GWT application, what you're really running under Eclipse is an instance of the Jetty web server that's been hacked up to know about GWT. Though, I suppose you could set breakpoints inside Jetty itself, you never do that. What you do do, however, is set breakpoints in the servlets that are running inside Jetty — the servlets that comprise your application.

Server-side breakpoints are rather ho-hum, but you can also set breakpoints in the Java code that comprises the client side of the application. Since the client-side code is actually running in the browser (in JavaScript), a certain amount of magic is required to make that work as well. To simplify: Your JavaScript application is running in the browser under a plugin. (Google provides versions for all major browsers). When you set a breakpoint in Eclipse, the web server communicates with the plugin in such a way that you effectively set a breakpoint in the GWT-generated JavaScript as well. This way, the two versions of the client-side code effectively run in sync with each other.

In practice, this setup means that you can set Eclipse-debugger breakpoints in both the client-side and server-side code, and then actually watch the entire program execute in a single instance of the debugger. Even better, browser-hosted debuggers like FireBug or the built-in Chrome Developer Tools view are also active, so you can inspect the GWT-generated HTML and JavaScript in the browser, and set breakpoints in any hand-built JavaScript code that is not part of the GWT application. This is a spectacularly productive test environment.

So here's the problem: The hacked up version of Jetty, by default, will only recognize HTTP requests that come from the local machine. When testing our OAuth application, however, HTTP requests to the GWT version of Jetty are coming from two places: from the local machine (when we launch the application from a browser), and from the Internet (when Google sends us the Auth token). The local URL that you typically use to test a GWT applictaion looks something like this:

http://127.0.0.1:8888/Calendar.html?gwt.bsvr=127.0.0.1:9997

Google, however, can't send the OAuth token to that address, because 127.0.0.1 (which means "the local machine") is not a public Internet address; and even if it could, Jetty wouldn't accept the external HTTP request.

Google wants to send the token to something like

http://70.90.10.1:8888/calendar/AuthTokenRegistrar

or in my case

http://timezer:8888/calendar/AuthTokenRegistrar

(the calendar/AuthTokenRegistrar part of the URL identifies the servlet that receives the token). However, Jetty refuses requests to 70.90.10.1 or timezer.com.

The fix is, fortunately, easy. In Eclipse, go to the Run:Run Configurations dialog. On the left, under Web Applications, select the OAuth application that you're testing. Now, click on the (x)= Arguments and add the argument -bindAddress 0.0.0.0 to the front of the Program Arguments, which holds the command-line arguments for Jetty itself. That 0.0.0.0 address causes Jetty to bind to the IP address of the current machine, whatever it is. You ould also bind ot the actual IP address (70.90.10.1, as aforementioned) if you like, but the 0.0.0.0 form lets you change the IP address of your machine without having to reconfigure Eclipse.

Install the Eclipse GData plugin

Now that the physical world is squared away, we need to think about software. The next step is to install the GData plugin into Eclipse, The plugin isn't essential, but it takes care of some of the busywork of downloading and installing the required jars for a given Google GData API. It also adjusts the Eclipse build-path configuration to accommodate the new jars it installs. That's all the plugin does, however. It doesn't help with the coding.

On the downside, the plugin, frustratingly, doesn't install all the jars you need. For example, if you ask for Calendar APIs, that's all you get. You don't get the additional jars that are required for OAuth.

Google doesn't document the dependencies between jars very well, so using the plugin can help resolve some of the non-obvious dependencies when you install an API jar, so it's worth going through the trouble of installing it.

The plugin works by adding an "Add Google API's" menu to the Google-plugin widget on the toolbar (see Figure 3).

[Click image to view at full size]
Figure 3: Using the GData Plugin in Eclipse.

You don't create an explicit GData project, you just add support to an existing project. If you've already installed the GWT plugin, then the widget is already there and installing the plugin just adds the menu item; otherwise, the widget is added.

The plugin also sets up the javadoc locations for the main high-level API (e.g., Calendar), but unfortunately, not for the packages that the high-level API uses (e.g., the Jsr305 Annotations jar or the Google Collections APIs).

Find the plugin at http://code.google.com/p/gdata-java-client-eclipse-plugin/. There's a link to a pretty good tutorial on that page, and there's also a useful YouTube video at http://www.youtube.com/watch?v=dz9Ny22M4V4. Both of these are a bit out of date, but you can follow along without much difficulty. If you've done this sort of thing before, installation is pretty easy: Just bring up Eclipse's Help->Install New Software menu and enter the following URL (which is annoyingly omitted from the video) as the update site to work with:

http://gdata-java-client-eclipse-plugin.googlecode.com/svn/update-site

The plugin supports the following GData APIs, but using the others is a simple matter of putting an appropriate jar or jars on your CLASSPATH:

  • Apps Provisioning
  • Base
  • Blogger
  • Calendar
  • Code Search
  • Contacts
  • Documents List
  • Health
  • Notebook
  • Picasa Web Albums
  • Spreadsheets
  • YouTube

Adding OAuth-Support jars

As I mentioned earlier, the Google GData plugin installs only those jars that you need for the specified API. It doesn't install all of the jars that you need to do OAuth. Google provides instructions for manual installation here. (You should read this file if you're deploying to the app engine. I'm not demonstrating app-engine-related configuration stuff in this article.)

To install the OAuth jars manually, go to the home directory for the java-client-wrapper project. From there, click on the "downloads" tab, and then download the jdata-src.java.1.45.0.zip file (or whatever version number is current).

Unpack the archive to create a directory called gdata. In that directory, the subdirectory .../gdata/java/lib contains compiled .jar files for all the various GData APIs. For OAuth, you need the following jars:

  • gdata-client-1.0.jar
  • gdata-client-meta-1.0.jar
  • gdata-core-1.0.jar
  • gdata-docs-3.0.jar
  • gdata-docs-meta-3.0.jar
  • gdata-media-1.0.jar

In addition, you'll also need the google-collect-1.0-rc1.jar, which is in the .../gdata/java/deps subdirectory in the zip file. You can find the javadoc for all the GData wrapper classes in the .../gdata/doc directory.

Once you have the jars in the right place, you need to add them to the Eclipse build path (Select "Project:Properties:Java Build Path," then pick the "Libraries" tab and click on the "Add External JARs" button. Navigate to the directory where you just copied the jar files and click "Open"). I typically change the name of the jar when I copy it into the lib directory to make it easier to update the jars later on. For example, I might copy gdata-client-1.0.jar into myproject/war/WEB-INF/lib/gdata-client.jar (without the version number in the name). That way, when the jar is updated to some other version, I can just copy the new version (with my nonstandard name) right on top of the old one in my .../lib directory, and I don't have to mess with the build path (because the file name hasn't changed).

For what it's worth, I've found that it's a lot easier to manually edit the Eclipse .classpath file at the root of your project directory than it is to use the GUI process I just described. Just shut down Eclipse, modify the file in an ASCII editor, then bring Eclipse back up.

Here are standard <classpathentry> elements for the required Google jars — change the paths as necessary:

<classpath>
...
	<classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-client-meta.jar"/>
	<classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-client.jar"/>
	<classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-core.jar"/>
	<classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-docs-meta.jar"/>
	<classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-docs.jar"/>
	<classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/google-collect.jar"/>
...
</classpath>

Make A Key Pair and Self-Signed Certificate

The next step is to make a certificate and private key that you can use to authenticate your OAuth request. I discussed this issue in last month's article — in a nutshell, you create an RSA private key and a public-key certificate using openssl. The following command does the trick:

		openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 \
		-subj /C=US/ST=CA/L=Berkeley/CN=www.<em>myDomain</em>.com \
		-keyout <em>myDomain</em>-rsakey.pem -out <em>myDomain</em>-cert.pem

You'll need to change myDomain to your actual domain name, and also change the -subj argument to correctly state your actual country, state, city, and domain name. This certificate is good for a year (-days 365), so you'll have to create a new one a year from now. Omit this argument if you don't want the certificate to expire.

Once you've created the cert (myDomain-cert.pem) you need to register it with Google. This step is actually optional, but you'll want to do it before you deploy to the real world in order to get rid of the scary looking warning that shows up on the User's grant-access request page. The long-form instructions are here, but the short form is that you go to your Manage Domains page (there's a link in the long-form instructions), where you'll see a screen like the one shown in Figure 4.

[Click image to view at full size]
Figure 4: Registering a Domain with Google.

The "Target URL" should be a proper prefix of the URL that you'll be giving to Google. I just use the main domain name, but you could specify something like "http://www.myDomain.com/oauth" if you want to limit access to specific servlets. Once the registration is complete, Google will give you a screen like the one shown in Figure 5. You should note the Consumer Key and the Consumer Secret — you'll need the key momentarily. Also note that you can change the certificate at any point (to register a new one after the current one expires, for example) from this page.

[Click image to view at full size]
Figure 5: Successful Registration.

If you want to see what the permission-granting page will look like, you can click the "Test your AuthSub registration here" link at the bottom of the page. That link will get you through the Google login page (if you're not already logged in, to a page that looks like the one shown in Figure 6.) You can test that the authorization works by logging on to Google, clicking on "My Account," then choosing Authorizing applications & sites from the Security section.

[Click image to view at full size]
Figure 6: Granting Access.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV