LibraryToggle FramesPrintFeedback

Available in Fuse Mediation Router 2.3

The gauth component is used by web applications to implement a Google-specific OAuth consumer. It will be later extended to support other OAuth providers as well. Although this component belongs to the Camel Components for Google App Engine (GAE), it can also be used to OAuth-enable non-GAE web applications. For a detailed description of Google's OAuth implementation refer to the Google OAuth API reference.

Name Default Value Required Description
callback null true (can alternatively be set via GAuthAuthorizeBinding.GAUTH_CALLBACK message header) URL where to redirect the user after having granted or denied access.
scope null true (can alternatively be set via GAuthAuthorizeBinding.GAUTH_SCOPE message header) URL identifying the service(s) to be accessed. Scopes are defined by each Google service; see the service's documentation for the correct value. To specify more than one scope, list each one separated with a comma. Example: http://www.google.com/calendar/feeds/.
consumerKey null true (can alternatively be set on component-level). Domain identifying the web application. This is the domain used when registering the application with Google. Example: camelcloud.appspot.com. For a non-registered application use anonymous.
consumerSecret null one of consumerSecret or keyLoaderRef is required (can alternatively be set on component-level). Consumer secret of the web application. The consumer secret is generated when when registering the application with Google. It is needed if the HMAC-SHA1 signature method shall be used. For a non-registered application use anonymous.
keyLoaderRef null one of consumerSecret or keyLoaderRef is required (can be alternatively set on component-level) Reference to a private key loader in the registry. Part of camel-gae are two key loaders: GAuthPk8Loader for loading a private key from a PKCS#8 file and GAuthJksLoader to load a private key from a Java key store. It is needed if the RSA-SHA1 signature method shall be used. These classes are defined in the org.apache.camel.component.gae.auth package.
authorizeBindingRef Reference to GAuthAuthorizeBinding false Reference to a OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> in the registry for customizing how an Exchange is bound to GoogleOAuthParameters. This binding is used for teh authorization phase. Most applications won't change the default value.
upgradeBindingRef Reference to GAuthAuthorizeBinding false Reference to a OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> in the registry. for customizing how an Exchange is bound to GoogleOAuthParameters. This binding is used for teh token upgrade phase. Most applications won't change the default value.
Name Type Endpoint Message Description
GAuthAuthorizeBinding.GAUTH_CALLBACK String gauth:authorize in Overrides the callback option.
GAuthAuthorizeBinding.GAUTH_SCOPE String gauth:authorize in Overrides the scope option.
GAuthUpgradeBinding.GAUTH_ACCESS_TOKEN String gauth:upgrade out Contains the long-lived access token. This token should be stored by the applications in context of a user.
GAuthUpgradeBinding.GAUTH_ACCESS_TOKEN_SECRET String gauth:upgrade out Contains the access token secret. This token secret should be stored by the applications in context of a user.

Some endpoint options such as consumerKey, consumerSecret or keyLoader are usually set to the same values on gauth:authorize and gauth:upgrade endpoints. The gauth component allows to configure them on component-level. These settings are then inherited by gauth endpoints and need not be set redundantly in the endpoint URIs. Here are some configuration examples.

[Note]component configuration for a registered web application using the HMAC-SHA1 signature method
<bean id="gauth" class="org.apache.camel.component.gae.auth.GAuthComponent">
    <property name="consumerKey" value="example.appspot.com" />
    <property name="consumerSecret" value="QAtA...HfQ" />
</bean>

[Note]component configuration for an unregistered web application using the HMAC-SHA1 signature method
<bean id="gauth" class="org.apache.camel.component.gae.auth.GAuthComponent">
    <!-- Google will display a warning message on the authorization page -->
    <property name="consumerKey" value="anonymous" />
    <property name="consumerSecret" value="anonymous" />
</bean>

[Note]component configuration for a registered web application using the RSA-SHA1 signature method
<bean id="gauth" class="org.apache.camel.component.gae.auth.GAuthComponent">
    <property name="consumerKey" value="ipfcloud.appspot.com" />
    <property name="keyLoader" ref="jksLoader" />
    <!--<property name="keyLoader" ref="pk8Loader" />-->
</bean>

<!-- Loads the private key from a Java key store -->
<bean id="jksLoader"
    class="org.apache.camel.component.gae.auth.GAuthJksLoader">
    <property name="keyStoreLocation" value="myKeytore.jks" />
    <property name="keyAlias" value="myKey" />
    <property name="keyPass" value="myKeyPassword" />
    <property name="storePass" value="myStorePassword" />
</bean>

<!-- Loads the private key from a PKCS#8 file -->
<bean id="pk8Loader"
    class="org.apache.camel.component.gae.auth.GAuthPk8Loader">
    <property name="keyStoreLocation" value="myKeyfile.pk8" />
</bean>

Here's the minimum setup for adding OAuth to a (non-GAE) web application. In the following example, it is assumed that the web application is running on gauth.example.org.

[Note]GAuthRouteBuilder.java
import java.net.URLEncoder;
import org.apache.camel.builder.RouteBuilder;

