Code Monkey home page Code Monkey logo

monetta's Introduction

Monetta

Build Status Coverage Status

Token authorization for MongoDB and Express framework

Monetta is opinionated token authorization for MongoDB and Express (or any other Javascript framework using similar middleware functions). Principle is simple, Monetta receives configuration and returns middleware for login, authorization and logout.
Configuration options include MongoDB connection parameters and names of collections where users and access tokens reside. After Monetta is initialized with proper config it creates MongoDB connection and uses it to read from users table and manage access tokens. Almost everything happens under the hood, everything user of the module has to do is call middleware to pass user credentials, receive token, check token etc.

Installation

npm i -S monetta

Example

'use strict';

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const crypto = require('crypto');
const Monetta = require('monetta');

const config = {
  mongoConnection: {
    username: null,
    password: null,
    hosts: [
      {
        host: 'localhost',
        port: 27017
      }
    ],
    database: 'monetta'
  },
  // mongoConnectionUri: 'mongodb://localhost/monetta',
  users: {
    collection: 'users',
    mainField: 'username',
    passwordField: 'password'
  },
  accessTokens: {
    collection: 'tokens',
    httpHeader: 'x-auth-token',
    length: 24,
    maxAllowed: 5
  },
  generatePasswordHash: password => {
    const hash = crypto.createHmac('sha256', 'Secret squirrel');
    hash.update(password);
    return hash.digest('hex');
  }
};

const auth = new Monetta(config);

app.use(bodyParser.json());

app.get('/', (req, res) =>
  res.json({ message: 'This route does not require authorization.' })
);
app.post('/login', auth.login(), (req, res) =>
  res.json({ token: req.authToken })
);
app.get('/profile', auth.authorize(), (req, res) =>
  res.json({ user: req.user })
);
app.post('/logout', auth.logout(), (req, res) =>
  res.json({
    message: 'Logout succesful'
  })
);
app.post('/logout-all', auth.logoutAll(), (req, res) =>
  res.json({
    message: 'All devices are logged out'
  })
);

app.use((err, req, res, next) => {
  console.log(err);
  res.status(err.status).json({ error: err.message });
});

app.listen(3000, () => console.log('Example app listening on port 3000!'));

Configuration options

  • mongoConnection: parameters used to specify connection to MongoDB, these options are transformed into MongoDB URI using mongodb-uri-node, mongoConnectionUri can be used instead of this option.
  • mongoConnectionUri: raw string format used to initialize MongoDB connection, defaults to mongodb://localhost/monetta, mongoConnection option can be used instead.
  • users: used to specify collection where users are being stored
    • collection: name of collection, defaults to users
    • mainField: field used to search through user collection, same field you submit with password when logging in (in most cases username or email), defaults to username
    • passwordField: field used to store passwords, defaults to password
  • accessTokens: used to specify collection where access tokens are being stored, and options related to access tokens
    • collection: name of collection, defaults to tokens
    • httpHeader: header used to send access token when accessing routes that require authorization, defaults to x-auth-token
    • length: length of the access token, defaults to 48
    • maxAllowed: same user can have multiple active access tokens, i.e. when logging in with multiple devices, this option specifies maximum number of access tokens active at once, defaults to 10
  • generatePasswordHash: function used to encrypt password, only input parameter is password as string, returns encrypted password as string, by default it only emmits warning and returns password in plain text, WARNING! storing passwords in plain text to database is dangerous, please, pretty please, supply your own hash function when using Monetta

Middleware

login

Returns middleware that checks request body for fields specified in users config, searches the database for matching user, and creates access token.
For example, if user config looks like this:

users: {
    collection: 'super_cool_users',
    mainField: 'super_cool_name',
    passwordField: 'super_cool_pass'
  }

Request body could look like this:

{
  "super_cool_name": "test",
  "super_cool_pass": "test"
}

Login middleware will check super_cool_users collection for user with property super_cool_name that equals test. Then it will compare password hash from super_cool_pass property from request body to one in database. If user is not found or password hashes do not match it will throw error. If user is found it will create access token, store it in database, and create req.authToken property containing said token.

app.post('/login', auth.login(), (req, res) =>
  res.json({ token: req.authToken })
);

authorize

Returns middleware that checks header specified in accessTokens.httpHeader for access token. Then it searches database for user related to that access token. If user is found it will bind user object to req.user, otherwise it will throw error.

app.get('/profile', auth.authorize(), (req, res) =>
  res.json({ user: req.user })
);

logout

Returns middleware that checks header specified in accessTokens.httpHeader for access token. Then it searches database for that token. If token is found it will delete the token from database, otherwise it will throw error.

app.post('/logout', auth.logout(), (req, res) =>
  res.json({
    message: 'Logout succesful'
  })
);

logoutAll

Returns middleware that checks header specified in accessTokens.httpHeader for access token. Then it searches database for that token. If token is found it will find user who owns the token and delete all tokens owned by that user, otherwise it will throw error.

app.post('/logout-all', auth.logoutAll(), (req, res) =>
  res.json({
    message: 'All devices are logged out'
  })
);

TODO

  • Add access token expiration
  • Add option to use refresh token
  • Add http error codes on thrown errors

monetta's People

Contributors

glepur avatar

Stargazers

Denis Šaško avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.