Auth
Simple authentication module for node.js applications
Installation
$ npm i --save knoxxnxt-auth
Usage
// default options shown herevar options = db: mail: templates: dir: __dirname + '/mail/templates' transport: from: 'Default From <default@example.com>' url: invite: accept: 'http://example.com/auth/invite/accept?token=<%- user.activationToken %>&email=<%- user.email %>' reject: 'http://example.com/auth/invite/reject?token=<%- user.activationToken %>&email=<%- user.email %>' activate: 'http://example.com/auth/activate?token=<%- user.activationToken %>&email=<%- user.email %>' reset: 'http://example.com/auth/reset?token=<%- user.resetToken %>&email=<%- user.email %>' subject: invite: 'You are invited' activate: 'Activate your account' reset: 'Reset Your account password' password: // bcrypt rounds rounds: 10 length: min: 8 max: 100 entropy: min: 24 // default user fields default: properties: {} roles: ; var auth = options;var methods = authmethods;
User Model
User Password
Password is validated using zxcvbn. It must obey the following rules:
- Greater than 8 characters
- Minimum 24 bits of entropy
- No dictionary words or common passwords
Constants
exportsTOKEN_LENGTH = 64; exportsRESET_TOKEN_EXPIRY = 1000 * 60 * 60 * 3; // 3 hours exportsEMPTY_PASSWORD_HASH = '$2a$10$FISKBraDkuYqs5WNoyJiWe4.kgdJC1hHF0toHCzN80ZNLIRDKUBFS'; // password -> '' exportsCURRENT_VERSION = version; exportsROLE = USER: 'user' USER_ADMIN: 'user admin';exportsROLES = 'user' 'user admin'; exportsSTATUS = INVITED: 'invited' REGISTERED: 'registered' ENABLED: 'enabled' DISABLED: 'disabled';exportsSTATUSES = 'registered' 'enabled' 'disabled'; exportsMESSAGE = ...;
API
version
Current library version
isSupported(semver)
For plugins or wrappers, returns if the supported auth versions are compatible with the existing version.
admin(options)
Creates an admin console to call methods. options
are passed straight to the repl.start
function.
Additional options include:
sock
: UNIX socket to bind toport
: Port to bind tohost
: Host to bind to
Either sock
or port
must be provided.
auth;
Client terminal
$ nc localhost 9091 auth > auth.methods.allundefinedauth > [{"_id":0,"email":"test@jksdua.asia","roles":["user"],"status":"enabled","properties":{"name":{"first":"Test","last":"User"},"some":{"other":"property"},"__pass":"I like big hashes and I cannot lie"}}] auth > methods.get;undefinedauth > {"_id":0,"email":"test@jksdua.asia","roles":["user"],"status":"enabled","properties":{"name":{"first":"Test","last":"User"},"some":{"other":"property"},"__pass":"I like big hashes and I cannot lie"}}undefinedauth >
methods.get({ email })
Get a single user from the database.
var user = authmethods;
methods.all({ [query], [options] })
Get all the users in the database.
// no filter, no optionsvar allUsers = authmethodsall; var disabledUsers = authmethodsall query: status: 'disabled' ; var fiveDisabledUsers = authmethodsall query: status: 'disabled' options: limit: 5 ;
methods.insert({ email, pass, [roles], [properties] })
Low-level method for bypassing registration and invitation mechanisms.
try var user = authmethods; catche {}
methods.update(user)
Low-level method for updating user record directly.
Note: This completely replaces the user object in the database
try var user = authmethods; catche {}
methods.remove({ email })
Low-level method for removing a user from the database. This is a permanent operation.
try var user = authmethods; catche {}
methods.login({ email, pass })
Validates a user's credentials. If correct, returns the user record.
try var user = authmethods; catche {}
methods.register({ email, pass, [roles], [properties], [mailOptions] })
Registers a new user. An email is sent to activate the user account. Until the account is activated, the status of the user is marked as 'registered'. Once activated, the user status changes to 'enabled'.
try var user = authmethods; catche {}
methods.activate({ email, [token], [skipTokenVerification=false] })
Activates a user. The status of the user is changed from 'registered' to 'enabled'.
If skipTokenVerification
is passed, token is not validated.
try var user = authmethods; var user = authmethods; catche {}
methods.resendActivationEmail({ email, [mailOptions] })
Creates a new activation token and sends the activation email.
try var status = authmethods; catche {}
methods.invite({ email, [roles], [properties], [mailOptions] })
Invites a new user. The user status is marked as invited
. The user is sent an email with instructions on how to activate their account.
try var user = authmethods; catche {}
methods.resendInvitationEmail({ email, [mailOptions] })
Resends invitation email sent by invite()
.
try var user = authmethods; catche {}
methods.acceptInvite({ email, pass, [token], [skipTokenVerification=false] })
Accept an invitation. Changes user status from invited
to enabled
.
If skipTokenVerification
is passed, token is not validated.
try var user = authmethods; var user = authmethods; catche {}
methods.rejectInvite({ email, [token], [skipTokenVerification=false] })
Reject an invitation. Removes user record from the system - this is permanent.
If skipTokenVerification
is passed, token is not validated.
try var user = authmethods; var user = authmethods; catche {}
methods.getProperties({ email })
Get user properties
try var properties = authmethods; catche {}
methods.setProperties({ email, properties })
Set user properties. User properties are replaced as is so ensure all properties are sent when updating.
try authmethods; catche {}
methods.changePassword({ email, oldPass, newPass })
Change a user's password
try authmethods; catche {}
methods.resetRequest({ email, [mailOptions] })
User is requesting a password reset. An email is sent to the user with a reset link.
try authmethods; catche {}
methods.resetResponse({ email, token, [pass], [skipTokenVerification=false] })
User is requesting a password reset. An email is sent to the user with a reset link.
If skipTokenVerification
is passed, token is not validated.
try authmethods; catche {}
methods.disable({ email })
Mark a user as disabled
try authmethods; catche {}
methods.enable({ email })
Mark a user as enabled
try authmethods; catche {}
Datastore
Any backend databased can be used such as MongoDB, Postgres, MySQL etc. It must support the following method signatures. All methods must be generator functions.
By default, a memory database is used and a warning is printed to the console.
.find([args])
An arguments hash passed from application level code is passed straight to the function. This could be used for various querying options.
.findById(id)
The user id is passed. It expects the entire user model to be returned.
.findByEmail(email)
Fetch a user by email. It expects the entire user model to be returned.
.insert(user)
A user json object is sent. The user object contains nested properties that must be handled appropriately by the data store. It expects a boolean indicating if the user was successfully inserted into the database.
It is left to the data store to assign the user with an id. This must be set as _id
field on the user object
.bulkInsert(users)
An array of user json objects is sent. It expects a boolean indicating if the user was successfully inserted into the database.
.update(user)
The entire user object is passed to the data store. It expects a boolean indicating if the user was successfully inserted into the database.
.removeByEmail(email)
Remove a user from the database using their email address.
.reset()
Remove all the database records
Creating a datastore
See knoxxnxt-auth-mongodb for a sample implementaion.
Step 1
Create a new datastore that conforms to the above API.
Step 2
$ require knoxxnxt-auth --save-dev
Step 3
Run knoxxnxt-auth
tests with the correct environment variable pointing to the new file
Debugging
In case of issues, debug by setting the environment variable DEBUG="knoxxnxt-auth:*"
.
$ cd node_modules/knoxxnxt-auth$ DB_MODULE="$(pwd)/../../datastore.js" npm test