Blog Archives

Securing Express Routes with PassportJS

It’s been a while since I posted anything, but I finally found something worth blogging about! Besides my trip to India at the beginning of the year and not much work recently…

Recently I’ve been building a web app for my gaming clan to help them run their practices and also to help me learn more of Node.js and NOSQL (CouchDB in particular). My first big problem in building this app was that of user login, or authentication. After googling around a bit for some modules to help with this (I really like the modular nature of node.js!) I came across a unified login system called Auth0, which I have to say is really awesome. I decided to go with this as who hasn’t thought that letting people login using facebook or similar would be cool but it’s too hard to bother! After running through their node.js tutorial which makes use of PassportJS and their authentication strategy passport-auth0 I came up with the following basic login/authentication code. (This is stripped down a bit, for my full code see here)


http = require 'http'
express = require "express" # Note this is Express v3.5.x

app = module.exports = express()

httpServer = http.createServer app

passport = require 'passport'
Auth0Strategy = require 'passport-auth0'
security = require('./security')

strategy = new Auth0Strategy 
	domain:       security.auth0.domain
	clientID:     security.auth0.clientID
	clientSecret: security.auth0.clientSecret
	callbackURL:  '/callback'
, (accessToken, refreshToken, profile, done) ->
	console.log "Hit Auth0 strategy"
	done null, profile

passport.use strategy

# This is not a best practice, but we want to keep things simple for now
passport.serializeUser (user, done) -> done null, user

passport.deserializeUser (user, done) -> done null, user

helmet = require 'helmet'
	
app.configure ->
	app.use express.logger 'dev'
	app.set 'views', "#{__dirname}/views"
	app.engine 'jade', require('consolidate').jade
	app.set 'view engine', 'jade'
	
	app.use helmet.xframe(), helmet.iexss(), helmet.contentTypeOptions(), helmet.cacheControl()
	app.use express.json(), express.urlencoded()
	app.use express.methodOverride()
	app.use express.cookieParser()
	app.use express.session
		secret: security.cookieSecret
		#cookie:
			#httpOnly: true
			# secure: true # for HTTPS only
	app.use passport.initialize()
	app.use passport.session()
	app.use require('express-validator')()
	
app.all '/api/*', auth

auth = (req, res, next) -> if req.isAuthenticated() then next() else res.redirect '/login'

# Auth0 callback handler
app.get '/callback', passport.authenticate('auth0',
	failureRedirect: '/login'
), (req, res) ->
	if not req.user then throw new Error 'user null'
	if req.user._json.appid?
		req.session.dbconn = require('./../startup_security/nano').nano req.user._json.user_id, req.user._json.dbpass
		res.redirect "/#{req.user._json.appid}/manage"
	else res.redirect "/first-login"

# warning this would log you out of facebook if you logged in via the facebook button - don't use this in live!
app.get '/logout', (req, res) ->
	req.logout()
	delete req.session
	delete req.user
	res.redirect "https://simeonc.auth0.com/logout?returnTo=http://tawmanager.localhost:3000/"

app.get '/login', (req, res) -> res.render 'login.jade'
app.get '/first-login', auth, (req, res) -> res.render 'first-login.jade'

httpServer.listen 3000

console.log "Server Running on port 3000 via ExpressJS"
console.log "Authentication Via Passport.js and Auth0"

Now this is my final code after some help from the owner of passport-node0 here. Now I’ll detail some of the quirks I had to get through that are really, really poorly documented.

First; Authenticating individual routes. Initially from reading through what other people have written and the other information out there I tried this:

<pre>app.get '/first-login', passport.authenticate('auth0'), (req, res) -> res.render 'first-login.jade'</pre>

That is WRONG, and meant I spent many many hours looking at 302 redirects from that page back to the login page for no discernable reason…
Correct is:

auth = (req, res, next) -> if req.isAuthenticated() then next() else res.redirect '/login'</pre>
<pre>app.get '/first-login', auth, (req, res) -> res.render 'first-login.jade'</pre>
<pre>

Secondly; Authenticating all routes matching a particular prefix. From here and there around the web I thought you did this via:

app.use '/api', auth

Turns out that’s also wrong (this ones in the docs so I felt really stupid when I found it). Here’s the correct one:

app.all '/api/*', auth

Why I’ve come to love functional programming

Recently I have been starting to learn Node.js and inadvertently changed my opinion of functional programming VS Object Oriented programming. During my work on supporting legacy Coldfusion sites I stumbled across some code that forms the basis of this comparison of functional programming VS Object Oriented programming. (PS if you want a good introduction to the differences look on over to: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html).

This particular example will be Coldfusion and Pseudo-javascript (or coffeescript) and focuses around a multi-keyword search on 3 columns on 2 tables. Our tables are as follows:

Table Name: Jedi
With Columns: Name, Planet, Lightsaber_Colour.

Table Name: Sith
With Columns: Name, Catch_Phrase, Teacher.

First of all we will define a master function, and a convenience function for searching each of the tables, we do this for an attempt at reusability. We’ll call this main search function “galacticSearch” which will return a SQL string and take the arguments: Keyword (required, string), table (required, string) and andFlag (optional, boolean, defaults to true). The andFlag determines whether our search will return with all the keywords or any of the keywords (AND and OR searches respectively). The SQL returned will be less than perfect as really we should use something more forgiving and inclusive than the ‘=’ operator, for example in MSSQL name LIKE “%#ListGetAt(arguments.keywords, i, ‘ ‘)#%”. Also the params should be using cfqueryparam etc etc, it’s not perfect code but it doesn’t have to be production code for illustration purposes!

Here’s my implementation in Coldfusion, standing up for the Object Oriented languages:

<cffunction name="jediSearch" returnType="string">
	<cfargument name="keywords" required="true" required="false" type="string">
	<cfargument name="andFlag" required="false" type="boolean" default="true">
	<cfreturn galacticSearch(arguments.keywords,'jedi',arguments.andFlag)>
</cffunction>

<cffunction name="sithSearch" returnType="string">
	<cfargument name="keywords" required="true" required="false" type="string">
	<cfargument name="andFlag" required="false" type="boolean" default="true">
	<cfreturn galacticSearch(arguments.keywords,'sith',arguments.andFlag)>
</cffunction>

<cffunction name="galacticSearch" returnType="string">
	<cfargument name="keywords" required="true" required="false" type="string">
	<cfargument name="table" required="true" type="string">
	<cfargument name="andFlag" required="false" type="boolean" default="true">
	<cfscript>
		var sql = 'SELECT * FROM #arguments.table# WHERE ';
		//loop through the keywords
		for(var i = 1; i LTE ListLen(arguments.keywords, ' '); i++){
			//change the columns for each table
			if(arguments.table is 'jedi'){
				sql &= "(name = '#ListGetAt(arguments.keywords, i, ' ')#'";
				sql &= "OR planet = '#ListGetAt(arguments.keywords, i, ' ')#'";
				sql &= "OR lightsaber_colour = '#ListGetAt(arguments.keywords, i, ' ')#')";
			}else{
				sql &= "(name = '#ListGetAt(arguments.keywords, i, ' ')#'";
				sql &= "OR catch_phrase = '#ListGetAt(arguments.keywords, i, ' ')#'";
				sql &= "OR teacher = '#ListGetAt(arguments.keywords, i, ' ')#')";
			}
			if(i LT ListLen(arguments.keywords, ' ')){
				sql &= (arguments.andFlag)?' AND ':' OR ';
			}
		}
		return sql;
	</cfscript>
</cffunction>

Now if your like me, you look at this code and think “How on earth do I add another table easily and safely?”. Well you have to add a new function like “jediSearch” and then add an extra if/else into the loop in galacticSearch. Personally I’d rather not do that as it’s kind of messy and galacticSearch isn’t really the generic function I’d like it to be. Also when you edit like this you risk breaking something already working and increasing development time.

So next we move onto my solution in Pseudo-Javascript. Things of note are that we have changed the galacticSearch function to also take a columnsFunction that takes a keyword and returns the WHERE clause SQL for searching a tables columns for one keyword.

