Skip to content

Commit

Permalink
Merge pull request hapijs#512 from walmartlabs/user/eran
Browse files Browse the repository at this point in the history
Direct use of Boom (0.3.0)
  • Loading branch information
geek committed Feb 11, 2013
2 parents 6c3ecc0 + 919674d commit 654f5d6
Show file tree
Hide file tree
Showing 39 changed files with 485 additions and 259 deletions.
8 changes: 4 additions & 4 deletions examples/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ internals.main();
Try various URLs like:
http://localhost:8080/ // success
http://localhost:8080/?username=test // success
http://localhost:8080/admin?username=walmart&password=worldofwalmartlabs // success
http://localhost:8080/admin?username=walmart // fail
http://localhost:8080/users?email=vnguyen@walmart.com // success
http://localhost:8080/users?email=@walmart.com // fail
http://localhost:8080/admin?username=steve&password=shhhhhh // success
http://localhost:8080/admin?username=steve // fail
http://localhost:8080/users?email=steve@example.com // success
http://localhost:8080/users?email=@example.com // fail
http://localhost:8080/config?choices=1&choices=2 // success
http://localhost:8080/config?choices=1 // success
http://localhost:8080/config // fail
Expand Down
2 changes: 1 addition & 1 deletion examples/views/cms/views/partials/footer.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<footer><p>&copy; @WalmartLabs 2013</p></footer>
<footer><p>&copy; @Someone 2013</p></footer>
16 changes: 8 additions & 8 deletions lib/auth/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

var Cryptiles = require('cryptiles');
var Utils = require('../utils');
var Err = require('../error');
var Boom = require('boom');