public class GAuthRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        // Calback URL to redirect user from Google Authorization back to the web application
        String encodedCallback = URLEncoder.encode("https://gauth.example.org:8443/handler", "UTF-8");
        // Application will request for authorization to access a user's Google Calendar
        String encodedScope = URLEncoder.encode("http://www.google.com/calendar/feeds/", "UTF-8");

        // Route 1: A GET request to http://gauth.example.org/authorize will trigger the the OAuth
        // sequence of interactions. The gauth:authorize endpoint obtains an unauthorized request
        // token from Google and then redirects the user (browser) to a Google authorization page.
        from("jetty:http://0.0.0.0:8080/authorize")
            .to("gauth:authorize?callback=" + encodedCallback + "&scope=" + encodedScope);

        // Route 2: Handle callback from Google. After the user granted access to Google Calendar
        // Google redirects the user to https://gauth.example.org:8443/handler (see callback) along
        // with an authorized request token. The gauth:access endpoint exchanges the authorized
        // request token against a long-lived access token.
        from("jetty:https://0.0.0.0:8443/handler")
            .to("gauth:upgrade")
            // The access token can be obtained from
            // exchange.getOut().getHeader(GAuthUpgradeBinding.GAUTH_ACCESS_TOKEN)
            // The access token secret can be obtained from
            // exchange.getOut().getHeader(GAuthUpgradeBinding.GAUTH_ACCESS_TOKEN_SECRET)
            .process(/* store the tokens in context of the current user ... */);
    }

}

The OAuth sequence is triggered by sending a GET request to http://gauth.example.org/authorize . The user is then redirected to a Google authorization page. After having granted access on this page, Google redirects the user to the web application which handles the callback and finally obtains a long-lived access token from Google.

These two routes can perfectly co-exist with any other web application framework. The framework provides the basis for web application-specific functionality whereas the OAuth service provider integration is done with Fuse Mediation Router. The OAuth integration part could even use resources from an existing servlet container by using the servlet component instead of the jetty component.

[Tip]What to do with the OAuth access token?
  • Application should store the access token in context of the current user. If the user logs in next time, the access token can directly be loaded from the database, for example, without doing the OAuth dance again.

  • The access token is then used to get access to Google services, such as a Google Calendar API, on behalf of the user. Java applications will most likely use the GData Java library for that. See Access token usage for an example how to use the access token with the GData Java library to read a user's calendar feed.

  • The user can revoke the access token at any time from his Google Accounts page. In this case, access to the corresponding Google service will throw an authorization exception. The web application should remove the stored access token and redirect the user again to the Google authorization page for creating another one.

The above example relies on the following component configuration.

<bean id="gauth" class="org.apache.camel.component.gae.auth.GAuthComponent">
    <property name="consumerKey" value="anonymous" />
    <property name="consumerSecret" value="anonymous" />
</bean>

If you don't want that Google displays a warning message on the authorization page, you'll need to register your web application and change the consumerKey and consumerSecret settings.

To OAuth-enable a Google App Engine application, only some small changes in the route builder are required. Assuming the GAE application hostname is camelcloud.appspot.com a configuration might look as follows. Here, the ghttp component is used to handle HTTP(S) requests instead of the jetty component.

[Note]GAuthRouteBuilder
import java.net.URLEncoder;
import org.apache.camel.builder.RouteBuilder;

public class TutorialRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        String encodedCallback = URLEncoder.encode("https://camelcloud.appspot.com/handler", "UTF-8");
        String encodedScope = URLEncoder.encode("http://www.google.com/calendar/feeds/", "UTF-8");

        from("ghttp:///authorize")
            .to("gauth:authorize?callback=" + encodedCallback + "&scope=" + encodedScope);

        from("ghttp:///handler")
            .to("gauth:upgrade")
            .process(/* store the tokens in context of the current user ... */);
    }

}

Here's an example how to use an access token to access a user's Google Calendar data with the GData Java library. The example application writes the titles of the user's public and private calendars to stdout.

[Note]Access token usage
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthParameters;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarFeed;

import java.net.URL;

public class AccessExample {

    public static void main(String... args) throws Exception {
        String accessToken = ...
        String accessTokenSecret = ...

        CalendarService myService = new CalendarService("exampleCo-exampleApp-1.0");
        OAuthParameters params = new OAuthParameters();
        params.setOAuthConsumerKey("anonymous");
        params.setOAuthConsumerSecret("anonymous");
        params.setOAuthToken(accessToken);
        params.setOAuthTokenSecret(accessTokenSecret);
        myService.setOAuthCredentials(params, new OAuthHmacSha1Signer());

        URL feedUrl = new URL("http://www.google.com/calendar/feeds/default/");
        CalendarFeed resultFeed = myService.getFeed(feedUrl, CalendarFeed.class);

        System.out.println("Your calendars:");
        System.out.println();

        for (int i = 0; i < resultFeed.getEntries().size(); i++) {
            CalendarEntry entry = resultFeed.getEntries().get(i);
            System.out.println(entry.getTitle().getPlainText());
        }
    }
}
Comments powered by Disqus