Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
passport-local-mongoose-argon
Advanced tools
A fork of the Passport-Local Mongoose package, rebuilt around Argon2 for extra security
Passport Local Mongoose Argon is a Mongoose plugin, a fork of the original Passport-Local-Mongoose that simplifies building username and password logins with Passport.
This fork uses Argon2 in this Node.js binding for extra security when hashing and storing passwords.
This is a work in progress!
This module is very heavily based on the work of Christoph Walcher for the original Passport Local Mongoose plugin and Ranieri Althoff for the Argon2 Node binding. All credit goes to them and their collaborators.
The Argon2 implementation also requires a global instalation of node-gyp
and GCC
.
The easiest way to do this on Windows is to npm install --global --production windows-build-tools
and then npm install -g node-gyp
;
On MacOS and Unix you'll need to follow these instructions.
AFTER you've installed the dependencies listed above you can go ahead and simply npm install --save passport-local-mongoose-argon
and then require it in your app.
This package was tested against projects built with passport-local-mongoose @ 4.x.x. It should work as a drop-in replacement in almost any project on a recent version.
It WILL NOT work when updating from older versions due to breaking changes.
It WILL NOT work with hashes from a non-Argon2 algorithm. It is NOT backward compatible with the PBKDF2 versions.
This SHOULD NOT be used in production until further testing. If you find bugs, especially security-related, raise an issue on this repo.
Michael Herman gives a comprehensible walk through for setting up mongoose, passport, passport-local and passport-local-mongoose for user authentication in his blog post User Authentication With Passport.js
For more details on the original passport-local-mongoose you can check out its repo. Most of its excellent functionality has been preserved and some of the examples are reproduced below.
First you need to plugin Passport Local Mongoose into your User schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongooseArgon = require('passport-local-mongoose-argon');
const User = new Schema({});
User.plugin(passportLocalMongooseArgon);
module.exports = mongoose.model('User', User);
You're still free to define your User how you like. Passport Local Mongoose Argon will add a username and hash field to store the username and the hashed password.
Additionally Passport Local Mongoose Argon adds some methods to your Schema. See the API Documentation section for more details.
You should configure Passport/Passport-Local as described in the Passport Guide.
Passport Local Mongoose Argon supports this setup by implementing a LocalStrategy
and serializeUser/deserializeUser functions.
To setup Passport Local Mongoose Argon use this code
const User = require('./models/user');
//USE "createStrategy" INSTEAD OF "authenticate" in older versions of the original
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
When plugging in Passport Local Mongoose Argon additional options can be provided to configure the hashing algorithm as well as the plugin itself.
User.plugin(passportLocalMongoose, options);
Argon options map directly to the Argon2 hashing options, and can even be changed in production. Older Argon2 hashes will still work. However, the defaults listed below should be good enough for all cases.
Argon Options
Argon Defaults are set in accordance with the Argon2 RFC and are in theory safe for every use case. You don't need to change them unless you're going for something very specific. If you find hashing takes too long even with timeCost set to 1, gradually lower memoryCost and parallelism.
Argon Defaults
On top of the Argon options you also have a large number of configuration options kept from the original plugin, to enhance your db models and authentication security.
Plugin Options
true
. Default: function(model, queryParameters) { return model.findOne(queryParameters); }
. See the examples section for a use case.The Argon2 Node binding generates a 128-bit salt using crypto.randomBytes for each password in compliance with the RFC. The salt, and the hashing options get stored directly in the hash. This lets you change current hashing options as time goes on while still being able to verify previously stored hashes with different options.
If you want even more security you can add your own pepper manually to the user's password before calling the register / change password methods.
Override default error messages by setting options.errorMessages.
For a complete example implementing a registration, login and logout see the login example.
asynchronous method to set a user's password hash
asynchronous method to change a user's password hash. If oldPassword does
not match the user's old password an IncorrectPasswordError
is passed to cb.
asynchronous method to authenticate a user instance
asynchronous method to reset a user's number of failed password attempts (only defined if options.limitAttempts
is true)
callback arguments
AuthenticationError
describing the reason the password failed, else undefined.Using setPassword()
will only update the document's password fields, but will not save the document.
To commit the changed document, remember to use Mongoose's document.save()
after using setPassword()
.
Error Handling
IncorrectPasswordError
: specifies the error message returned when the password is incorrect. Defaults to 'Incorrect password'.IncorrectUsernameError
: specifies the error message returned when the username is incorrect. Defaults to 'Incorrect username'.MissingUsernameError
: specifies the error message returned when the username has not been set during registration. Defaults to 'Field %s is not set'.MissingPasswordError
: specifies the error message returned when the password has not been set during registration. Defaults to 'Password argument not set!'.UserExistsError
: specifies the error message returned when the user already exists during registration. Defaults to 'User already exists with name %s'.AttemptTooSoonError
: Occurs if the option limitAttempts
is set to true and a login attept occures while the user is still penalized.TooManyAttemptsError
: Returned when the user's account is locked due to too many failed login attempts.All those errors inherit from AuthenticationError
, if you need a more general error class for checking.
Static methods are exposed on the model constructor. For example to use createStrategy function use
const User = require('./models/user');
User.createStrategy();
LocalStrategy
instance that can be used in passport.First we define a schema with an additional field active
of type Boolean.
var UserSchema = new Schema({
active: Boolean
});
When plugging in Passport Local Mongoose we set usernameUnique
to avoid creating a unique mongodb index on field username
. To avoid
non active users to be queried by mongodb we can specify the option findByUsername
that allows us to restrict a query. In our case
we want to restrict the query to only query users with field active
set to true
. The findByUsername
MUST return a Mongoose query.
UserSchema.plugin(passportLocalMongoose, {
// Needed to set usernameUnique to true to avoid a mongodb index on the username column!
usernameUnique: false,
findByUsername: function(model, queryParameters) {
// Add additional query parameter - AND condition - active: true
queryParameters.active = true;
return model.findOne(queryParameters);
}
});
To test the implementation we can simply create (register) a user with field active
set to false
and try to authenticate this user
in a second step:
var User = mongoose.model('Users', UserSchema);
User.register({username:'username', active: false}, 'password', function(err, user) {
if (err) { ... }
var authenticate = User.authenticate();
authenticate('username', 'password', function(err, result) {
if (err) { ... }
// Value 'result' is set to false. The user could not be authenticated since the user is not active
});
});
Passport Local Mongoose Argon is licensed under the MIT license.
FAQs
A fork of the Passport-Local Mongoose package, rebuilt around Argon2 for extra security
We found that passport-local-mongoose-argon demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.