searchJedi = (keywords, andFlag = true) ->
	return galacticSearch keywords, 'jedi', andFlag, (keyword) ->
		return "(name = '#{ keyword }' OR planet = '#{ keyword }' OR lightsaber_colour = '#{ keyword }')"

searchSith = (keywords, andFlag = true) ->
	return galacticSearch keywords, 'sith', andFlag, (keyword) ->
		return "(name = '#{ keyword }' OR catch_phrase = '#{ keyword }' OR teacher = '#{ keyword }')"

galacticSearch = (keywords, andFlag = true, table, columnsFunction) ->
	sql = 'SELECT * FROM #{ table } WHERE '
	keys = keywords.split(' ')
	for i, key in keys
		sql += (if i gt 0 then (andFlag)?' AND ':' OR ' ELSE '') + columnsFunction(key)
	return sql

I think that the code is organised much tidier in the pseudo-javascript version. All the code referring to the interpretation of the keywords is in one place and all the code about searching the tables is held in another function. This in turn means that adding another table or more complexity to your keywords is not hard and you don’t risk messing up your previous code by doing it! That I think is very cool, especially if you have to work with other people/s code.

Admittedly you *could* do something similar in Object Oriented world, if you created a “Jedi” object and a “Sith” object and then coded the galacticSearch to take an object as an argument instead of a table name, but this seems like overly complicating things. Of course there is a case somewhere where passing the object is a better approach, but for most of my coding I’d rather the anonymous function approach I used in the functional programming version.

Chime in the comments if you have an opinion – I’m fairly new to functional programming so hearing from other people who know more than me is always nice!

Close browser window after print

On inheriting a site with a print popup window – ie a print button that is supposed to open another invisible window for print formatting, print said page, then invisibly close. I encountered a bug that occurred on newer browsers in the popup javascript from this code:

this.window.print();
this.window.close();

This is expected to show the print dialog and then close the window with print formatting, but it doesn’t! Most just ignore the close() call altogether and I think IE throws some kind of error, I had a different issue in IE that I fixed afterwards so I’m not sure what happens in IE. After some searching the best solution (sans jQuery) I found is linked at the top. Making use of timers and detecting when the page has finished loading as the print() call prevents the js from processing any further so it stops the page from being counted as “ready”.

AngularJS Table Sort Service

I’ve been meaning to do an angular post for a while having enjoyed the framework immensely. First off, go have a look here http://jsfiddle.net/Xanetia/Azhg7/. It supports multiple direction and column (hold shift and click headers) sorting (actually on any ng-repeat, but a table is the simplest usage). Now all you have to do if you want to use it is copy the factory as in that link, or download the following file (which has a bunch of other useful directives as well) and include the ‘sdevgame’ in your module declaration (eg angular.module(‘myapp’, [‘sdevgame’])): http://www.mediafire.com/?96p8pk72u0h2rfr

To use this table sorting service (or in fact to sort ANY ngRepeat) you have to do the following:

  1. Inject MultiOrder into your controller.
  2. Add ng-click=”modOrder($event, ‘name’)” where ‘name’ is the variable you want to orderBy in the ngRepeat, to the elements that you want to use for ordering. In the jsFiddle above I use the <th> tags to order each column.
  3. Add ” | orderBy: MultiOrder.orderArray” to any ngRepeats you want to order (this even works on multiple as long as the object names are the same).
  4. In your controller setup the following:
    $scope.MultiOrder = MultiOrder;
    $scope.MultiOrder.orderArray = ['-name'];//set the initial order
    $scope.MultiOrder.forceOrder = ['+name'];//set any default forced order
    $scope.MultiOrder.plusSortClass = "green";//these classes are put on the element when the sort is applied
    $scope.MultiOrder.minusSortClass = "blue";
    
    $scope.modOrder = MultiOrder.modOrder;

Note: I haven’t figured a way of dynamically applying the initial sorting class, so if you set the initial order or a force order don’t forget to add the class to the relative order element.