As you may recall from the last BORAX post, I had set up the application to transition to the start state which, for the purposes of our application, means someone needs to login. The application loads its first state as indicated by a linked relation in the header of the launchpad. Now, I sure think we would find it cool if we could handle the authentication.

Following along

This post will also cover some server-side development. If you want to follow along, install node.js and play with it. If you and others end up liking BORAX and its ability to make REST easy, then we can build bindings for non-node.js platforms.

If you want to start from the last post, clone the BORAX.js repository from GitHub and switch to the “post-1” tag.

Some server-side lovin’

BORIS

If you look at the current “example/server.js” in the repository, you’ll see a mess. Just a mess. Blech. Bad Curtis! But, every mess means a refactoring (or rewriting) opportunity!

Since this portion of the application deals with authentication, I think it would rock if I include the protection of resources in a server-side library that I will start writing in this post. The “lib/borax-in-server.js” will contain, obviously, the server-side components for BORAX on node.js.

It seems that the normal method for hooking in middleware to things like express.js and flatiron.js takes the form of a function with three parameters: the http.ServerRequest, the http.ClientResponse, and some next function to call if the registered handler did not fully handle the request. I can do the same here, I think.

Following the KISS with the perspective that “simple” refers to the use of the API, I think I can get away with the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var http = require('http')
, boris = require('borax-in-server')
, credential_function = require('my-auth-lib').authenticate
;

var auth = boris.auth(credential_function, content_function);
auth.addTree('/');

http.createServer(function(req, res) {
auth.protect(req, res, function() {
// Normal request processing.
});
}).listen(8181);

/* Or, if you use flatiron or the like, something like:
app.http.before.push(auth.protect);
*/

This would protect the path represented by ‘/‘ (the root) and all paths that would fall beneath it. That matches the requirements for the example application pretty nicely.

I’ll list the stories that describe boris. You can check out the tests and what not in the project.

For the borax-server library:

I changed the “server.js” file to use this new BORAX-provided asset protection. Now, things seem a little more reasonable. If I used flatiron or express, then I would have even less SLOCs in the server file. The following code abridges the actual server file and shows only the BORIS-related code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var creds = function(scheme, params) {
return scheme == 'Borax-Basic' &&
params['name'] == 'curtis' &&
params['password'] == 'password';
};

var challenge = function(res) {
var _401 = path.join('example', path.join('assets', '401.html'));
fs.readFile(_401, function(err, data) {
if(err) {
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('File Not Found');
return;
}
res.writeHead(401, {'Content-Type': 'text/html'});
res.end(data);
});
}

var protector = boris.auth(creds, challenge);
.addTree('/dashboard.html');

var server = http.createServer(function(req, res) {
var url = urlparse(req.url);
var asset_path = path.join('./example', url.pathname);
fs.stat(asset_path, function(err, stat) {

/* Use the protector to guard the configured path from above. */
protector.protect(req, res, function() {
if(stat && stat.isDirectory()) {
asset_path = path.join(asset_path, 'index.html');
}
var ext = path.extname(asset_path);
fs.readFile(asset_path, function(err, data) {
if(err) {
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('File Not Found');
return;
}
res.writeHead(200, {'Content-Type': mediaTypeExtensions[ext]});
res.end(data);
});
});
});
});