Browsing:

Category: express

Beginning Node.js – local authentication with Passport-Local Mongoose – part 6

Disclaimer: This is a series about me, creating a web application in Node.js. The completed example is available here.

I have a deep respect for all those developers out there that write fantastic modules I can use in my projects. One little gem is passport-local-mongoose. I've written about it before but as you see I'm doing it again.

What is passport-local-mongoose?

You can plug-in passport-local-mongoose into your Mongoose Userschema. This decorates the User object with a set of methods. E.g.

  • authenticate
  • register
  • setPassword
  • serialize
  • deserialize

It also hashes the passwords. This saves a lot of work.

What we should work on

  • Users should be able to register
  • Users should be able to authenticate
  • Users should be able to change their password
  • Users should be able to change their e-mail address
  • There should be a 'forgot password' procedure
  • Users should be able to delete their accounts

This article covers only 'register' and 'authenticate'. You can go ahead and clone the restaurant github repo for a full example.

To add local authentication to your app you'll need to run:

Of course, you may add your own properties to the model:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    passportLocalMongoose = require('passport-local-mongoose');

var User = new Schema({
    uuid: {
        type: String,
        required: false
    },
    firstname: {
        type: String,
        required: true
    },
    active: {
        type: String,
        required: false
    }
});

var options = ({missingPasswordError: "Wrong password"});
User.plugin(passportLocalMongoose,options);

module.exports = mongoose.model('User', User)

Now let's hook up Passport in our app.

Controller

Let's create a user controller which contains the register, the login and the getLogin functions (to check if a user has logged in).
Create a file named controller.user.js and put it in the app folder:

var mongoose = require('mongoose');
var User = require('./model.user');

exports.register = function (req, res) {
    console.log("registering: " + req.body.firstName);
    User.register(new User({
        username: req.body.username,
        firstname: req.body.firstname
    }), req.body.password, function (err, user) {
        if (err) {
            console.log(err);
            return res.send(err);
        } else {
            res.send({
                success: true,
                user: user
            });
        }
    });
};

exports.login = function (req, res, next) {

    User.authenticate()(req.body.username, req.body.password, function (err, user, options) {
        if (err) return next(err);
        if (user === false) {
            res.send({
                message: options.message,
                success: false
            });
        } else {
            req.login(user, function (err) {
                res.send({
                    success: true,
                    user: user
                });
            });
        }
    });

};

exports.getLogin = function (req, res) {
    console.log(req.user);
    if (req.user) {

        return res.send({
            success: true,
            user: req.user
        });

    } //res.send(500, {status:500, message: 'internal error', type:'internal'}); == deprecated


    res.send({
        success: false,
        message: 'not authorized'
    });
};

What happens?
1. User.authenticate and User.register:
The User.authenticate and User.register are functions we get from passport-local-mongoose. I just took this code as an example.

2. Check if a user is logged in with 'if(req.user)'
If a user is logged in, the req.user property is populated with the user object.
So if it exists, the user is logged in.

Routes

//mongodb
var mongoose = require('mongoose');
var User = require('./model.user');

var users = require('./controller.user');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var cookieParser = require('cookie-parser');
var session = require('express-session');


module.exports = function (app) {

    //initialize passport
    passport.use(User.createStrategy());
    // use static serialize and deserialize of model for passport session support
    passport.serializeUser(User.serializeUser());
    passport.deserializeUser(User.deserializeUser());

    //need this according to passport guide
    app.use(cookieParser());
    app.use(session({
        secret: 'the princess and the frog',
        saveUninitialized: true,
        resave: true
    }));
    app.use(passport.initialize());
    app.use(passport.session());

    //routes
    app.route('/register').post(users.register);
    app.route('/login').post(users.login);
    app.route('/login').get(users.getlogin);
   
   
};

Add this file to main.js, like so:

require('./app/routes.user')(app);

This will be your completed main.js:

var express = require('express');
var app = express();
var bodyparser = require('body-parser');
var mongoose = require('mongoose');

app.use(bodyparser.urlencoded({
  extended: true
}));

app.use(bodyparser.json());

mongoose.connect('mongodb://localhost:27017/restaurant');

require('./app/routes.food')(app);
require('./app/routes.user')(app);

app.use(express.static(__dirname + '/public'));

app.set('port', process.env.PORT || 3001);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

Let's try this

Install Postman or another REST API test tool.

  • Don't forget to configure the headers: Content-Type application/json

First, let's register a user (click POST):

Postman_passport

Second, let's login:

Selection_012

Check the login status:

Selection_015

The end of this series

This is where this series end. I hope anyone will enjoy this and at least learns something from my struggles. I know I did!
Your feedback is more than welcome by the way.


Beginning Node.js – REST API with Express 4 – part 2

This is the most simple REST API possible. I will explain every single detail in this post.

var express = require('express');
var app = express();

var menu = [{"description" : "papadums", "price":"2,00"}, {"description" : "chicken tikka masala", "price":"14,00"},{"description" : "fisher king beer", "price":"2,50"},{"description" : "sag paneer", "price":"6,00"}];