// Declare internals
Expand Down Expand Up @@ -33,24 +33,24 @@ internals.Scheme.prototype.authenticate = function (request, callback) {
var req = request.raw.req;
var authorization = req.headers.authorization;
if (!authorization) {
return callback(Err.unauthorized(null, 'Basic'));
return callback(Boom.unauthorized(null, 'Basic'));
}

var parts = authorization.split(/\s+/);

if (parts[0] &&
parts[0].toLowerCase() !== 'basic') {

return callback(Err.unauthorized(null, 'Basic'));
return callback(Boom.unauthorized(null, 'Basic'));
}

if (parts.length !== 2) {
return callback(Err.badRequest('Bad HTTP authentication header format', 'Basic'));
return callback(Boom.badRequest('Bad HTTP authentication header format', 'Basic'));
}

var credentialsParts = new Buffer(parts[1], 'base64').toString().split(':');
if (credentialsParts.length !== 2) {
return callback(Err.badRequest('Bad header internal syntax', 'Basic'));
return callback(Boom.badRequest('Bad header internal syntax', 'Basic'));
}

var credentials = {
Expand All @@ -67,15 +67,15 @@ internals.Scheme.prototype.authenticate = function (request, callback) {

if (!user) {
request.log(['auth', 'error', 'user', 'unknown']);
return callback(Err.unauthorized('Bad username or password', 'Basic'), null, true);
return callback(Boom.unauthorized('Bad username or password', 'Basic'), null, true);
}

if (!user.hasOwnProperty('password') ||
!user.id ||
user.id !== credentials.username) {

request.log(['auth', 'error', 'user', 'invalid']);
return callback(Err.internal('Bad user object received for Basic auth validation'), null, true);
return callback(Boom.internal('Bad user object received for Basic auth validation'), null, true);
}

if (typeof self.settings.hashPasswordFunc === 'function') {
Expand All @@ -86,7 +86,7 @@ internals.Scheme.prototype.authenticate = function (request, callback) {

if (!Cryptiles.fixedTimeComparison(user.password, credentials.password)) {
request.log(['auth', 'error', 'user', 'password']);
return callback(Err.unauthorized('Bad username or password', 'Basic'), null, true);
return callback(Boom.unauthorized('Bad username or password', 'Basic'), null, true);
}

// Authenticated
Expand Down
43 changes: 24 additions & 19 deletions lib/auth/cookie.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Load modules

var Utils = require('../utils');
var Err = require('../error');
var Boom = require('boom');
var Redirection = require('../response/redirection');


Expand All @@ -26,7 +26,8 @@ exports = module.exports = internals.Scheme = function (server, options) {
var cookieOptions = {
encoding: 'iron',
password: this.settings.password,
isSecure: !this.settings.allowInsecure
isSecure: !this.settings.allowInsecure,
path: '/'
};

if (this.settings.ttl) {
Expand All @@ -49,25 +50,13 @@ internals.Scheme.prototype.authenticate = function (request, callback) {

var self = this;

// Decorate request

request.setSession = function (session) {

request.setState(self.settings.cookie, session);
};

request.clearSession = function () {

request.clearState(self.settings.cookie);
};

var validate = function () {

// Check cookie

var session = request.state[self.settings.cookie];
if (!session) {
return unauthenticated(Err.unauthorized());
return unauthenticated(Boom.unauthorized());
}

self.settings.validateFunc(session, function (err, override) {
Expand All @@ -78,7 +67,7 @@ internals.Scheme.prototype.authenticate = function (request, callback) {
}

request.log(['auth', 'validate'], err);
return unauthenticated(Err.unauthorized('Invalid cookie'), session, true);
return unauthenticated(Boom.unauthorized('Invalid cookie'), session, true);
}

if (override) {
Expand All @@ -89,10 +78,10 @@ internals.Scheme.prototype.authenticate = function (request, callback) {
});
};

var unauthenticated = function (err) {
var unauthenticated = function (err, session, wasLogged) {

if (!self.settings.redirectTo) {
return callback(err);
return callback(err, session, wasLogged);
}

var uri = self.settings.redirectTo;
Expand All @@ -107,10 +96,26 @@ internals.Scheme.prototype.authenticate = function (request, callback) {
uri += self.settings.appendNext + '=' + encodeURIComponent(request.url.path);
}

return callback(new Redirection(uri));
return callback(new Redirection(uri), session, wasLogged);
};

validate();
};


internals.Scheme.prototype.extend = function (request) {

var self = this;

// Decorate request

request.setSession = function (session) {

request.setState(self.settings.cookie, session);
};

request.clearSession = function () {

request.clearState(self.settings.cookie);
};
};
2 changes: 1 addition & 1 deletion lib/auth/hawk.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

var Hawk = require('hawk');
var Utils = require('../utils');
var Err = require('../error');
var Boom = require('boom');


// Declare internals
Expand Down
51 changes: 31 additions & 20 deletions lib/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var Hawk = require('./hawk');
var Basic = require('./basic');
var Cookie = require('./cookie');
var Utils = require('../utils');
var Err = require('../error');
var Boom = require('boom');
var Log = require('hapi-log');


Expand All @@ -30,6 +30,7 @@ exports = module.exports = internals.Auth = function (server, options) {
// Load strategies

this.strategies = {};
this.extensions = [];
for (var name in settings) {
if (settings.hasOwnProperty(name)) {
var strategy = settings[name];
Expand All @@ -46,6 +47,12 @@ exports = module.exports = internals.Auth = function (server, options) {
case 'cookie': this.strategies[name] = new Cookie(this.server, strategy); break;
default: this.strategies[name] = strategy.implementation; break;
}

if (this.strategies[name].extend &&
typeof this.strategies[name].extend === 'function') {

this.extensions.push(this.strategies[name]);
}
}
}

Expand All @@ -55,6 +62,14 @@ exports = module.exports = internals.Auth = function (server, options) {

internals.Auth.authenticate = function (request, next) {

// Extend requests with loaded strategies

if (request.server.auth) {
for (var i = 0, il = request.server.auth.extensions.length; i < il; ++i) {
request.server.auth.extensions[i].extend(request);
}
}

// Modes: required, optional, try, none

var config = request.route.auth;
Expand Down Expand Up @@ -97,7 +112,7 @@ internals.Auth.prototype.authenticate = function (request, next) {
return next();
}

return next(Err.unauthorized('Missing authentication', authErrors));
return next(Boom.unauthorized('Missing authentication', authErrors));
}

var strategy = self.strategies[config.strategies[strategyPos++]]; // Increments counter after fetching current strategy
Expand All @@ -109,24 +124,21 @@ internals.Auth.prototype.authenticate = function (request, next) {
// Unauthenticated

if (!err && !session) {
return next(Err.internal('Authentication response missing both error and session'));
return next(Boom.internal('Authentication response missing both error and session'));
}

if (err) {
if (!wasLogged) {
request.log(['auth', 'unauthenticated'], err);
}

if (err instanceof Error === false) { // Not an actual error (e.g. redirect, custom response)
return next(err);
}

if (!err.isMissing ||
err.code !== 401) { // An actual error (not just missing authentication)
if (err instanceof Error === false || // Not an actual error (e.g. redirect, custom response)
!err.isMissing || // Missing authentication (did not fail)
err.response.code !== 401) { // An actual error (not just missing authentication)

if (config.mode === 'try') {
request.session = session;
request.log(['auth', 'unauthenticated', 'try']);
request.log(['auth', 'unauthenticated', 'try'], err);
return next();
}

Expand All @@ -135,9 +147,8 @@ internals.Auth.prototype.authenticate = function (request, next) {

// Try next strategy

var response = err.toResponse();
if (response.headers['WWW-Authenticate']) {
authErrors.push(response.headers['WWW-Authenticate']);
if (err.response.headers['WWW-Authenticate']) {
authErrors.push(err.response.headers['WWW-Authenticate']);
}

return authenticate();
Expand All @@ -153,7 +164,7 @@ internals.Auth.prototype.authenticate = function (request, next) {
(!session.scope || session.scope.indexOf(config.scope) === -1)) {

request.log(['auth', 'error', 'scope'], { got: session.scope, need: config.scope });
return next(Err.forbidden('Insufficient scope (\'' + config.scope + '\' expected)'));
return next(Boom.forbidden('Insufficient scope (\'' + config.scope + '\' expected)'));
}

// Check TOS
Expand All @@ -163,39 +174,39 @@ internals.Auth.prototype.authenticate = function (request, next) {
(!session.ext || !session.ext.tos || session.ext.tos < tos)) {

request.log(['auth', 'error', 'tos'], { min: tos, received: session.ext && session.ext.tos });
return next(Err.forbidden('Insufficient TOS accepted'));
return next(Boom.forbidden('Insufficient TOS accepted'));
}

// Check entity

var entity = config.entity || 'any';

// Entity: any
// Entity: 'any'

if (entity === 'any') {
request.log(['auth']);
request.isAuthenticated = true;
return next();
}

// Entity: user
// Entity: 'user'

if (entity === 'user') {
if (!session.user) {
request.log(['auth', 'error'], 'User session required');
return next(Err.forbidden('Application session cannot be used on a user endpoint'));
return next(Boom.forbidden('Application session cannot be used on a user endpoint'));
}

request.log(['auth']);
request.isAuthenticated = true;
return next();
}

// Entity: app
// Entity: 'app'

if (session.user) {
request.log(['auth', 'error'], 'App session required');
return next(Err.forbidden('User session cannot be used on an application endpoint'));
return next(Boom.forbidden('User session cannot be used on an application endpoint'));
}

request.log(['auth']);
Expand Down
2 changes: 1 addition & 1 deletion lib/auth/oz.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

var Oz = require('oz');
var Utils = require('../utils');
var Err = require('../error');
var Boom = require('boom');


// Declare internals
Expand Down
6 changes: 3 additions & 3 deletions lib/batch.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Load modules

var Async = require('async');
var Err = require('./error');
var Boom = require('boom');


// Declare internals
Expand Down Expand Up @@ -42,7 +42,7 @@ exports.config = {
};

if (!request.payload.requests) {
return request.reply(Err.badRequest('Request missing requests array'));
return request.reply(Boom.badRequest('Request missing requests array'));
}

for (var i = 0, il = request.payload.requests.length; i < il; ++i) {
Expand All @@ -67,7 +67,7 @@ exports.config = {
internals.process(request, requests, resultsData, request.reply);
}
else {
request.reply(Err.badRequest(errorMessage));
request.reply(Boom.badRequest(errorMessage));
}
}
};
Expand Down
3 changes: 2 additions & 1 deletion lib/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ exports.server = {
state: {
cookies: {
parse: true, // Parse content of req.headers.cookie
failAction: 'error' // Action on bad cookie - 'error': return 400, 'log': log and continue, 'ignore': continue
failAction: 'error', // Action on bad cookie - 'error': return 400, 'log': log and continue, 'ignore': continue
clearInvalid: false // Automatically instruct the client to remove the invalid cookie
}
},

Expand Down
11 changes: 0 additions & 11 deletions lib/error.js

This file was deleted.

Loading

0 comments on commit 654f5d6

Please sign in to comment.