Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Thursday, August 29, 2013

CSRF protection in a Play+AngularJS application

From Wikipedia:
Cross-site request forgery, also known as a one-click attack or session riding and abbreviated as CSRF (sometimes pronounced sea-surf[1]) or XSRF, is a type of malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts.[2] Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser.
There are plenty of articles online explaining such attacks and measures against them. The basic idea of such protection is to generate a CSRF token per session and send that token in every following request through means other than the Cookie request header (because it's the one that browser automatically set and hence the vulnerability). Typically the token can be sent back in a custom request header or in the request query string or an hidden input value in forms. Play has a built-in filter that implements such token based CSFR protection(here is a great blog article about it). However it's based on html form(with automatic query string generation). In a single-page application that relies on Play as a pure server-side API, most requests are performed by AJAX without involving html form. In that case CSRF token has to be sent through a custom request header. Our application uses AngularJS as our front-end framework. AngularJS also provides some facility to guard against CSRF (from AngularJS' documentation):
Angular provides a mechanism to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain could read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. The header will not be set for cross-domain requests. To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called XSRF-TOKEN on the first HTTP GET request. On subsequent XHR requests the server can verify that the cookie matches X-XSRF-TOKEN HTTP header, and therefore be sure that only JavaScript running on your domain could have sent the request.
So putting pieces together here is our implementation for CSFR protection in an AngularJS + Play application. The AngularJS side is automatic, so the work is at the play side to set token in the cookie and validate it.

When login succeeds, set the cookie that AngularJS consumers:
    Ok.withSession(("username" -> username).
       withCookies(Cookie("XSRF-TOKEN", createCSFRToken(username), httpOnly = false))
createCSFRToken is a function that hashes the username to a token so that the token is not reconstructible by attackers. httpOnly = true is there so that the cookie is readable by javascript (from the same domain of course).

For the following requests, here is the code to validate the token sent in the custom header (automatically set by AngularJS):
  def validateSessionUser(implicit request: RequestHeader): Option[String] = {
    request.session.get("username").filter { username =>
      request.headers.get("X-XSRF-TOKEN") == Some(createCSFRToken(username))
    }
  }
That's it. Feel free to ask any question in the comments.

Wednesday, January 30, 2013

Still not convinced about coffeescript?

Here is another example why you should start writing Coffeescript. The business story in this example is rather simple - I need to load all document from a collection (named Accounts), perform an asynchronous operation (notifyOwner) on each of them, and save all of them back to DB after all notifyOwner operations finish successfully. The following methods are available to achieve this simple task:
Account.find() #find all accounts
account.notifyOwner() 
account.save()
All three methods are asynchronous and return a jQuery promise which resolve with either the results or itself for chaining. Because there are multiple accounts involved, we will also need to take advantage of jQuery.when.

Here is how we implement the business logic in Coffeescript

Account.find()
  .then (accounts)->
     $.when (account.notifyOwner() for account in accounts)...
  .then (accounts...)->
     $.when (account.save() for account in accounts)...
  .done ->
     console.log 'successfully notified all owners'
It takes advantage of coffeescript's splats feature to overcome jQuery.when's inability to take in an array of deferred.
  #resolves only when all three deferred resolve) 
  jQuery.when(deferred1, deferred2. deferred3) 
  
  #immediately resolves with the array passed in) 
  jQuery.when([deferred1, deferred2. deferred3]) 
What Javascript does that Coffeescript translate to?
Account.find().then(function(accounts) {
  var account;
  return $.when.apply($, (function() {
    var _i, _len, _results;
    _results = [];
    for (_i = 0, _len = accounts.length; _i < _len; _i++) {
      account = accounts[_i];
      _results.push(account.notifyOwner());
    }
    return _results;
  })());
}).then(function() {
  var account, accounts;
  accounts = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
  return $.when.apply($, (function() {
    var _i, _len, _results;
    _results = [];
    for (_i = 0, _len = accounts.length; _i < _len; _i++) {
      account = accounts[_i];
      _results.push(account.save());
    }
    return _results;
  })());
}).done(function() {
  return console.log('successfully notified all owners');
});
If you don't mind a bit help from underscore, We probably can simplify the iteration logic:
Account.find().then(function(accounts) {
  var account;
  return $.when.apply($, (function() {
    return _(accounts).map(function(account){
      return account.notifyOwner();
    });
  })());
}).then(function() {
  var accounts = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
  return $.when.apply($, (function() {
    return _(accounts).map(function(account){
      return account.save();
    });
  })());
}).done(function() {
  return console.log('successfully notified all owners');
});
So, that's clearly a lot more key strokes than Coffeescript but that's not the point. The point is how easy to read this Javascript version vs the Coffeescript version. Code could be written only once but it often times has to be read multiple times afterwards. Which version will you rather read?

Now, are you convinced?

Thursday, September 22, 2011

queffee.js - a dynamic priority worker queue in javascript/coffeescript

Recently I wrote a very simple javascript library that helps manage asynchronous tasks. I named it queffee (github). It was written in coffeescript but the compiled javascript file is available too. This article gives an introduction about this library and how it can help a web application on the client side.

queffee.js is a small library and for the most part it has two public classes: queffee.Q - a dynamic priority job queue and queffee.Worker - well, a worker. You can enqueue tasks (asynchronous functions) into the queue and start a worker, then the worker will run those functions one by one. You can also start multiple workers can they will work on multiple tasks in parallel (in a single thread).

As an example ajax web application, let's look at a picture slide show running in a browser.
Let's start with the basic usage. In the slide show, there are many picture objects, which have a preload function that preloads the picture content to the browser so that when user select to display them, they will be immediately ready. This preload function is asynchronous and takes in a callback to call when the preload is done.
 class Picture
    preload: (callback) =>
      #preloading itself in browser, callback on success

You can always simply do
  for pic in pictures
    picture.preload()

The issue here is that because preload is asynchronous, this will run all of them simultaneously, so if you have too many pictures, that might be simply too many requests to the server. You can better manage that using queffee.
    q = new queffee.Q
    worker = new queffee.Worker(q)
    for pic in pictures
      q.enQ picture.preload

The worker will preload picture one after another, so one request at a time. If you want more simultaneous connections you can always start more workers.
  anotherWorker = new queffee.Worker(q)
  #or
  _(4).times -> new queffee.Worker(q)

Now let's look at a more advanced use case. In a slide show, users might select to skip some pictures and jump to a picture further down in slide. So preloading the pictures they already skipped is probably not as important as preloading the pictures immediately after the one they are seeing now. So we need to prioritize the preloading according to the current progress of the user. queffee supports that. When you enQ, you can give it a priority function and it will be used for the priority queue. Let's say you added a priority function to your picture class
  class Picture
    priority: =>
      #calculates its priority according to the distance to the current progress

then you can enQ the preloads like the following
   q.enQ picture.preload, picture.priority

Now when users skip pictures, you just need to call
   q.reorder()

Then the preloading works will be re-prioritized according to the new slideshow progress.
If you don't need to dynamically prioritize the tasks, you can also pass in a number value as the priority.

So far so good right? Another really interesting usage of queffee is to support offline mode for you ajax application.
Back to the picture slide show as the example. With enough preloaded pictures, it should be able to work fine after the browser goes offline. However, like most other ajax web apps, even with the data available locally, it still needs to update state back to server. Specifically in this app, if user operated on the picture, it needs to update the server with the latest states. More specifically, it needs to send ajax put/post requests back to the server. We don't really need a response from the server but if the browser goes offline, such ajax requests will be lost. With queffee, the problem can be elegantly solved with the following code.
  class Updater
    constructor: ->
      @_q = new queffee.Q
      @_worker = new queffee.Worker(@_q)

    put: (url, data) => this._addJob('put', url, data)

    post: (url, data) => this._addJob('post', url, data)

    _addJob: (method, url, data) =>
      @_q.enQ (callback) =>
        $.ajax(
                url: url
                data: data
                type: type
                success: callback
                error: => setTimeout(@_worker.retry, 180000)
              )

Then just use this updater to do the ajax update
  class Picture
    update: => updater.put('/picture', this)

That's it. The picture.update() methods is offline safe now. The Updater class uses queffee to run the ajax requests one by one. If disconnection causes one ajax request to fail, it will automatically retry every 3 minutes until it succeeds and continue with the following one. The way it detects the disconnection is a bit naive here but you got the idea.
There are two not so obvious things here: 1) the worker will not proceed to the next job until the current job finishes and calls callback, so if the ajax call in the current job fails, the worker will stay with the current job 2) the worker.retry() function re-run current job again which if succeeds, will start moving things again.

Be default queffee.Worker waits on the asynchronous task indefinitely, but if you give it a ms timeout (value or function), it will move on the next task after timeout.
For example, the following code waits at most 10 seconds for the picture to finish reload, after which the next picture will get preloaded.
   q.enQ picture.preload, picture.priority, 10000


In some cases you have a collection of asynchronous tasks and you want to run all of them sequentially and meanwhile monitor the progress. I wrote a util class in queffee called CollectionWorkQ just for that.
Here is the usage, let's still take the preloading pictures as the example, except this time we don't care about the priority but we need to monitor the progress.
    new queffee.CollectionWorkQ(
      collection: pictures
      operation: 'preload'
      onProgress: -> alert('another picture ready!')
      onFinish: -> alert('finished')
    ).start()

This should be intuitive enough, the operation option takes in a function name that will be called on each item of the collection. The operation option can also be a function that takes in an item and a callback like the following
    new queffee.CollectionWorkQ(
      collection: pictures
      operation: (picture, callback) -> picture.preload(callback)
    ).start()


That's it. Thanks for reading this. I hope it can be of usage for your projects. Again, it's on github, any contribution will be great.

Wednesday, August 24, 2011

Why Coffeescript's fat arrow makes it more functional (than JS)

We all know that in JS this is not read from the scope chain, it's reset on a context by context basis. Experienced JS programmers work around it and are quite used to it, but I think this fact made JS a lot less beautiful than it should be. Here is a simple example


var Note = Backbone.Model.extend({
initialize: function() {},
delete: function() {
//do something
this.log('deleted');
},
log: function(msg) {
alert(msg);
}
});
var note = new Note();

$('#delete-note').click(function(){
note.delete();
});


Sure, backbone.js already makes things a lot cleaner but the itchy point is this

$('#delete-note').click(function(){
note.delete();
});

The fact that you have to wrap the event handler within a function just make it more like a block passed in than what it really is - a function, especially when you are from a ruby background.
It really should just be

$('#delete-note').click(note.delete);


Well, you can't. If you do that, all the 'this' will be of a different meaning in the body of the delete function - in our example, it will complain that the log is undefined for HTMLElement.
Here is what Coffeescript gives you with its wonderful fat arrow

class Note extends Backbone.Model
delete: =>
#do something
this.log('deleted')
log: (msg) =>
alert(msg)

note = new Note
$('#delete-note').click note.delete

At a glance, it might look like just some keystroke savings. But from my experience the mind set that you can just pass any function as variables around is what makes it a lot more FUNctional.