Created
August 11, 2017 17:59
-
-
Save wootwoot1234/d6ce91b7a83f5dcbcbe742bd449a94bf to your computer and use it in GitHub Desktop.
passport-local-mongoose upgrade strategy toubleshoot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// dependencies | |
var path = require('path'); | |
var express = require('express'); | |
var http = require('http'); | |
var mongoose = require('mongoose'); | |
var passport = require('passport'); | |
var LocalStrategy = require('passport-local').Strategy; | |
var bodyParser = require('body-parser'); | |
var MongoStore = require('connect-mongo')(express); | |
var timeout = express.timeout; | |
// main config | |
var app = express(); | |
app.set('port', process.env.PORT || 1337); | |
app.set('views', __dirname + '/views'); | |
//app.set('view engine', 'jade'); | |
app.engine('html', require('ejs').renderFile); | |
app.set('view engine', 'html'); | |
//app.set('view options', { layout: false }); | |
app.use(bodyParser.json()); // for parsing application/json | |
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded | |
app.use(express.logger()); | |
//app.use(express.bodyParser()); | |
app.use(express.methodOverride()); | |
app.use(express.cookieParser('your secret here')); | |
//app.use(express.session()); | |
app.use(express.session({ | |
secret: '1234123412341234', | |
maxAge: new Date(Date.now() + 3600000), | |
store: new MongoStore({mongooseConnection:mongoose.connection}) | |
})); | |
app.use(passport.initialize()); | |
app.use(passport.session()); | |
app.use(app.router); | |
app.use(express.static(path.join(__dirname, 'public'))); | |
app.configure('development', function(){ | |
app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); | |
}); | |
app.configure('production', function(){ | |
app.use(express.errorHandler()); | |
}); | |
// passport config | |
var User = require('./models/user'); | |
passport.use(new LocalStrategy(User.authenticate())); | |
passport.serializeUser(User.serializeUser()); | |
passport.deserializeUser(User.deserializeUser()); | |
// mongoose | |
var uristring = process.env.MONGODB_URI || 'mongodb://localhost/passport_local_mongoose'; | |
mongoose.connect(uristring); | |
// routes | |
require('./routes')(app); | |
// catch 404 and forward to error handler | |
app.use(function(req, res, next) { | |
var err = new Error('Not Found'); | |
err.status = 404; | |
next(err); | |
}); | |
// error handlers | |
// development error handler | |
// will print stacktrace | |
if (process.env.NODE_ENV != "production") { | |
app.use(function(err, req, res, next) { | |
res.status(err.status || 500); | |
res.render('error', { | |
message: err.message, | |
error: err | |
}); | |
}); | |
} | |
// production error handler | |
// no stacktraces leaked to user | |
app.use(function(err, req, res, next) { | |
res.status(err.status || 500); | |
res.render('error', { | |
message: err.message, | |
error: {} | |
}); | |
}); | |
app.listen(app.get('port'), function(){ | |
console.log(("Express server listening on port " + app.get('port'))); | |
if(process.env.NODE_ENV != "production") { | |
console.log("NOT RUNNING IN PRODUCTION MODE, APP WILL NOT SEND MESSAGES OR SET PRICES"); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const passportLocalMongoose = require('passport-local-mongoose') | |
const mongoose = require('mongoose') | |
/** | |
* Wrap passport-local-mongoose plugin to allow the update of | |
* the passwords digestAlgorithm, from old `sha1` to a more secure `sha512` | |
*/ | |
module.exports = function authMongoose (schema, options) { | |
const digestAlgorithm = 'sha512' | |
schema.plugin(passportLocalMongoose, { | |
usernameField: 'email', | |
errorMessages: { | |
AttemptTooSoonError: 'signin.errors.attempt-too-soon', | |
TooManyAttemptsError: 'signin.errors.too-many-attempts', | |
IncorrectPasswordError: 'signin.errors.incorrect-password', | |
IncorrectUsernameError: 'signin.errors.incorrect-username' | |
}, | |
selectFields: '+digestAlgorithm', | |
digestAlgorithm: digestAlgorithm, | |
limitAttempts: true, | |
maxAttempts: 50 | |
}) | |
schema.add({ | |
digestAlgorithm: { type: String, select: false } | |
}) | |
/** | |
* Override .setPassword to also save `digestAlgorithm` key | |
*/ | |
const originalSetPassword = schema.methods.setPassword | |
schema.methods.setPassword = function setPassword (pass, cb) { | |
return originalSetPassword.call(this, pass, (err) => { | |
if (err) return cb(err) | |
this.set('digestAlgorithm', digestAlgorithm) | |
cb(null, this) | |
}) | |
} | |
/** | |
* Override .authenticate to migrate the password when needed | |
*/ | |
const originalAuthenticate = schema.methods.authenticate | |
schema.methods.authenticate = function verifyUserDigestAlgorithm (pass, cb) { | |
console.log("authenticate"); | |
const user = this | |
const userDigestAlgorithm = user.get('digestAlgorithm') | |
if (userDigestAlgorithm === digestAlgorithm) { | |
return originalAuthenticate.call(user, pass, cb) | |
} | |
// Migrate old sha1 password to a new one with sha256 | |
if (!userDigestAlgorithm) { | |
const sha1User = new Sha1User({ | |
hash: user.get('hash'), | |
salt: user.get('salt') | |
}) | |
return sha1User.authenticate(pass, (err, passed, msg) => { | |
if (err) return cb(err) | |
if (passed === false) return cb(null, passed, msg) | |
return user.setPassword(pass, (err, user) => { | |
if (err) return cb(err) | |
user.save((err, user) => { | |
if (err) return cb(err) | |
originalAuthenticate.call(user, pass, cb) | |
}) | |
}) | |
}) | |
} | |
return cb(null, false, { | |
message: 'signin.errors.must-reset-password' | |
}) | |
} | |
} | |
/** | |
* Use a temporary dummy model for old passwords verification | |
*/ | |
const Sha1UserSchema = new mongoose.Schema() | |
Sha1UserSchema.plugin(passportLocalMongoose, { | |
errorMessages: { | |
AttemptTooSoonError: 'signin.errors.attempt-too-soon', | |
TooManyAttemptsError: 'signin.errors.too-many-attempts', | |
IncorrectPasswordError: 'signin.errors.incorrect-password', | |
IncorrectUsernameError: 'signin.errors.incorrect-username' | |
}, | |
digestAlgorithm: 'sha1', | |
limitAttempts: false | |
}) | |
const Sha1User = mongoose.model('Sha1User', Sha1UserSchema) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var passport = require('passport'); | |
var User = require('./models/user'); | |
var Account = require('./models/user.account'); | |
var Listing = require('./models/user.account.listing'); | |
var Message = require('./models/user.account.listing.message'); | |
var MessageRule = require('./models/user.account.listing.messageRule'); | |
var Price = require('./models/user.account.listing.price'); | |
var PriceRule = require('./models/user.account.listing.priceRule'); | |
var Reservation = require('./models/user.account.reservation'); | |
var querystring = require('querystring'); | |
var https = require('https'); | |
var moment = require('moment-timezone'); | |
var mailer = require('./email/email'); | |
var nodemailer = require('nodemailer'); | |
// Generic error handler used by all endpoints. | |
function handleError(res, reason, message, code) { | |
console.log("Error: ", reason); | |
console.log(message); | |
return res.status(code || 500).json({"error": message}); | |
} | |
module.exports = function(app) { | |
app.get('/', function(req, res) { | |
if(!req.user) { | |
res.render('index'); | |
} else { | |
res.redirect('/admin/#/'); | |
} | |
}); | |
app.get('/admin', function(req, res) { | |
if(!req.user) { | |
res.redirect('/#!/login'); | |
} else { | |
res.render('admin', { user : req.user }); | |
} | |
}); | |
app.post('/register', function(req, res) { | |
console.log("/register"); | |
User.register(new User({ username : req.body.username }), req.body.password, function(error, doc) { | |
if (error) { | |
return handleError(res, "That email already exists. Try logging in instead.", {error_code: 400, error_message: "That email already exists. Try logging in instead."}, 400); | |
} else { | |
passport.authenticate('local')(req, res, function () { | |
var to = req.user.username; | |
var subject = "Welcome to Superhost Tools"; | |
var text = "Thanks for joining Superhost Tools. If you haven't already, the next step is to login and link your Airbnb account and begin automatically sending messages to your guests." | |
sendEmail(to, subject, text); | |
return res.redirect('/admin/#/'); | |
}); | |
} | |
}); | |
}); | |
app.post('/login', function(req, res, next) { | |
console.log("/login"); | |
/* look at the 2nd parameter to the below call */ | |
passport.authenticate('local', function(error, user, info) { | |
console.log("error", error); | |
console.log("user", user); | |
console.log("info", info); | |
if (error) { | |
return next(error); | |
} | |
if (!user) { | |
return handleError(res, "That email and password combination is invalid. Try something else.", {error_code: 400, error_message: "That email and password combination is invalid. Try something else."}, 400); | |
} | |
req.logIn(user, function(error) { | |
if (error) { | |
return next(error); | |
} | |
return res.redirect('/admin/#/'); | |
}); | |
})(req, res, next); | |
}); | |
app.get('/logout', function(req, res) { | |
console.log("/logout"); | |
req.logout(); | |
res.redirect('/'); | |
}); | |
//... | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var mongoose = require('mongoose'), | |
Schema = mongoose.Schema, | |
passportLocalMongoose = require('passport-local-mongoose'), | |
//authMongoose = require('./mongoose'), | |
bcrypt = require('bcrypt-nodejs'); | |
var User = new Schema({ | |
username: String, | |
password: String, | |
}, | |
{timestamps: true}); | |
//User.plugin(authMongoose); | |
// // OLD | |
// npm install passport@0.1.17 --save | |
// npm install passport-local@0.1.6 --save | |
// npm install passport-local-mongoose@0.2.5 --save | |
// // NEW | |
// npm install passport@0.3.2 --save | |
// npm install passport-local@1.0.0 --save | |
// npm install passport-local-mongoose@4.1.0 --save | |
User.plugin(passportLocalMongoose); | |
module.exports = mongoose.model('User', User); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment