{"id":13510357,"url":"https://github.com/zemirco/lockit","last_synced_at":"2025-10-06T13:44:32.569Z","repository":{"id":5862253,"uuid":"7079272","full_name":"zemirco/lockit","owner":"zemirco","description":"Authentication solution for Express","archived":false,"fork":false,"pushed_at":"2015-11-02T15:09:36.000Z","size":1200,"stargazers_count":440,"open_issues_count":14,"forks_count":50,"subscribers_count":24,"default_branch":"master","last_synced_at":"2024-05-13T20:05:38.845Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zemirco.png","metadata":{"files":{"readme":"README.md","changelog":"History.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-12-09T13:59:55.000Z","updated_at":"2024-04-26T13:28:36.000Z","dependencies_parsed_at":"2022-08-31T15:43:03.879Z","dependency_job_id":null,"html_url":"https://github.com/zemirco/lockit","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zemirco%2Flockit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zemirco%2Flockit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zemirco%2Flockit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zemirco%2Flockit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zemirco","download_url":"https://codeload.github.com/zemirco/lockit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247419860,"owners_count":20936012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T02:01:35.450Z","updated_at":"2025-10-06T13:44:27.538Z","avatar_url":"https://github.com/zemirco.png","language":"JavaScript","readme":"# Lockit\n\n[![Build Status](https://travis-ci.org/zemirco/lockit.svg?branch=master)](https://travis-ci.org/zemirco/lockit)\n[![NPM version](https://badge.fury.io/js/lockit.svg)](http://badge.fury.io/js/lockit)\n[![Dependency Status](https://david-dm.org/zemirco/lockit.svg)](https://david-dm.org/zemirco/lockit)\n\nLockit is an authentication solution for [Express](http://expressjs.com/).\nCheck out the [demo](http://arcane-caverns-2402.herokuapp.com/).\n\nIt consists of multiple single purpose modules:\n\n - [lockit-login](https://github.com/zemirco/lockit-login)\n - [lockit-signup](https://github.com/zemirco/lockit-signup)\n - [lockit-delete-account](https://github.com/zemirco/lockit-delete-account)\n - [lockit-forgot-password](https://github.com/zemirco/lockit-forgot-password)\n - [lockit-sendmail](https://github.com/zemirco/lockit-sendmail)\n - [lockit-couchdb-adapter](https://github.com/zemirco/lockit-couchdb-adapter)\n - [lockit-mongodb-adapter](https://github.com/zemirco/lockit-mongodb-adapter)\n - [lockit-sql-adapter](https://github.com/zemirco/lockit-sql-adapter)\n - [lockit-utilities](https://github.com/zemirco/lockit-utilities)\n - [lockit-template-blank](https://github.com/zemirco/lockit-template-blank)\n\n## Table of contents\n\n- [Quickstart](#quickstart)\n- [Full Installation](#full-installation)\n- [Configuration](#configuration)\n  - [Database connection](#database-connection)\n  - [Sending emails](#sending-emails)\n  - [Custom views](#custom-views)\n- [Events](#events)\n  - [signup](#signup)\n  - [login](#login)\n  - [logout](#logout)\n  - [delete](#delete)\n  - [forgot::sent](#forgotsent)\n  - [forgot::success](#forgotsuccess)\n- [REST API](#rest-api)\n- [Sample config](#sample-config)\n- [Features](#features)\n- [Routes included](#routes-included)\n\n## Quickstart\n\n1. Create new Express app.\n\n  `express`\n\n2. Install Lockit and sessions via npm.\n\n  `npm install \u0026\u0026 npm install lockit cookie-session --save`\n\n3. Use `lockit` and `cookie-session` in your Express `app.js`.\n\n  ```js\n  var cookieSession = require('cookie-session');\n  var Lockit = require('lockit');\n  var lockit = new Lockit();\n\n  ...\n  app.use(cookieSession({\n    secret: 'my super secret String'\n  }));\n  app.use(lockit.router);\n  ```\n\n4. Go to [localhost:3000/signup](http://localhost:3000/signup)\n\nBy default Lockit uses an in-memory SQLite database.\nSo you don't have to set up any db. Lockit will just work.\nCheck out the [default example](https://github.com/zemirco/lockit/tree/master/examples/default).\n\nFor production use a persistent data store!\n\n## Full installation\n\n1. Install and require\n\n  `npm install lockit --save`\n\n  ```js\n  var config = require('./config.js');\n  var Lockit = require('lockit');\n\n  var app = express();\n\n  // express middleware\n  // ...\n  // sessions are required\n  app.use(cookieParser());\n  app.use(cookieSession({\n    secret: 'your secret here'\n  }));\n\n  var lockit = new Lockit(config);\n\n  app.use(lockit.router);\n\n  // you now have all the routes like /login, /signup, etc.\n  // and you can listen on events. For example 'signup'\n  lockit.on('signup', function(user, res) {\n    console.log('a new user signed up');\n    res.send('Welcome!');   // set signup.handleResponse to 'false' for this to work\n  });\n  ```\n\n2. Add styles\n\n  Views are built with [bootstrap](http://getbootstrap.com/).\n  You can use [your own ones](#custom-views) though!\n  Use Bootstrap CDN and add the following line to your `layout.jade`\n\n  ```jade\n  link(rel='stylesheet', href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css')\n  ```\n\n3. Install database adapter\n\n  `npm install lockit-[DB]-adapter` where `[DB]` can be\n\n  | Database | Command |\n  | --- | --- |\n  | [CouchDB](https://github.com/zemirco/lockit-couchdb-adapter) | `npm install lockit-couchdb-adapter` |\n  | [MongoDB](https://github.com/zemirco/lockit-mongodb-adapter) | `npm install lockit-mongodb-adapter` |\n  | [SQL (PostgreSQL, MySQL, MariaDB or SQLite)](https://github.com/zemirco/lockit-sql-adapter) | `npm install lockit-sql-adapter` |\n\n  If you use a SQL database you also have to install the connector.\n\n  ```\n  npm install pg       # for postgres\n  npm install mysql    # for mysql\n  npm install sqlite3  # for sqlite\n  npm install mariasql # for mariasql\n  ```\n\n## Configuration\n\nYou need a `config.js` somewhere in your app.\n\n### Database connection\n\nAdd the database connection string to your `config.js`.\n\n```js\n// database settings for CouchDB\nexports.db = 'http://127.0.0.1:5984/';        // connection string for database\n\n// or if you want to use MongoDB\n// exports.db = {\n//   url: 'mongodb://127.0.0.1/',\n//   name: 'test',\n//   collection: 'users'  // collection name for MongoDB\n// };\n\n// PostgreSQL\n// exports.db = {\n//   url: 'postgres://127.0.0.1:5432/',\n//   name: 'users',\n//   collection: 'my_user_table'  // table name for SQL databases\n// };\n\n// MySQL\n// exports.db = {\n//   url: 'mysql://127.0.0.1:3306/',\n//   name: 'users',\n//   collection: 'my_user_table'\n// };\n\n// SQLite\n// exports.db = {\n//   url: 'sqlite://',\n//   name: ':memory:',\n//   collection: 'my_user_table'\n// };\n```\n\n### Sending emails\n\nBy default the email service is stubbed and no emails are sent.\nThat means that you won't receive any signup and password reset tokens.\nYou have to look them up in your database and call the routes manually (e.g. `/signup/:token`).\nTo send emails you need an email server and you have to change the settings in your `config.js`:\n\n - `emailType` - usually `nodemailer-smtp-transport`\n - `emailSettings` - see [nodemailer](https://github.com/andris9/Nodemailer) for more information\n\nWith [mailgun](http://www.mailgun.com/pricing) you can send up to 10,000 emails per month for free.\n\n```js\nexports.emailType = 'nodemailer-smtp-transport';\nexports.emailSettings = {\n  service: 'Mailgun',\n  auth: {\n    user: 'postmaster@username.mailgun.org',\n    pass: 'secret-password'\n  }\n};\n```\n\n### Custom views\n\nLockit comes with built-in views which are based on Bootstrap.\nIf you want to use your own custom views you can. It is dead simple.\n\nPut them into your `views` folder, for example `views/lockit/myLogin.jade`.\nThen edit your `config.js` and set the path to your custom view.\n\n```js\nexports.login = {\n  route: '/login',\n  logoutRoute: '/logout',\n  views: {\n    login: 'lockit/myLogin.jade',\n    loggedOut: 'lockit/myLogoutSuccess.jade'\n  }\n};\n```\n\nThe only thing you have to keep in mind is the structure. The `login.views.login` view, for example,\nneeds a form element with two input fields. The `method` has to be `POST` and `action` should point\nto your `login.route`. The input fields have to have the names `login` and `password`. If something\nwent wrong during the login process you'll get an `error` variable that you can use in your template.\n\nHere is a minimalistic example for an alternative `myLogin.jade`.\n\n```jade\nextend /layout\n\nblock content\n  h1 Login\n  form(action=\"/login\", method=\"POST\")\n    div\n      label(for=\"login\") Email or Username\n      input(type=\"text\", id=\"login\", name=\"login\", placeholder=\"Your email or username\")\n    div\n      label(for=\"password\") Password\n      input(type=\"password\", id=\"password\", name=\"password\", placeholder=\"Your password\")\n    if error\n      p #{error}\n    input(type=\"submit\", value=\"Login\")\n```\n\nFor more information about each view see the `views` folder inside the different repositories.\nMake sure your view extends `/layout` which is different to your normal views. They extend `layout`\nwithout the slash. This is required to find the view.\n\n## Events\n\nLockit emits the most important events for user authentication. Those are\n\n - `signup`\n - `login`\n - `logout`\n - `delete`\n\nYou can use these events to intercept requests and implement some custom logic,\nlike getting the gravatar before sending a response to the client.\n\n##### `signup`\n\nA new user signed up. The callback function has two arguments.\n\n- `user` is an object and contains information about the new user, like `user.name` or `user.email`.\n- `res` is the standard Express.js `res` object with methods like `res.render` and `res.send`.\nIf you've set `signup.handleResponse` to `false` Lockit will not handle the response for you.\nYou therefore have to send the response back to the client manually or otherwise it will wait forever.\n\n```js\nlockit.on('signup', function(user, res) {\n  // ...\n});\n```\n\n##### `login`\n\nA user logged in. Callback function this time has three arguments.\n\n- `user` is again the JSON object containing info about that particular user.\n- `res` is the normal Express.js response object with all properties and methods.\n- `target` is the redirect target route after a successful login, i.e. `/settings`\n\n```js\nlockit.on('login', function(user, res, target) {\n  // ...\n});\n```\n\n##### `forgot::sent`\n\nA user forgot the password and an email has been sent.\nCallback function has two arguments.\n\n- `user` is again the JSON object containing info about that particular user.\n- `res` is the normal Express.js response object with all properties and methods.\n\n```js\nlockit.on('forgot::sent', function(user, res) {\n  // ...\n});\n```\n\n##### `forgot::success`\n\nUser has created a new password. Callback function has two arguments.\n\n- `user` is again the JSON object containing info about that particular user.\n- `res` is the normal Express.js response object with all properties and methods.\n\n```js\nlockit.on('forgot::success', function(user, res) {\n  // ...\n});\n```\n\n##### `logout`\n\nA user logged out. Same as above without the `target` string.\n\n```js\nlockit.on('logout', function(user, res) {\n  // ...\n});\n```\n\n##### `delete`\n\nA user deleted an account. Same callback as above.\n\n```js\nlockit.on('delete', function(user, res) {\n  // ...\n});\n```\n\n## REST API\n\nIn a single page application (SPA) all routing and template rendering is done on the client.\nBefore version 0.5.0 Lockit caught relevant routes, like `/login` or `/signup`,\nand did the entire rendering on the server.\n\nStarting with version 0.5.0 you're able to use Lockit as a REST API and communicate via JSON.\nAll you have to do is set `exports.rest` in your `config.js`.\n\n```js\nexports.rest = {\n  // set starting page for single page app\n  index: 'public/index.html',\n\n  // use view engine (render()) or send static file (sendfile())\n  useViewEngine: false\n}\n```\n\nWith REST enabled all default routes get a `/rest` prefix so you can catch `/login`\non the client. To allow for true page refreshes (i.e. user is at `/login` and refreshes the page)\nall routes on the server, like `/login` and `/signup`, send the `rest.index` view\nto the client. From there your SPA has to take over.\n\nHere is a short example how the process works.\n\n1. User sends GET request for `/login`\n2. Server has a route handler for this request and sends `index.html` back\n3. Client router takes over and renders `/login` page\n4. User enters credentials and submits the form\n5. Client controller catches submit and sends POST via AJAX request to `/rest/login`\n6. Server handles POST request and validates user credentials\n7. Server sends status code `200` or some JSON with error message\n8. Client reacts to JSON from server and redirects on success or shows error\n\nI've built a [simple example](https://github.com/zemirco/lockit/tree/master/examples/angular)\nusing AngularJS on the client side.\n\n## Sample config\n\nIf you want to go crazy and customize all the things you can:\n\n```js\n// name for subject and email content\nexports.appname = 'lockit - Test App';\n\n// url for proper link generation\nexports.url = 'http://localhost:3000';\n\n// email settings (same as nodemailer)\nexports.emailType = 'nodemailer-stub-transport';\nexports.emailSettings = {\n  service: 'none',\n  auth: {\n    user: 'none',\n    pass: 'none'\n  }\n};\n\n// whenever a library uses request under the hood (like nano in lockit-couchdb-adapter)\n// the following values will be used\nexports.request_defaults = {\n  // proxy: 'http://someproxy'\n};\n\n// email template from npm\nexports.emailTemplate = 'lockit-template-blank';\n\n// render views or json for single page apps\nexports.rest = false;\n\n// or if you want to use rest\n// exports.rest = {\n//\n//   // set starting page for single page app\n//   index: 'public/index.html',\n//\n//   // use view engine (render()) or send static file (sendfile())\n//   useViewEngine: false\n//\n// }\n\n// signup settings\nexports.signup = {\n  route: '/signup',\n  tokenExpiration: '1 day',\n  views: {\n    signup: '',         // input fields 'name', 'email' and 'password' | local variable 'error' | POST /'signup.route'\n    linkExpired: '',    // message link has expired | input field 'email' | POST /'signup.route'/resend-verification\n    verified: '',       // message email is now verified and maybe link to /'login.route'\n    signedUp: '',       // message email has been sent =\u003e check your inbox\n    resend: ''          // input field 'email' | local variable 'error' | POST /'signup.route'/resend-verification\n  },\n  handleResponse: true  // let lockit handle the response after signup success\n};\n\n// login settings\nexports.login = {\n  route: '/login',\n  logoutRoute: '/logout',\n  views: {\n    login: '',          // input fields 'login' and 'password' | POST /'login.route' | local variable 'error'\n    loggedOut: ''       // message that user logged out\n  },\n  handleResponse: true  // let lockit handle the response after login/logout success\n};\n\n// forgot password settings\nexports.forgotPassword = {\n  route: '/forgot-password',\n  tokenExpiration: '1 day',\n  views: {\n    forgotPassword: '', // input field 'email' | POST /'forgotPassword.route' | local variable 'error'\n    newPassword: '',    // input field 'password' | POST /'forgotPassword.route'/#{token} | local variable 'error'\n    changedPassword: '',// message that password has been changed successfully\n    linkExpired: '',    // message that link has expired and maybe link to /'forgotPassword.route'\n    sentEmail: ''       // message that email with token has been sent\n  }\n};\n\n// delete account settings\nexports.deleteAccount = {\n  route: '/delete-account',\n  views: {\n    remove: '',         // input fields 'name', 'phrase', 'password' | POST /'deleteAccount.route' | local variable 'error'\n    removed: ''         // message that account has been deleted\n  },\n  handleResponse: true  // let lockit handle the response after delete account success\n};\n\n// lock account\n// show warning after three failed login attempts\nexports.failedLoginsWarning = 3;\n// lock account after five failed login attempts\nexports.failedLoginAttempts = 5;\n// lock account for 20 minutes\nexports.accountLockedTime = '20 minutes';\n\n// public email address of your app\nexports.emailFrom = 'welcome@lock.it';\n\n// email signup template\nexports.emailSignup = {\n  subject: 'Welcome to \u003c%- appname %\u003e',\n  text: [\n    '\u003ch2\u003eHello \u003c%- username %\u003e\u003c/h2\u003e',\n    'Welcome to \u003c%- appname %\u003e.',\n    '\u003cp\u003e\u003c%- link %\u003e to complete your registration.\u003c/p\u003e'\n  ].join(''),\n  linkText: 'Click here'\n};\n\n// email already taken template\nexports.emailSignupTaken = {\n  subject: 'Email already registered',\n  text: [\n    '\u003ch2\u003eHello \u003c%- username %\u003e\u003c/h2\u003e',\n    'you or someone else tried to sign up for \u003c%- appname %\u003e.',\n    '\u003cp\u003eYour email is already registered and you cannot sign up twice.',\n    ' If you haven\\'t tried to sign up, you can safely ignore this email. Everything is fine!\u003c/p\u003e',\n    '\u003cp\u003eThe \u003c%- appname %\u003e Team\u003c/p\u003e'\n  ].join('')\n};\n\n// resend signup template\nexports.emailResendVerification = {\n  subject: 'Complete your registration',\n  text: [\n    '\u003ch2\u003eHello \u003c%- username %\u003e\u003c/h2\u003e',\n    'here is the link again. \u003c%- link %\u003e to complete your registration.',\n    '\u003cp\u003eThe \u003c%- appname %\u003e Team\u003c/p\u003e'\n  ].join(''),\n  linkText: 'Click here'\n};\n\n// forgot password template\nexports.emailForgotPassword = {\n  subject: 'Reset your password',\n  text: [\n    '\u003ch2\u003eHey \u003c%- username %\u003e\u003c/h2\u003e',\n    '\u003c%- link %\u003e to reset your password.',\n    '\u003cp\u003eThe \u003c%- appname %\u003e Team\u003c/p\u003e'\n  ].join(''),\n  linkText: 'Click here'\n};\n```\n\n## Features\n\n - responsive html email template: [lockit-template-blank](https://github.com/zemirco/lockit-template-blank)\n - support for wide range of databases out of the box\n - email address verification\n - account locking after too many failed login attempts\n - verification link expiration\n - failed login tracking\n - /login redirection when user is unauthorized\n - password hash generation with bcrypt\n - unit tests for all modules\n - serves proper HTML views or only JSON\n - events for most important happenings `login`, `logout`, `signup` and `delete`\n - implementation of [lots of](https://www.owasp.org/index.php/Guide_to_Authentication) [best](http://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication) [pratices](https://www.owasp.org/index.php/Authentication_Cheat_Sheet)\n\n\n## Routes included\n\nFrom [lockit-signup](https://github.com/zemirco/lockit-signup)\n\n - GET /signup\n - POST /signup\n - GET /signup/:token\n - GET /signup/resend-verification\n - POST /signup/resend-verification\n\nFrom [lockit-login](https://github.com/zemirco/lockit-login)\n\n - GET /login\n - POST /login\n - POST /login/two-factor\n - GET /logout\n\nFrom [lockit-forgot-password](https://github.com/zemirco/lockit-forgot-password)\n\n - GET /forgot-password\n - POST /forgot-password\n - GET /forgot-password/:token\n - POST /forgot-password/:token\n\nFrom [lockit-delete-account](https://github.com/zemirco/lockit-delete-account)\n\n - GET /delete-account\n - POST /delete-account\n\n## Test\n\n`grunt`\n\n## License\n\nMIT\n","funding_links":[],"categories":["JavaScript","others","Packages","Number"],"sub_categories":["Authentication"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzemirco%2Flockit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzemirco%2Flockit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzemirco%2Flockit/lists"}