Skip to content

Commit

Permalink
Created parse() middleware via bootstrap() for interop with expre…
Browse files Browse the repository at this point in the history
…ss centric middleware
  • Loading branch information
avoidwork committed Aug 27, 2014
1 parent bde8c53 commit 4b67d75
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 50 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Added `OAuth2`, & `SAML` authentication
- Refactored `Local Auth` to use passport
- Refactored `auth()` to mix stateless & stateful auth strategies the same time
- Added `parse()` middleware via `bootstrap()` to coerce `req.body`

## 0.6.1
- Upgrading turtle.io to 3.0.15 for etag middleware fix (out of order execution negated it)
Expand Down
3 changes: 1 addition & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
},
"local": {
"enabled": false,
"auth": null,
"middleware": null
"auth": null
},
"saml": {
"enabled": false,
Expand Down
73 changes: 52 additions & 21 deletions lib/tenso.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var turtleio = require( "turtle.io" ),
util = keigai.util,
array = util.array,
clone = util.clone,
coerce = util.coerce,
iterate = util.iterate,
merge = util.merge,
string = util.string,
Expand All @@ -42,7 +43,10 @@ var turtleio = require( "turtle.io" ),
REGEX_SCHEME = /^(\w+\:\/\/)|\//,
REGEX_COLLECTION = /(.*)(\/.*)$/,
REGEX_MODIFY = /DELETE|PATCH|POST|PUT/,
REGEX_GETREWRITE = /HEAD|OPTIONS/i;
REGEX_GETREWRITE = /HEAD|OPTIONS/i,
REGEX_BODY = /POST|PUT|PATCH/i,
REGEX_FORMENC = /application\/x-www-form-urlencoded/,
REGEX_BODY_SPLIT = /&|=/;

/**
* Tenso
Expand Down Expand Up @@ -184,19 +188,21 @@ function auth ( obj, config ) {
authUris = [],
sesh, fnCookie, fnSesh, luscaCsrf, luscaCsp, luscaXframe, luscaP3p, luscaHsts, luscaXssProtection, protection, passportAuth, passportInit, passportSession;

/**
* Flags the request for async auth strategies
* @private
*/
function asyncFlag () {
arguments[0].protectAsync = true;
arguments[2]();
}

/**
* Authorization guard
* @private
*/
function init ( session ) {
passportInit = passport.initialize();
obj.server.use( passportInit ).blacklist( passportInit );

if ( session ) {
passportSession = passport.session();
obj.server.use( passportSession ).blacklist( passportSession );
}
}

function guard ( req, res, next ) {
if ( req.isAuthenticated() ) {
return next();
Expand All @@ -206,10 +212,6 @@ function auth ( obj, config ) {
}
}

/**
* Failure redirect
* @private
*/
function redirect () {
arguments[1].redirect( "/" );
}
Expand Down Expand Up @@ -305,14 +307,10 @@ function auth ( obj, config ) {
obj.server.use( protection ).blacklist( protection );

if ( stateless && !stateful ) {
passportInit = passport.initialize();
obj.server.use( passportInit ).blacklist( passportInit );
init( false );
}
else if ( stateful ) {
passportInit = passport.initialize();
passportSession = passport.session();
obj.server.use( passportInit ).blacklist( passportInit );
obj.server.use( passportSession ).blacklist( passportSession );
else {
init( true );

passport.serializeUser( function ( user, done ) {
done( null, user );
Expand Down Expand Up @@ -507,7 +505,24 @@ function auth ( obj, config ) {
} );
} ) );

obj.server.post( "/login", passport.authenticate( "local" ) );
config.routes.post = config.routes.post || {};
config.routes.post["/login"] = function ( req, res ) {
var final, mid;

final = function () {
passport.authenticate( "local", {successRedirect: "/"} )( req, res, function ( e ) {
if ( e ) {
res.error( 401, "Unauthorized" );
}
} );
};

mid = function () {
passportSession( req, res, final );
};

passportInit( req, res, mid );
};
}

if ( config.auth.oauth2.enabled ) {
Expand Down Expand Up @@ -612,11 +627,27 @@ function bootstrap ( obj, config ) {
next();
}

function parse ( req ) {
var args;

if ( REGEX_BODY.test( req.method ) && REGEX_FORMENC.test( req.headers["content-type"] ) ) {
args = req.body ? array.chunk( req.body.split( REGEX_BODY_SPLIT ), 2 ) : [];
req.body = {};

array.each( args, function ( i ) {
req.body[i[0]] = coerce( i[1] );
} );
}

arguments[2]();
}

function rateLimit ( req, res, next ) {
rate( obj, req, res, next );
}

obj.server.use( mediator ).blacklist( mediator );
obj.server.use( parse ).blacklist( parse );

if ( config.rate.enabled ) {
obj.server.use( rateLimit ).blacklist( rateLimit );
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"test": "grunt test"
},
"dependencies": {
"keigai": "0.6.1",
"turtle.io": "3.0.15",
"keigai": "0.6.2",
"turtle.io": "3.0.17",
"cookie-parser": "1.3.2",
"express-session": "^1.7.2",
"passport": "0.2.0",
Expand Down
51 changes: 31 additions & 20 deletions src/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@ function auth ( obj, config ) {
authUris = [],
sesh, fnCookie, fnSesh, luscaCsrf, luscaCsp, luscaXframe, luscaP3p, luscaHsts, luscaXssProtection, protection, passportAuth, passportInit, passportSession;

/**
* Flags the request for async auth strategies
* @private
*/
function asyncFlag () {
arguments[0].protectAsync = true;
arguments[2]();
}

/**
* Authorization guard
* @private
*/
function init ( session ) {
passportInit = passport.initialize();
obj.server.use( passportInit ).blacklist( passportInit );

if ( session ) {
passportSession = passport.session();
obj.server.use( passportSession ).blacklist( passportSession );
}
}

function guard ( req, res, next ) {
if ( req.isAuthenticated() ) {
return next();
Expand All @@ -39,10 +41,6 @@ function auth ( obj, config ) {
}
}

/**
* Failure redirect
* @private
*/
function redirect () {
arguments[1].redirect( "/" );
}
Expand Down Expand Up @@ -138,14 +136,10 @@ function auth ( obj, config ) {
obj.server.use( protection ).blacklist( protection );

if ( stateless && !stateful ) {
passportInit = passport.initialize();
obj.server.use( passportInit ).blacklist( passportInit );
init( false );
}
else if ( stateful ) {
passportInit = passport.initialize();
passportSession = passport.session();
obj.server.use( passportInit ).blacklist( passportInit );
obj.server.use( passportSession ).blacklist( passportSession );
else {
init( true );

passport.serializeUser( function ( user, done ) {
done( null, user );
Expand Down Expand Up @@ -340,7 +334,24 @@ function auth ( obj, config ) {
} );
} ) );

obj.server.post( "/login", passport.authenticate( "local" ) );
config.routes.post = config.routes.post || {};
config.routes.post["/login"] = function ( req, res ) {
var final, mid;

final = function () {
passport.authenticate( "local", {successRedirect: "/"} )( req, res, function ( e ) {
if ( e ) {
res.error( 401, "Unauthorized" );
}
} );
};

mid = function () {
passportSession( req, res, final );
};

passportInit( req, res, mid );
};
}

if ( config.auth.oauth2.enabled ) {
Expand Down
16 changes: 16 additions & 0 deletions src/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,27 @@ function bootstrap ( obj, config ) {
next();
}

function parse ( req ) {
var args;

if ( REGEX_BODY.test( req.method ) && REGEX_FORMENC.test( req.headers["content-type"] ) ) {
args = req.body ? array.chunk( req.body.split( REGEX_BODY_SPLIT ), 2 ) : [];
req.body = {};

array.each( args, function ( i ) {
req.body[i[0]] = coerce( i[1] );
} );
}

arguments[2]();
}

function rateLimit ( req, res, next ) {
rate( obj, req, res, next );
}

obj.server.use( mediator ).blacklist( mediator );
obj.server.use( parse ).blacklist( parse );

if ( config.rate.enabled ) {
obj.server.use( rateLimit ).blacklist( rateLimit );
Expand Down
6 changes: 5 additions & 1 deletion src/intro.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var turtleio = require( "turtle.io" ),
util = keigai.util,
array = util.array,
clone = util.clone,
coerce = util.coerce,
iterate = util.iterate,
merge = util.merge,
string = util.string,
Expand All @@ -32,4 +33,7 @@ var turtleio = require( "turtle.io" ),
REGEX_SCHEME = /^(\w+\:\/\/)|\//,
REGEX_COLLECTION = /(.*)(\/.*)$/,
REGEX_MODIFY = /DELETE|PATCH|POST|PUT/,
REGEX_GETREWRITE = /HEAD|OPTIONS/i;
REGEX_GETREWRITE = /HEAD|OPTIONS/i,
REGEX_BODY = /POST|PUT|PATCH/i,
REGEX_FORMENC = /application\/x-www-form-urlencoded/,
REGEX_BODY_SPLIT = /&|=/;
12 changes: 8 additions & 4 deletions test/tenso_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,15 @@ describe("Local", function () {
local: {
enabled: true,
auth: function ( username, password, callback ) {
callback( null, {username: username, password: password} );
if ( username === "test" && password === 123 ) {
callback( null, {username: username, password: password} );
}
else {
callback( true, null );
}
}
},
protect: ["/uuid"],
session: {}
protect: ["/uuid"]
}
} );

Expand Down Expand Up @@ -416,7 +420,7 @@ describe("Local", function () {
.form()
.send({username:"test", password:123})
.expectStatus(302)
.expectHeader("Location", "/uuid")
.expectHeader("Location", "/")
.use(persistCookies)
.end(function(err) {
if (err) throw err;
Expand Down

0 comments on commit 4b67d75

Please sign in to comment.