In this third and final part in this series of three post we’ll fill in the final piece of the puzzle and look at how we achieve the Dropbox authentication using OAuth. The previous two parts are found here and here.
First a disclaimer, I don’t claim to be knowledgeable about OAuth! I made the point in the last post that you don’t really need to be because the compositional approach hides the unnecessary details. However I’ve got to agree with the recommendation that you must understand the security implications before putting OAuth into a production environment.
The authentication process in our demo client application involves two services. The first is called Prepare. Remember from the previous post the user will be redirected to this service if they get an authentication failure whilst trying to browse a Dropbox directory.
Figure 1: OAuth Prepare Service
Prepare initiates communication with Dropbox service by sending the our demo client’s
consumer key and secret. The consumer key and secret are obtained from Dropbox when you register a new application on their developer pages. These are stored and returned by the OAuth Settings service. (We factor this out here rather than having a literal inside prepare because they are also needed by the second service, Prime.)
Figure 2: OAuth Settings Service
As we can see the settings contain a number of URLs in addition to the key and secret which are required to drive this negotiation. These URLs are:
requestTokenURL - service which the client application should call to obtain an access token using it’s consumer key and secret.
authorizeWebSiteURL - the web site the user should be redirected to, to login if necessary and approve access by the client application.
callbackURL - the URL that the authorizeWebsite will redirect back to after successful login.(in our case this is the prime service)
accessTokenURL the service used by the prime service to obtain an access token once the user has approved access and Dropbox has returned a uid.
The OAuth Prepare endpoint wraps the first part of the negotiation with Dropbox which involves sending the demo application specific consumer key and secret to obtain a request token. The request token and callbackURL are then appended as parameters onto the authorizeWebSiteURL which is put into the response. Looking at the nCoDE program in figure 1 we can see that the response from OAuth prepare is used twice. Firstly we sink it into the users session for use later by the Prime service. Secondly we extract the authorizeURL using XPath, that we sink to the httpResponse:/redirect. This has the effect of redirecting the users browser to the Dropbox web site where they will be presented with a page something like this:
You’ll notice the Sequence accessor is connected to the response. The sequence accessor allows a sequence of requests to be evaluated in order regardless of if they needed. In fact only the response from one of the arguments (the first one named response) is used and returned as it’s response. This is something that is not normally possible with the lazy functional evaluation of nCODE. In functional evaluation requests are only made to satisfy requirements made by the arguments to other endpoints.
When the Prepare service is requested it should redirect the users browser to Dropbox, they will login if necessary and then Dropbox will redirect back to the callback URL we specified in the OAuth settings with a UID. This will cause the invocation of our second service Prime. Prime performs the necessary final parts of the OAuth negotiation to tie the request token with the UID to obtain the access token it needs to invoke the dropbox API on behalf of the user.
Figure 3: OAuth Prime Service
We can see this final part of the negotiation is handled by the OAuth Prime accessor. It has three arguments, our OAuth settings, the response from OAuth Prepare that we stored in the users session and the UID parameter. The response from OAuth prime is the access token that we’ll to pass into subsequent HTTP requests to attach the appropriate OAuth headers to a request. In Prime we use the sequence accessor again to firstly store the access token in the session before using it to retrieve the users account information. First we request /account/info from Dropbox, this returns back a JSON representation of the users account details and usage information. We convert this to HDS using the JSONToHDS accessor and the style it into a HTML page using XSLT. This page then contains a “continue to files link…” which returns the user back to listing their root directory.
I hope this proved useful and instructive. I also hope it shows the compositional approach and how a small set of general purpose components working with a small set of generic representations can lead to rich solutions. If you want a copy of the module please drop me an email at tab at 1060.org. I’m reluctant to put up a put general download because of the uncertain status of the consumer key and secret provided by Dropbox. Really they should be obscured inside an application and will only be transmitted over the wire encrypted by HTTPS, of course this isn’t really possible with a code demo.