Walkthrough: doing the miiCard OAuth exchange with Java
Some of the miiCard API wrapper libraries only deal with accessing the API once you've got OAuth tokens, and assume that you'll use a library of your choice to actually perform the OAuth exchange and get an access token and secret.
In an effort to make getting up and running with miiCard quicker we've started filling the gaps there, and have just published some example code for how to do the miiCard OAuth exchange using Java - in particular this is a JSP implementation but the bulk of it is readily portable to whatever framework you happen to be using. We're using the Signpost OAuth library to perform the exchange - the same library we depend on for the Java wrapper library.
The new code will make its way into the Java API wrapper library test harness when we next do a scheduled update, but you can find the individual code in the following GitHub Gists:
- Kicking off the OAuth flow by getting a request token and secret, and redirecting the client to miiCard
- Handling the callback from miiCard and turning the request token into an authorised access token and secret for use with the API
- A listener class that hooks into the Signpost library to correct a couple of issues related to reporting of Content-Length in requests it makes
- A sample web.xml file that ties the above together
The rest of this post is a walkthrough of the sample code and how it all wires together to perform the miiCard OAuth exchange.
Prerequisites and setup
The above code assumes that:
- You've got Signpost as a dependency in your project
- You've got the miiCard Java API Wrapper Library as a dependency in your project
Note: This code is for educational purposes only - it shows the bare minimum required to perform the OAuth exchange with miiCard but would of course require security and exception handling that is omitted to keep the sample easy to digest.
First, let's see an example web.xml file:
- Setting up a couple of parameters, 'MiiCardConsumerKey' and 'MiiCardConsumerSecret' to store our API key and secret respectively
- Letting the system know about two new Servlets - one to kick off the OAuth flow and one to finish it off as a callback from miiCard
- Mapping the two Servlets to two new URLs: /miicard/connect to start the flow, and /miicard/callback to finish it off
You'll need to amend the namespace in the two <servlet-class> tags to match where you use the code.
Kicking off the OAuth exchange
Starting with some code, we'll then break down what we're doing:
Breaking down some of the more interesting lines:
|Lines 26-27||Pulling the consumer key and secret in from configuration|
Creating a new Signpost OAuthConsumer using our consumer key and secret, and an OAuthProvider pointing to the miiCard OAuth endpoint and our consumer key
|Line 38||Sets a listener to fix an issue in Signpost that causes the Content-Length header to be omitted in some situations (see a little later on for an explanation)|
|Lines 42-44||Figures out the callback URL by replacing the end of the current URL with 'callback' to match the mapping defined in web.xml (above)|
|Line 46||Asks Signpost to retrieve a request token, obtaining the URL to which we should redirect the client in the process|
|Lines 50-51||Stores the OAuthConsumer and OAuthProvider in session state so that they're available to the callback method|
|Line 54||Redirects the user's browser to miiCard to sign in and authorise data sharing|
If all goes well, the user will find themselves at a miiCard login prompt where they can sign into the miiCard or create an account. They're then asked what data to share based on your API key configuration, before being returned to the URL we calculated in Lines 42-44.
Completing the OAuth exchange
Let's start with the source again:
This time around things are a little easier:
|Lines 19-20||Restores our OAuthConsumer and OAuthProvider from session state was put there as part of the kick-off request|
|Line 22||Again sets a listener to fix the Content-Length header issue|
|Line 27||Asks Signpost to request an authorised access token from miiCard for the user who's just returned|
|Lines 31-32||Pulls the access token and access token secret from the OAuthConsumer - it's these two that now give you access to the miiCard API|
|Lines 36-38||Dummy diagnostic code to just dump the access token and secret to the screen|
Of course, in your real application you wouldn't ever show the user their access token and secret. Instead you'd:
- Store the access token and secret in your database against the logged-in user's user profile
- Perhaps make a call to the miiCard API to check the user's identity assurance status or to consume their identity information
- Redirect the user back to your application
ZeroContentLengthFixListener - or fixing up Signpost
Signpost in some configurations fails to send a Content-Length header with requests to the miiCard OAuth endpoints, the absence of which causes miiCard's servers to reject the request.
Luckily Signpost provides two hooks where we can alter the request just before it's sent - that's what our ZeroContentLengthFixListener is doing:
When we're about to send a request, we call the setFixedLengthStreamingMode method with a content length of zero - this causes the correct header to be sent when making the request. We then also make sure that the request is capable of sending a POST body.
Once all of the above is namespaced, packaged and integrated into your application you would kick off the OAuth exchange by directing your user to /miicard/connect. They are then redirected to miiCard, and return to your site at /miicard/callback where an access token is obtained, before you store the tokens, call the API and redirect the user back to your application.