• Stars
    star
    439
  • Rank 99,247 (Top 2 %)
  • Language
    JavaScript
  • Created almost 12 years ago
  • Updated about 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Authentication solution for Express

Lockit

Build Status NPM version Dependency Status

Lockit is an authentication solution for Express. Check out the demo.

It consists of multiple single purpose modules:

Table of contents

Quickstart

  1. Create new Express app.

express

  1. Install Lockit and sessions via npm.

npm install && npm install lockit cookie-session --save

  1. Use lockit and cookie-session in your Express app.js.
var cookieSession = require('cookie-session');
var Lockit = require('lockit');
var lockit = new Lockit();

...
app.use(cookieSession({
  secret: 'my super secret String'
}));
app.use(lockit.router);
  1. Go to localhost:3000/signup

By default Lockit uses an in-memory SQLite database. So you don't have to set up any db. Lockit will just work. Check out the default example.

For production use a persistent data store!

Full installation

  1. Install and require

npm install lockit --save

var config = require('./config.js');
var Lockit = require('lockit');

var app = express();

// express middleware
// ...
// sessions are required
app.use(cookieParser());
app.use(cookieSession({
  secret: 'your secret here'
}));

var lockit = new Lockit(config);

app.use(lockit.router);

// you now have all the routes like /login, /signup, etc.
// and you can listen on events. For example 'signup'
lockit.on('signup', function(user, res) {
  console.log('a new user signed up');
  res.send('Welcome!');   // set signup.handleResponse to 'false' for this to work
});
  1. Add styles

Views are built with bootstrap. You can use your own ones though! Use Bootstrap CDN and add the following line to your layout.jade

