Email and App Authentication

Obindo lets you create an inbox for your app, so your users may quickly and easily forward information directly into whatever data schema you prefer. If you are sending your email to an app and you need to authenticate the user, you can use the following Obindo capabilities. Obindo presently supports both Basic Authentication as well as the OAuth 2 workflow, allowing each end user (whoever sends an email into your inbox) to authenticate their email with your application.

OAuth 2: There are many explanations and diagrams of the OAuth 2 workflow (such as yahoo and evernote). There are stated principles that in an ideal world, every application would adhere to. However, we've found that they don't all match those exactly. So we've provided the basic shell of the OAuth 2 workflow so that you can customize the important steps for your own application.

The basic OAuth 2 workflow:
  1. Register with the remote site. This is done by the developer before any connection can be made. Usually after registering, you're given a consumer key and consumer secret with which you make all subsequent calls. On some applications, you must configure how much access you would like to the end user's data (read, read and write, etc.).
  2. Redirect the end user to the remote site. Most times (though not always) this starts with doing a simple HTTP get of the site to obtain a request token which will be used later. Also typically, you will pass the URL to which the user will be redirected after they've logged in on the remote site (or this redirect URL is configured one time when registering with the site in step 1).
  3. Set access token once user is redirected back. When redirected back, there will be additional arguments in the querystring (usually a code). These are used (possibly with the request token from step 2) to make one more call to the remote site to obtain an access token. This token serves as the login credentials for the end user to the remote site; all calls from this point will use the access token.
  4. Refresh the access token. On some sites, the access token never expires. On others, it expires after a certain amount of time and needs to be refreshed. For these sites, a refresh token is returned along with the access token in step 3. When an attempt is made to access the system with an old access token, an unauthorized response is sent by the remote site (HTTP status code 401). At this point, a call needs to be made with the refresh token to obtain a new access token.
  5. Finally, access to the remote site. With the access token, you now have access to the user's data on the remote site. You can utilize the site's REST API to view/add/edit/delete their data.

How Obindo makes this easy
We take care of a lot of the OAuth 2 process for you -- all token saving, all communication with the end user, all browser redirection -- as well as provide utility methods to help you connect as quickly as possible (see them all here).

In the script, there are two additional objects: oauth2 and tokens.
  • oauth contains three methods which can be overwritten to be executed at the appropriate time during the OAuth 2 workflow.
  • tokens has the properties requestToken and accessToken which can be set from the values returned from the remote site and used again whenever necessary. The tokens are always unique to email address of the email received.

So here's the shell of what a script using OAuth 2 would look like:
//global variables to set
var requestTokenUrl, authorizeUrl, tokenUrl, newStatusUrl

* getAuthRedirectUrl: returns the url of the remote site 
* to which to redirect the user for login.
oauth2.getAuthRedirectUrl= function() {
    //retrieve request token from remote site, set it for use later
    var response= get(requestTokenUrl);
    tokens.requestToken= util.jsonify(response.text);

    //build url the user will be redirected to
    var args= { consumer_key: consumerKey, 
                //other arguments to pass
                callback= oauth2.getCallbackUrl() };  

    return authorizeUrl + '?' + util.getQueryArgsFromObject(args);

* onAuthResponse: Set the access token once the user
* has logged in on the remote site.
* takes in the querystring returned from the remote site's redirect.
oauth2.onAuthResponse= function(q) {
    var qResponse= util.getObjectFromQueryArgs(q);
    //build HTTP post to retrieve access token
    var args= { client_id: consumerKey,
                client_secret: consumerSecret,
                //other arguments to pass
                code: qResponse.code };
    var url= tokenUrl + '?' + util.getQueryArgsFromObject(args);
    var accessResponse= post({ url: url });

    tokens.accessToken= util.jsonify(accessResponse.text);

* refreshAccessToken: Use the saved refresh token 
* to obtain a new access token
oauth2.refreshAccessToken= function() {
    var rt= tokens.accessToken.refresh_token;
    var args= { grant_type: "refresh_token",
                refresh_token: rt,
                client_id: consumerKey,
                client_secret: consumerSecret };
    var url= tokenUrl + '?' + util.getQueryArgsFromObject(args);
    var response= post({ url: url });
    var newToken= util.jsonify(response.text);
    newToken.refresh_token= rt;
    tokens.accessToken= newToken;	

* "document ready" method: Once all tokens are set,
* the code to access the rest of the remote site's APIs.
$(function() {
  var url= newStatusUrl + '?status=' + util.urlEncode(message.text);  
  post({ url: url, header: { Authorization : 'OAuth ' + tokens.accessToken.access_token } });  
May look like a lot, but let's break that down into the basic OAuth 2 workflow steps...

The Obindo OAuth 2 workflow

1. Register with the remote site.
Sorry, we can't automate that! You'll still have to register with the remote site.

2. Redirect the end user to the remote site.
Override our oauth2.getAuthRedirectUrl method to return the remote site's url. Maybe just another step (typically an HTTP get) to retrieve a request token.

Obindo sends the end user an email saying that authentication is required. Also included is a link to an Obindo page which calls this script and redirects the user to the resulting URL.

3. Set access token once user is redirected back
Override our oauth2.onAuthResponse method which takes in the querystring the remote site takes back. Then you just have to set the tokens.accessToken property to a json object, most likely by making one more call to the remote site.

Obindo runs this script on another page in the browser. If successful, redirects the user to a success message.

4. Refresh the access token.
If necessary, override the oauth2.refreshAccessToken method to obtain a new access token from the remote site and save it back into the Obindo system. If the access token doesn't expire, you don't need to override this method.

5. Finally, access to the remote site.
Now you can make calls to the remote site's API using the stored access token to give you access to the user's data. (This is made to mimic the jQuery "document ready" method since once all the tokens are ready, this will run.)

Once a user is authenticated, this will run for every email sent in by the user on the server-side (i.e. without any browser needed to be opened).

Additional Notes
  • If your script doesn't require any OAuth 2, you don't need to override any of these methods. Also no need to use the "document ready" method, you can just script away against the message object
  • Worried about other users seeing your OAuth 2 credentials? Check out how to hide sections of your script from other users.
  • Writing several apps that access the same system? Does an Obindo app already exist that accesses a system you'd like to write an app for? You can avoid writing the entire OAuth2 workflow in each app by using the oauth2.use method.
  • Some sites require that one url (or a set list of urls) for redirection be configured when registering on their site (in step 1). We try to keep the authentication process as stateless as possible, so when the user is redirected back to Obindo, another step needs to be put in place to recognize with whom the access token is associated. Visit our cookbook for more details.
  • With this document, we are trying to address how OAuth 2 works for most sites. We've found that slight idiosyncrasies are common when trying to connect. We think we've covered all the steps that you may run into. Some have fewer steps (ex. no separate call for request token). Some have the same steps, but they are more complicated than described here (ex. requiring HMAC-SHA1 signatures).
    We try to make it as easy as possible with utility methods and code snippets. We also recommend clicking around other scripts to see if anyone else has already done the work (for example, tweet tackled HMAC-SHA1 signatures). If you've tried everything and think you are unable to connect, please contact us and let us know. Thanks.