Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmlin committed Aug 10, 2012
1 parent 32e6e0a commit 7d5b7f5
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/

22 changes: 22 additions & 0 deletions errors/badrequesterror.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* `BadRequestError` error.
*
* @api public
*/
function BadRequestError(message) {
Error.call(this);
Error.captureStackTrace(this, arguments.callee);
this.name = 'BadRequestError';
this.message = message || null;
};

/**
* Inherit from `Error`.
*/
BadRequestError.prototype.__proto__ = Error.prototype;


/**
* Expose `BadRequestError`.
*/
module.exports = BadRequestError;
18 changes: 18 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Module dependencies.
*/
var Strategy = require('./strategy')
, BadRequestError = require('./errors/badrequesterror');


/**
* Framework version.
*/
require('pkginfo')(module, 'version');

/**
* Expose constructors.
*/
exports.Strategy = Strategy;

exports.BadRequestError = BadRequestError;
41 changes: 41 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "passport-mongoose",
"version": "0.0.1",
"description": "MongoDB username and password authentication strategy for Passport using Mongoose.",
"author": {
"name": "Mike M. Lin",
"email": "mike.m.lin@gmail.com",
"url": "http://www.seemikecode.com/"
},
"repository": {
"type": "git",
"url": "git://github.com/mmlin/passport-mongoose.git"
},
"bugs": {
"url": "http://github.com/mmlin/passport-mongoose/issues"
},
"main": "./index.js",
"dependencies": {
"pkginfo": "0.2.x",
"passport": "~0.1.1",
"mongoose": "3.x"
},
"engines": {
"node": ">= 0.4.0"
},
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/MIT"
}
],
"keywords": [
"passport",
"mongoose",
"mongodb",
"mongo",
"auth",
"authn",
"authentication"
]
}
149 changes: 149 additions & 0 deletions strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* Module dependencies.
*/
var passport = require('passport')
, util = require('util')
, BadRequestError = require('./errors/badrequesterror')
, mongoose = require('mongoose');

/**
* `Strategy` constructor.
*
* The local authentication strategy authenticates requests based on the
* credentials submitted through an HTML-based login form.
*
* Applications must supply a `verify` callback which accepts `username` and
* `password` credentials, and then calls the `done` callback supplying a
* `user`, which should be set to `false` if the credentials are not valid.
* If an exception occured, `err` should be set.
*
* Optionally, `options` can be used to change the fields in which the
* credentials are found.
*
* Options:
* - `usernameField` field name where the username is found, defaults to _username_
* - `passwordField` field name where the password is found, defaults to _password_
* - `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`)
*
* Examples:
*
* passport.use(new LocalStrategy(
* function(username, password, done) {
* User.findOne({ username: username, password: password }, function (err, user) {
* done(err, user);
* });
* }
* ));
*
* @param {Object} options
* @param {Function} verify
* @api public
*/
function Strategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = {};
}
options = options || {};
//if (!verify) throw new Error('local authentication strategy requires a verify function');

this._usernameField = options.usernameField || 'username';
this._passwordField = options.passwordField || 'password';
this._saltField = options.saltField || 'salt';
this._modelName = options.modelName || 'User';
this._db = options.connection || mongoose.createConnection('localhost', 'test');
try {
this._model = this._db.model(this._modelName);
} catch (e) {
var schemaConfig = {};
schemaConfig[this._usernameField] = String;
schemaConfig[this._passwordField] = String;
schemaConfig[this._saltField] = String;
this._model = this._db.model(this._modelName, new mongoose.Schema(schemaConfig));
}

passport.Strategy.call(this);
this.name = 'mongoose';
//this._verify = verify;
this._passReqToCallback = options.passReqToCallback;
}

/**
* Inherit from `passport.Strategy`.
*/
util.inherits(Strategy, passport.Strategy);

Strategy.prototype._verify = function(username, password, done) {

var usernameField = this._usernameField;
var passwordField = this._passwordField;
var query = {};

query[usernameField] = username;

this._model.findOne(query, function(err, user) {

// Something went terribly wrong.
if (err)
return done(null, false, { message: err.toString() })

// The user doesn't exist.
if (!user)
return done(null, false, { message: 'User not found' });

// The password isn't correct.
if (user[passwordField] != password)
return done(null, false, { message: 'Bad password' });

// Everything looks good.
return done(null, user);
});
};

/**
* Authenticate request based on the contents of a form submission.
*
* @param {Object} req
* @api protected
*/
Strategy.prototype.authenticate = function(req, options) {
options = options || {};
var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);

if (!username || !password) {
return this.fail(new BadRequestError(options.badRequestMessage || 'Missing credentials'));
}

var self = this;

function verified(err, user, info) {
if (err) { return self.error(err); }
if (!user) { return self.fail(info); }
self.success(user, info);
}

if (self._passReqToCallback) {
this._verify(req, username, password, verified);
} else {
this._verify(username, password, verified);
}

function lookup(obj, field) {
if (!obj) { return null; }
var chain = field.split(']').join('').split('[');
for (var i = 0, len = chain.length; i < len; i++) {
var prop = obj[chain[i]];
if (typeof(prop) === 'undefined') { return null; }
if (typeof(prop) !== 'object') { return prop; }
obj = prop;
}
return null;
}
};


/**
* Expose `Strategy`.
*/
module.exports = Strategy;

0 comments on commit 7d5b7f5

Please sign in to comment.