app.use(express.static(__dirname + '/public'));

app.get('/food', function(req, res){
  res.send(menu);
});

app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

Let's get started

First create a folder named 'restaurant' or whatever you would like to name the API.
Then run 'npm init' to create a package.json file. This file contains metadata, dependencies etc.:

mkdir restaurant
cd restaurant
npm init

You will get a bunch of questions. Answer them (or accept the defaults) and hit enter:

About to write to /Users/jacqueline/Dropbox/devel/restaurant/package.json:
{
  "name": "restaurant",
  "version": "0.1.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jacqueline",
  "license": "MIT"
}

Is this ok? (yes)

Install Express

Next we will install Express with NPM. Express is a minimalist web framework for Node.js.

jacqueline@nsa:~/Dropbox/devel/restaurant$ npm install express --save

You will now see 'express' mentioned in the package.json.
The '--save' parameter adds a "^" before the package, it will make sure the right version is used.

Create the app

Create a file named 'main.js' (that's how I named the main file in my package.json, you can also name it app.js or server.js).

Add these contents:

var express = require('express');
var app = express();
app.get('/', function(req, res){
      res.send('hello world');
    });

 app.listen(3000);

Next install nodemon because it is awesome. It restarts node every time a file in the project is changed.
Add the '-g' parameter because nodemon should be installed globally and not just as a module in the project folder.

npm install -g nodemon

Now run nodemon main.js on the commandline. It will return:

jacqueline@nsa:~/Dropbox/devel/restaurant$ nodemon main.js 
18 Oct 08:04:59 - [nodemon] v1.2.0
18 Oct 08:04:59 - [nodemon] to restart at any time, enter `rs`
18 Oct 08:04:59 - [nodemon] watching: *.*
18 Oct 08:04:59 - [nodemon] starting `node main.js`

Now browse to http://localhost:3000. This will display 'Hello World' in the browser.

Serve JSON data

Alter your main.js file and add some json and change the app.get bit:

var express = require('express');
var app = express();

var menu = [{"description" : "papadums", "price":"2,00"}, {"description" : "chicken tikka masala", "price":"14,00"},
{"description" : "fisher king beer", "price":"2,50"},{"description" : "sag paneer", "price":"6,00"}];

app.get('/food', function(req, res){
  res.send(menu);
});

app.listen(3000);

Now if we browse to http://localhost/food, we will retrieve our delicious menu. We can also a REST client like POSTMAN to test:
food

With curl:

curl http://localhost:3000/food
[{"description":"papadums","price":"2,00"},{"description":"chicken tikka masala","price":"14,00"},{"description":"fisher king beer","price":"2,50"},{"description":"sag paneer","price":"6,00"}]

Consuming the API

Create a folder called public in your app directory.

Next add this line to main.js, with this we'll tell Express to go and find index.html files in a subfolder called public:

app.use(express.static(__dirname + '/public'));

Drop an index.html in the public folder.
This makes the directory structure look like so:

restaurant/
├── main.js
├── node_modules
│   └── express
├── package.json
└── public
└── index.html

Open index.html and add the following code:



  
  
  
    

Welcome to my restaurant!

On the menu:

And the result is..:

food-awesom

Add Bootstrap with Bower

Bower is like NPM, but for front end scripts. You can use NPM for frontend scripts as well, but I like to keept them separate.

npm install -g bower

Create a file named .bowerrc to tell Bower to put the javascripts into a /public/js:

vim .bowerrc
{
    "directory" : "public/js"
 }

You can create a bower.json file to organize the dependencies:

bower init

jacqueline@nsa:~/Dropbox/devel/restaurant$ bower init
? name: restaurant
? version: 0.1.0
? description: menu app
? main file: main.js
? what types of modules does this package expose?: node
? keywords:
? authors: jacqueline <jacqueline@nsa.gov>
? license: MIT

Then install your client side javascript dependencies like so:

bower install --save bootstrap

Now we can add some styling:

nicerestaurant

Last but not least: some feedback when starting the server

In Express you can define variables with app.set. I would suggest to configure the port like this:

app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

process.env.PORT || 3000 means: whatever is in the environment variable PORT, or use 3000 if there's nothing there.

This makes completed main.js look like this:

var express = require('express');
var app = express();

var menu = [{"description" : "papadums", "price":"2,00"}, {"description" : "chicken tikka masala", "price":"14,00"},
{"description" : "fisher king beer", "price":"2,50"},{"description" : "sag paneer", "price":"6,00"}];

app.get('/food', function(req, res){
  res.send(menu);
});

app.use(express.static(__dirname + '/public'));

app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'));
console.log("the server is running on http://localhost:" + app.get('port'));

And this is where this tutorial ends. I love open source. It's great to be able to use all these tools (Node, NPM, Express) and be very productive. Next time I will show how to use a (NoSQL) database. Not sure to use MongoDb or Postgresql yet. We'll see.