link(rel='stylesheet', href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css')
  1. Install database adapter

npm install lockit-[DB]-adapter where [DB] can be

Database Command
CouchDB npm install lockit-couchdb-adapter
MongoDB npm install lockit-mongodb-adapter
SQL (PostgreSQL, MySQL, MariaDB or SQLite) npm install lockit-sql-adapter

If you use a SQL database you also have to install the connector.

npm install pg       # for postgres
npm install mysql    # for mysql
npm install sqlite3  # for sqlite
npm install mariasql # for mariasql

Configuration

You need a config.js somewhere in your app.

Database connection

Add the database connection string to your config.js.

// database settings for CouchDB
exports.db = 'http://127.0.0.1:5984/';        // connection string for database

// or if you want to use MongoDB
// exports.db = {
//   url: 'mongodb://127.0.0.1/',
//   name: 'test',
//   collection: 'users'  // collection name for MongoDB
// };

// PostgreSQL
// exports.db = {
//   url: 'postgres://127.0.0.1:5432/',
//   name: 'users',
//   collection: 'my_user_table'  // table name for SQL databases
// };

// MySQL
// exports.db = {
//   url: 'mysql://127.0.0.1:3306/',
//   name: 'users',
//   collection: 'my_user_table'
// };

// SQLite
// exports.db = {
//   url: 'sqlite://',
//   name: ':memory:',
//   collection: 'my_user_table'
// };

Sending emails

By default the email service is stubbed and no emails are sent. That means that you won't receive any signup and password reset tokens. You have to look them up in your database and call the routes manually (e.g. /signup/:token). To send emails you need an email server and you have to change the settings in your config.js:

  • emailType - usually nodemailer-smtp-transport
  • emailSettings - see nodemailer for more information

With mailgun you can send up to 10,000 emails per month for free.

exports.emailType = 'nodemailer-smtp-transport';
exports.emailSettings = {
  service: 'Mailgun',
  auth: {
    user: '[email protected]',
    pass: 'secret-password'
  }
};

Custom views

Lockit comes with built-in views which are based on Bootstrap. If you want to use your own custom views you can. It is dead simple.

Put them into your views folder, for example views/lockit/myLogin.jade. Then edit your config.js and set the path to your custom view.

exports.login = {
  route: '/login',
  logoutRoute: '/logout',
  views: {
    login: 'lockit/myLogin.jade',
    loggedOut: 'lockit/myLogoutSuccess.jade'
  }
};

The only thing you have to keep in mind is the structure. The login.views.login view, for example, needs a form element with two input fields. The method has to be POST and action should point to your login.route. The input fields have to have the names login and password. If something went wrong during the login process you'll get an error variable that you can use in your template.

Here is a minimalistic example for an alternative myLogin.jade.

extend /layout

block content
  h1 Login
  form(action="/login", method="POST")
    div
      label(for="login") Email or Username
      input(type="text", id="login", name="login", placeholder="Your email or username")
    div
      label(for="password") Password
      input(type="password", id="password", name="password", placeholder="Your password")
    if error
      p #{error}
    input(type="submit", value="Login")

For more information about each view see the views folder inside the different repositories. Make sure your view extends /layout which is different to your normal views. They extend layout without the slash. This is required to find the view.

Events

Lockit emits the most important events for user authentication. Those are

  • signup
  • login
  • logout
  • delete

You can use these events to intercept requests and implement some custom logic, like getting the gravatar before sending a response to the client.

signup

A new user signed up. The callback function has two arguments.

  • user is an object and contains information about the new user, like user.name or user.email.
  • res is the standard Express.js res object with methods like res.render and res.send. If you've set signup.handleResponse to false Lockit will not handle the response for you. You therefore have to send the response back to the client manually or otherwise it will wait forever.
lockit.on('signup', function(user, res) {
  // ...
});
login

A user logged in. Callback function this time has three arguments.

  • user is again the JSON object containing info about that particular user.
  • res is the normal Express.js response object with all properties and methods.
  • target is the redirect target route after a successful login, i.e. /settings
lockit.on('login', function(user, res, target) {
  // ...
});
forgot::sent

A user forgot the password and an email has been sent. Callback function has two arguments.

  • user is again the JSON object containing info about that particular user.
  • res is the normal Express.js response object with all properties and methods.
lockit.on('forgot::sent', function(user, res) {
  // ...
});
forgot::success

User has created a new password. Callback function has two arguments.

  • user is again the JSON object containing info about that particular user.
  • res is the normal Express.js response object with all properties and methods.
lockit.on('forgot::success', function(user, res) {
  // ...
});
logout

A user logged out. Same as above without the target string.

lockit.on('logout', function(user, res) {
  // ...
});
delete

A user deleted an account. Same callback as above.

lockit.on('delete', function(user, res) {
  // ...
});

REST API

In a single page application (SPA) all routing and template rendering is done on the client. Before version 0.5.0 Lockit caught relevant routes, like /login or /signup, and did the entire rendering on the server.

Starting with version 0.5.0 you're able to use Lockit as a REST API and communicate via JSON. All you have to do is set exports.rest in your config.js.

exports.rest = {
  // set starting page for single page app
  index: 'public/index.html',

  // use view engine (render()) or send static file (sendfile())
  useViewEngine: false
}

With REST enabled all default routes get a /rest prefix so you can catch /login on the client. To allow for true page refreshes (i.e. user is at /login and refreshes the page) all routes on the server, like /login and /signup, send the rest.index view to the client. From there your SPA has to take over.

Here is a short example how the process works.

  1. User sends GET request for /login
  2. Server has a route handler for this request and sends index.html back
  3. Client router takes over and renders /login page
  4. User enters credentials and submits the form
  5. Client controller catches submit and sends POST via AJAX request to /rest/login
  6. Server handles POST request and validates user credentials
  7. Server sends status code 200 or some JSON with error message
  8. Client reacts to JSON from server and redirects on success or shows error

I've built a simple example using AngularJS on the client side.

Sample config

If you want to go crazy and customize all the things you can:

// name for subject and email content
exports.appname = 'lockit - Test App';

// url for proper link generation
exports.url = 'http://localhost:3000';

// email settings (same as nodemailer)
exports.emailType = 'nodemailer-stub-transport';
exports.emailSettings = {
  service: 'none',
  auth: {
    user: 'none',
    pass: 'none'
  }
};

// whenever a library uses request under the hood (like nano in lockit-couchdb-adapter)
// the following values will be used
exports.request_defaults = {
  // proxy: 'http://someproxy'
};

// email template from npm
exports.emailTemplate = 'lockit-template-blank';

// render views or json for single page apps
exports.rest = false;

// or if you want to use rest
// exports.rest = {
//
//   // set starting page for single page app
//   index: 'public/index.html',
//
//   // use view engine (render()) or send static file (sendfile())
//   useViewEngine: false
//
// }

// signup settings
exports.signup = {
  route: '/signup',
  tokenExpiration: '1 day',
  views: {
    signup: '',         // input fields 'name', 'email' and 'password' | local variable 'error' | POST /'signup.route'
    linkExpired: '',    // message link has expired | input field 'email' | POST /'signup.route'/resend-verification
    verified: '',       // message email is now verified and maybe link to /'login.route'
    signedUp: '',       // message email has been sent => check your inbox
    resend: ''          // input field 'email' | local variable 'error' | POST /'signup.route'/resend-verification
  },
  handleResponse: true  // let lockit handle the response after signup success
};

// login settings
exports.login = {
  route: '/login',
  logoutRoute: '/logout',
  views: {
    login: '',          // input fields 'login' and 'password' | POST /'login.route' | local variable 'error'
    loggedOut: ''       // message that user logged out
  },
  handleResponse: true  // let lockit handle the response after login/logout success
};

// forgot password settings
exports.forgotPassword = {
  route: '/forgot-password',
  tokenExpiration: '1 day',
  views: {
    forgotPassword: '', // input field 'email' | POST /'forgotPassword.route' | local variable 'error'
    newPassword: '',    // input field 'password' | POST /'forgotPassword.route'/#{token} | local variable 'error'
    changedPassword: '',// message that password has been changed successfully
    linkExpired: '',    // message that link has expired and maybe link to /'forgotPassword.route'
    sentEmail: ''       // message that email with token has been sent
  }
};

// delete account settings
exports.deleteAccount = {
  route: '/delete-account',
  views: {
    remove: '',         // input fields 'name', 'phrase', 'password' | POST /'deleteAccount.route' | local variable 'error'
    removed: ''         // message that account has been deleted
  },
  handleResponse: true  // let lockit handle the response after delete account success
};

// lock account
// show warning after three failed login attempts
exports.failedLoginsWarning = 3;
// lock account after five failed login attempts
exports.failedLoginAttempts = 5;
// lock account for 20 minutes
exports.accountLockedTime = '20 minutes';

// public email address of your app
exports.emailFrom = '[email protected]';

// email signup template
exports.emailSignup = {
  subject: 'Welcome to <%- appname %>',
  text: [
    '<h2>Hello <%- username %></h2>',
    'Welcome to <%- appname %>.',
    '<p><%- link %> to complete your registration.</p>'
  ].join(''),
  linkText: 'Click here'
};

// email already taken template
exports.emailSignupTaken = {
  subject: 'Email already registered',
  text: [
    '<h2>Hello <%- username %></h2>',
    'you or someone else tried to sign up for <%- appname %>.',
    '<p>Your email is already registered and you cannot sign up twice.',
    ' If you haven\'t tried to sign up, you can safely ignore this email. Everything is fine!</p>',
    '<p>The <%- appname %> Team</p>'
  ].join('')
};

// resend signup template
exports.emailResendVerification = {
  subject: 'Complete your registration',
  text: [
    '<h2>Hello <%- username %></h2>',
    'here is the link again. <%- link %> to complete your registration.',
    '<p>The <%- appname %> Team</p>'
  ].join(''),
  linkText: 'Click here'
};

// forgot password template
exports.emailForgotPassword = {
  subject: 'Reset your password',
  text: [
    '<h2>Hey <%- username %></h2>',
    '<%- link %> to reset your password.',
    '<p>The <%- appname %> Team</p>'
  ].join(''),
  linkText: 'Click here'
};

Features

  • responsive html email template: lockit-template-blank
  • support for wide range of databases out of the box
  • email address verification
  • account locking after too many failed login attempts
  • verification link expiration
  • failed login tracking
  • /login redirection when user is unauthorized
  • password hash generation with bcrypt
  • unit tests for all modules
  • serves proper HTML views or only JSON
  • events for most important happenings login, logout, signup and delete
  • implementation of lots of best pratices

Routes included

From lockit-signup

  • GET /signup
  • POST /signup
  • GET /signup/:token
  • GET /signup/resend-verification
  • POST /signup/resend-verification

From lockit-login

  • GET /login
  • POST /login
  • POST /login/two-factor
  • GET /logout

From lockit-forgot-password

  • GET /forgot-password
  • POST /forgot-password
  • GET /forgot-password/:token
  • POST /forgot-password/:token

From lockit-delete-account

  • GET /delete-account
  • POST /delete-account

Test

grunt

License

MIT

More Repositories

1

json2csv

Convert json to csv with column titles
JavaScript
2,713
star
2

swift-linechart

Line Chart library for iOS written in Swift
Swift
602
star
3

nodejs-pdf-docs

Node.js Manual & Documentation (.pdf, .mobi, .epub)
TeX
497
star
4

sf-city-lots-json

really big json file representing san francisco's subdivision parcels
145
star
5

flexbox-grid

Grid system using CSS flex properties
CSS
128
star
6

express-upload-progress

File uploading with Express.js and progress bar
JavaScript
119
star
7

nghellostyle

AngularJS seed for Google Closure Compiler
JavaScript
117
star
8

swift-timeago

Relative time / time ago for Swift
Swift
56
star
9

json2csv-stream

Transform stream from json to csv
JavaScript
52
star
10

node-require-s--best-practices

Some best practices / conventions when using Node's `require()`
JavaScript
51
star
11

couchdb

CouchDB client in Go
Go
44
star
12

tu-darmstadt-latex-thesis

LaTeX template for any thesis at the TU Darmstadt
41
star
13

swift-couchbaselite-cheatsheet

Swift CouchbaseLite Cheat Sheet
Objective-C
39
star
14

keycloak

Go library for accessing the Keycloak API
Go
34
star
15

swift-piechart

Piechart library for iOS written in Swift
Swift
32
star
16

ng-form-shake

CSS3 form shake effect with AngularJS
CSS
27
star
17

couchdb-cookie-auth

CouchDB cookie authentication example with PouchDB
JavaScript
25
star
18

ng-signup-form

GitHub like signup form with AngularJS
JavaScript
24
star
19

email

Easily send HTML emails with Golang
Go
19
star
20

mozilla-persona-express-couchdb

Mozilla Persona example app with Express and CouchDB
JavaScript
18
star
21

csrf-express-angular

CSRF protection example app built with Express and Angular
JavaScript
18
star
22

gartner-wcm-d3

Interactive summary of Gartner's Magic Quadrant for Web Content Management with d3.js
JavaScript
17
star
23

swift-couchdb

CouchDB client for Swift
Swift
15
star
24

couch-pwd

CouchDB like salt and password generation with PBKDF2
JavaScript
12
star
25

follow

Go client for CouchDB _changes API
Go
12
star
26

primus-express-session

Share a user session between Express and Primus
JavaScript
11
star
27

d3-hill-chart

d3 hill chart
JavaScript
10
star
28

uid

URL safe string generator for Go / Golang
Go
10
star
29

pouchdb-vs-couchbase

cordova app to compare performance of pouchdb and couchbase lite phonegap
Objective-C
9
star
30

simple-recaptcha

simple implementation of google's reCAPTCHA
JavaScript
9
star
31

codedeploy-golang

AWS CodeDeploy Golang app
Shell
9
star
32

lockit-signup

sign up routes for lockit middleware
JavaScript
9
star
33

lockit-login

login and logout routes for lockit
JavaScript
9
star
34

lockit-couchdb-adapter

CouchDB adapter for lockit
JavaScript
8
star
35

lockit-sendmail

Email utilities for lockit
JavaScript
7
star
36

lockit-mongodb-adapter

MongoDB adapter for lockit
JavaScript
7
star
37

bannerify

Add banner to your browserify bundle
JavaScript
7
star
38

memorystore

memory session store for gorilla/sessions
Go
6
star
39

dok

JavaScript documentation generator based on JSDoc
JavaScript
6
star
40

papertrail

Golang client for papertrail
Go
6
star
41

lockit-utilities

Utilities module for lockit
JavaScript
6
star
42

old-zemirco.github.io

My private blog powered by Octopress
JavaScript
5
star
43

zemirco.github.io

http://mircozeiss.com/ powered by Jekyll
CSS
4
star
44

lockit-delete-account

delete account middleware for lockit
JavaScript
4
star
45

dcp

Discovery and Basic Configuration Protocol (DCP)
Go
4
star
46

enterjs

react d3 showcase
JavaScript
3
star
47

grunt-jade-preprocess

Grunt deployment process with Jade
JavaScript
3
star
48

seriesci-demo

Series CI demo
Shell
3
star
49

lockit-forgot-password

forgot password middleware for lockit
JavaScript
3
star
50

panel.jsx

React Panel component
JavaScript
2
star
51

swift-http

Swift HTTP
Swift
2
star
52

swift-scale

d3.js like scale in Swift
Swift
2
star
53

ng-scoreboard-clock

An angular.js directive to display the current time as seen on sports scoreboards.
JavaScript
2
star
54

couchdb-browser-auth

CouchDB user authentication from the browser
JavaScript
2
star
55

lockit-template-blank

blank email template for lockit-sendmail
JavaScript
2
star
56

codedeploy-couchdb

CodeDeploy CouchDB
Shell
2
star
57

docker

Dockerfiles
Go
1
star
58

branch

branch demo
1
star
59

enterjs2020

enterJS 2020
TypeScript
1
star
60

couchdb-ssl

CouchDB with nginx
Nginx
1
star
61

jira

JIRA REST API client in Go
Go
1
star
62

protoc-gen-twirp-es

JavaScript code generator for Twirp RPC
Go
1
star
63

sankey

D3 sankey
JavaScript
1
star
64

zemirq

nng test
Go
1
star
65

dotfiles

dotfiles
Vim Script
1
star
66

lockit-profile

sample '/profile' route for Lockit
JavaScript
1
star
67

swift-querystring

Swift library for encoding classes into URL query parameters
Swift
1
star
68

table.jsx

React Table component
JavaScript
1
star
69

lockit-koa-login

Lockit login module for Koa
JavaScript
1
star
70

string2stream

Converts a string into a stream by emitting one character after the other
JavaScript
1
star
71

enterjs2019

enterJS 2019 demo app
JavaScript
1
star
72

lockit-sql-adapter

SQL adapter for lockit
JavaScript
1
star