OAuth Plugin

OAuth Plugin

This is a Grails plugin to provide easy interaction with OAuth service providers. OAuth is an open standard for secure API authentication. Using OAuth, users can securely and easily allow third party applications to access their private data maintained by OAuth provider services through web service API. Refer to the OAuth 1.0 spec for complete details.

Installation

Under your Grails project's root directory, type this command to install the OAuth Plugin

grails install-plugin oauth

Usage

Configuration

Before using the OAuth plugin, the required OAuth parameters should be defined in Config.groovy of your project.

e.g. One consumer identity for each OAuth service provider:

oauth{
	provider_name{
		requestTokenUrl='http://example.com/oauth/request_token'
		accessTokenUrl='http://example.com/oauth/access_token'
		authUrl='http://example.com/oauth/authorize'
		consumer.key='key'
		consumer.secret='secret'
	}
}

In the above case, the OAuth provider name and the corresponding consumer name will both be "provider_name".

You can also specify multiple consumer identities for each OAuth service provider. e.g.:

oauth{
	provider_name{
		requestTokenUrl='http://example.com/oauth/request_token'
		accessTokenUrl='http://example.com/oauth/access_token'
		authUrl='http://example.com/oauth/authorize'
		consumers{
			consumer_a{
				key='key'
				secret='secret'
			}
			consumer_b{
				key='key'
				secret='secret'
			}
		}
	}
}

In the above case, the OAuth provider name will be "provider_name". The consumer names will be "consumer_a" and "consumer_b"

OAuth authorization workflow with the OAuth plugin

Asking for authorization

To initiate the OAuth authentication process, first call the "auth" action of the plugin's OauthController with the consumer name and other optional parameters. The taglib shipped with the plugin provides convenient tags to help you create the link to the action with the parameters. Refer to the "OauthTagLib" section below for information about the taglib. The "auth" action will perform the perparation work and redirect to the user authorization URL.

For example, the following code creates a link to the "auth" action. "myConsumer" should be specified in the config.
When the user clicks the link, the plugin will collect and prepare the required data and redirect to the user authorization URL of the service provider which the specified consumer belongs to. Then the user will be asked by the service provider whether to allow your application to access the user resources or not.

<g:oauthLink consumer='myConsumer' returnTo="[controller:'myController',action:'oauthComplete']">Authorize</g:oauthLink>

The callback and the access token 

OAuth plugin provides a predefined callback action. It also handles exchanging the authorized token with the access token. So the only thing you need to take care of is to define your own action to handle the access token stored in the session by the callback.

After the user has chosen to allow or disallow the access, the service provider redirects back to "callback" action of the OauthController. The "callback" action will do the more homework and finally store the access token in the session object "oauthToken". "oauthToken" is a map with entries "key" and "secret", which contains the token key and secret of the access token.

Then your application's "returnTo" controller action will be called. You can then have your own code handle the access token any way you want (e.g. store the access token in the database).

However, depending on the implementation of the service provider, you may have to specify a hard coded callback URL on the service provider's website. In that case, specify the callback URL at the service provider to the URL of the "callback" action of the "OauthController".
e.g.:

http://your.server/your-app/oauth/callback

You can also map the URL any way you like by using your own UrlMappings

Accessing OAuth protected resource

After the completion of OAuth authorization by obtaining the authorized access token, your application is now qualified to access the protected user resource. The OauthService#accessResource method provides a convenient way for doing this.

e.g. Accessing a read-only resource. The "GET" method is used by default. The response returned is a String containing the http response body.

def response = oauthService.accessResource('http://api.url','consumer_name',[key:'accesskey',secret:'accesssecret'])

e.g. Posting data to API resource.

def response = oauthService.accessResource('http://api.url',
					'consumer_name',
					[key:'accesskey',secret:'accesssecret'],
					'POST',
					[param1:'additional parameter']
					)

You can also use named parameters. Note that "consumer", "url", and "token" are required parameters.

def response = oauthService.accessResource(url:'http://api.url',consumer:'consumer_name',token:[key:'accesskey',secret:'accesssecret'], method:'POST')

Error handling

In case of  problems happening during OAuth methods from OauthService throw net.oauth.OAuthProblemException. You may catch the exception in your own code.

OauthController catches net.oauth.OAuthProblemException in its built-in actions and stores the error code in the session as "session.oauthError". The predefined error codes are:

  • oauth.unknown
  • oauth.requesttoken.missing
  • oauth.accesstoken.missing
  • oauth.400badrequest
  • oauth.oauth.401unauthorized
  • oauth.invalid.consumer
  • oauth.invalid.token

You can create i18n messages for each of the error code. You can open the messages.properties file shipped with the plugin to see the sample error messages and include them in your application's i18n messages file.

Reference

OauthService

accessResource(url, consumer, token, method='GET', params=null) - Helper function with default parameters to access an OAuth protected resource. "url", "consumer", and "token" are required. "token" should be a map containing two entries: "key" and "secret". Returns the response body from the service as a String.
accessResource(Map args) - Overloaded helper function with named parameters to access an OAuth protected resource. Returns the response body from the service as a String.

getConsumer(name) - Returns the consumer instance by name

getProvider(name) - Returns the OAuth service provider instance by name

getOauthClient() - Returns an OAuthHttpClient instance

*Below are methods used by OauthController internally. Usually you don't need to call them directly. But you might want to use them to write your own controller to handle the Oauth process instead of using the shipped OauthController.

fetchRequestToken(consumerName) 

getAuthUrl(key, consumerName, params)

fetchAccessToken(consumerName, requestToken)

OauthController

auth -  The action to call to start the OAuth authorization sequence

callback - This action will be called when the OAuth service provider returns from user authorization

OauthTagLib

oauthLink - Renders an OAuth user authorization request link to the service provider. "returnTo" and "error" are optional. If none specified, the current controller and action will be used by default. The "returnTo" controller action will be called by OauthController#callback when the authorization process completes successfully. "error" controller and action will be called in case of any problem occurs.
Example:

<g:oauthLink consumer='myConsumer'>Authorize</g:oauthLink>
<g:oauthLink consumer='myConsumer' returnTo="[controller:'myController',action:'oauthComplete']">Authorize</g:oauthLink>
<g:oauthLink consumer='myConsumer' returnTo="[controller:'myController']">Authorize</g:oauthLink>
<g:oauthLink consumer='myConsumer' returnTo="[controller:'myController',action:'oauthComplete']" error="[controller:'errorController',action:'errorAction']">Authorize</g:oauthLink>

oauthUrl - Construct the URL string for OAuth authorization action

hasOauthError - Renders the body of the tag when there's an OAuth error
Example:

<g:hasOauthError>
     <div class="errors">
           <g:renderOauthError />
     </div>
</g:hasLoginError>

renderOauthError - Renders the OAuth error. You should define messages for the error code. Refer to the "Error handling" section above.
Example:

<g:renderOauthError />

Plugin version history

0.1 (May 13, 2008)

Labels

 
(None)