Skip to content

omarathon/oauth1-hmac

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OAuth1-HMAC

OAuth1-HMAC is a lightweight library implementing the OAuth1.0 protocol as a consumer, using the HMAC signing strategy.

This library wraps the Google OAuth Client Library for Java (google-oauth-client | GitHub) which implements the underlying OAuth1.0 functionality (JavaDoc).

Please note that the OAuth1.0 implementation in google-oauth-client is in Beta, and is thus subject to change. Its implementation has been tested and verified working for version 1.31.0. For higher versions, it exhibits buggy behaviour, thus the version of the google-oauth-client dependency shall only be bumped if the OAuth1.0 implementation remains unchanged and works.

If your project uses a conflicting version of google-oauth-client (such a dependency may come transitively from google-api-client) then usage of this library is highly unrecommended.

Documentation

The latest version of OAuth1-HMAC has a JavaDoc here.

Installation

To add this library as a dependency to your Maven project, add the following repository:

<repositories>
	<repository>
		<id>jitpack.io</id>
		<url>https://jitpack.io</url>
	</repository>
</repositories>

and the following dependency:

<dependencies>
	<dependency>
	    	<groupId>com.github.omarathon</groupId>
	    	<artifactId>oauth1-hmac</artifactId>
	    	<version>1.0</version>
	</dependency>
</dependencies>

Usage

Primary API

Main Instance

Usage of this library involves constructing either an OAuth1WithCallback (JavaDoc) instance, or an OAuth1NoCallback (JavaDoc) instance, depending on whether you're using a callback or not, respectively (a callback is the URL the user is redirected to after verifying their temporary token).

If using Spring, it's recommended to construct such an instance as a Configuration bean, and inject it via autowiring.

Both OAuth1WithCallback and OAuth1NoCallback require the following parameters to its constructor:

  • consumerKey::String - Required identifier portion of the client credentials (equivalent to a username). More information: client_id entry of the OAuthParameters table here
  • consumerSecret::String - Client-shared secret. More information: client_id entry of the OAuthParameters table here
  • requestTokenUrl::String - Encoded authorization server URL. More information: request_uri entry of the OAuthParameters table here
  • authoriseUrl::String - Encoded user authorization URL the user visits to verify their temporary token, or null if only wish to receive the temporary token and build it yourself
  • accessTokenUrl::String - Encoded authorization server URL, for requesting an access token from the service provider
  • tokenMapStrategy::TokenMapStrategy - Strategy to map temporary tokens to token secrets, and fetch the token secret for a temporary token

and OAuth1WithCallback requires an additional parameter:

  • callbackUrl::String - Absolute URI back to which the server will redirect the resource owner when the Resource Owner Authorization step has completed. More information: redirect_uri entry of the OAuthParameters table here
Example Instance

Using the University of Warwick's OAuth provider as an example, one may construct an OAuth1WithCallback instance with the following values:

  • consumerKey::String - "<YOUR_CONSUMER_KEY_FROM_WARWICK>"
  • consumerSecret::String - "<YOUR_CONSUMER_SECRET_FROM_WARWICK>"
  • requestTokenUrl::String - "https://websignon.warwick.ac.uk/oauth/requestToken"
  • callbackUrl::String - <YOUR_WEBSITE_LOGIN_URL>
  • authoriseUrl::String - "https://websignon.warwick.ac.uk/oauth/authorise"
  • accessTokenUrl::String - "https://websignon.warwick.ac.uk/oauth/accessToken"
  • tokenMapStrategy::TokenMapStrategy - new HashMapTokenMapStrategy()

TokenMapStrategy

On constructing either OAuth1WithCallback or OAuth1NoCallback, an instance of TokenMapStrategy (JavaDoc) must be provided:

interface TokenMapStrategy {
	void mapTemporaryTokenToTemporaryTokenSecret(@Nonnull String temporaryToken, @Nonnull String temporaryTokenSecret) throws TokenMapException
    
	@Nullable
	String fetchTemporaryTokenSecretForTemporaryToken(@Nonnull String temporaryToken) throws TokenMapException
}

where:

  • mapTemporaryTokenToTemporaryTokenSecret maps the given temporaryToken to the given temporaryTokenSecret persistently for at least the longest permissible duration of an OAuth1.0 handshake
  • fetchTemporaryTokenSecretForTemporaryToken retrieves the value of temporaryTokenSecret for the given temporaryToken from the map, and returns null if it does not exist

OAuth1-HMAC provides a preset implementation HashMapTokenMapStrategy (JavaDoc), which uses an in-memory static HashMap to persist the temporary token to token secret mapping. This could be used for prototyping / non-production purposes, but in production it's recommended to use a database.

Main Instance API

Both OAuth1WithCallback and OAuth1NoCallback provide the following instance methods:

  • begin - Requests a temporary token and corresponding token secret from the service provider, then maps the temporary token to the token secret via the TokenMapStrategy, and returns the obtained temporary token along with the authenticate URL (redirect URL) if authoriseUrl is non-null
  • authorised - Fetches the token secret corresponding to the temporary token via the TokenMapStrategy, then uses the obtained token secret along with the original temporary token (and verifier if using a callback, which is parsed on the front-end as a parameter to the callback URL) to obtain an access token from the service provider

and they both provide the following static method, which is used to make requests to the resource server on the user's behalf after a successful OAuth1.0 handshake:

  • makeOAuthBackedRequest - Makes a request to the given URL wrapped with a user's OAuth credentials (which includes their access token) obtained from authorised

Examples

Simple "Raw Java" Example

One may find an example application (which does not use a callback URL) in Example.java.

To use a callback URL, use an instance of OAuth1WithCallback instead of OAuth1NoCallback.

This simple example:

  1. Obtains and displays a temporary token and redirect URL from the service provider.
  2. Waits for the user to verify the temporary token by polling until a key-press occurs.
  3. After a key-press occurs, obtains and displays an access token from the service provider using their temporary token.
  4. Makes a request on the behalf of the user to the resource server using their access token, and displays the result.

For an understanding of the terms used in this example, please refer to the following diagram of the OAuth1.0 flow: OAuth1.0 Flow

Spring Example

A Spring example implementing a consumer for Warwick University's OAuth1.0 provider can be found here. Such example is listed as an official example in their list of example consumer implementations.

Testing

Both OAuth1NoCallback and OAuth1WithCallback have been tested and verified working in production.

  • OAuth1NoCallback has been tested via Example.java. The CONSUMER_KEY, CONSUMER_SECRET, REQUEST_TEMPORARY_TOKEN_URL, AUTHORISE_TEMPORARY_TOKEN_URL, ACCESS_TOKEN_URL and RESOURCE_SERVER_REQUEST_URL constants were filled with those matching a live provider, and the program succesfully does the OAuth1.0 handshake and obtains the expected data from the resource provider on behalf of the user. Feel free to perform such test yourself.

  • OAuth1WithCallback is being used live in production on ModulePal - a testimonial case of it working as intended. Its implementation is very similar to OAuth1NoCallback - there are no surprises here given that OAuth1NoCallback works as intended.

Support

Please contact Omar Tanner via Discord (omarathon#2226) if you require assistance with this library.