Build restful API authentication using JSON web tokens (JWT)

Build restful API authentication using JSON web tokens (JWT)

To build Restful API authentication using JWT we will use Node.js, Mongoose.js, JWT and Express.js.

The workflow

Will Have unprotected and protected routes.

A user will authenticate by passing in a name and a password and get back a token.

The user will store this token on their client-side and send it for every request.

We will validate this token, and if all is good, pass back information in JSON format.

Our API will be built with

Normal routes (not authenticated).

route middleware to authenticate the token.

route to authenticate a user and password and get a token.

authenticated routes to get all users.

Create API Routes

This includes the following routes:

POST http://localhost:4000/api/authenticate : Check name and password against the database and provide a token if authentication successful. This route will not require a token because this is where we get the token.

GET http://localhost:4000/api : Show a random message. This route is protected and will require a token.

GET http://localhost:4000/api/users List all users. This route is protected and will require a token.

Also

Create Basic Routes These are the unprotected routes like the home page (http://localhost:4000). We'll also create a /setup route here so that we can create a sample user in our new database

Our directory structure would look like:

Check the code below

The Config.js is used for configuration purpose such as keeping mongodb URI, secret, application port etc. values.

// config.js

// set up a configuration parameters and pass it using module.exports
module.exports = {
    'secret': 'mysecret',
    'database': 'mongodb://localhost:27017/test_db',
    'port' : '4000'
};

The user.js for ODM using MongooseJS.

//user.js

// get an instance of mongoose and mongoose.Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// set up a mongoose model and pass it using module.exports
module.exports = mongoose.model('User', new Schema({ 
    name: String, 
    password: String, 
    admin: Boolean 
}));

Our Main server.js file: It has JWT implemetation, route definition and authentication middleware.

// server.js

// We are building an Express Application
var express = require('express');
var app = express();

// Bodyparser for parsing form data
var bodyParser = require('body-parser');
// Use bodyparse in our app
app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

// Morgan for logging
var morgan = require('morgan');
// Use morgan in our app
app.use(morgan('dev'));

// Load configuration
var config = require('./config');

// jsonwebtoken for authentication
var jwt = require('jsonwebtoken');

// Mongoose as ORM for Mongodb-nodejs
var mongoose = require('mongoose');
mongoose.connect(config.database); // connect to database

app.set('superSecret', config.secret); // Use secret from config file

var User = require('./models/user'); // Mongoose ORM schema

app.listen(config.port); // Start server at port specified in config.js

app.get('/', function(req, res) {
    res.send('Create API Routes This includes the following routes');
});

app.get('/setup', function(req, res) {

    // create a sample uservar adminuser = new User({
        name: 'admin',
        password: 'password',
        admin: true
    });

    // save the sample user
    adminuser.save(function(err) {
        if (err) throw err;

        console.log('User saved successfully');
        res.json({
            success: true
        });
    });
});

var router = express.Router(); // Create Express router
app.use('/api', router); // Access router's method with /api as prefix e.g. http://localhost:4000/api/

// Create authentication token if the username and passwords are matched or correct
router.post('/authenticate', function(req, res) {
    // find the user
    User.findOne({
        name: req.body.name
    }, function(err, user) {
        if (err) throw err;

        if (!user) {
            res.json({
                success: false,
                message: 'Authentication failed. User not found.'
            });
        } else if (user) {
            // check if password matchesif (user.password != req.body.password) {
                res.json({
                    success: false,
                    message: 'Authentication failed. Wrong password.'
                });
            } else {

                const payload = {
                    admin: user.admin
                };
                var token = jwt.sign(payload, app.get('superSecret'), {
                    expiresIn: 24 * 60 * 60
                });
                // return the information including token as JSON
                res.json({
                    success: true,
                    message: 'Get your token!',
                    token: token
                });
            }

        }

    });
});

// route middleware to verify a token
router.use(function(req, res, next) {
    // check header or url parameters or post parameters for tokenvar token = req.body.token || req.query.token || req.headers['x-access-token'];

    // decode tokenif (token) {
        // verifies secret and checks exp
        jwt.verify(token, app.get('superSecret'), function(err, decoded) {
            if (err) {
                return res.json({
                    success: false,
                    message: 'Failed to authenticate token.'
                });
            } else {
                // if everything is good, save to request for use in other routes
                req.decoded = decoded;
                next();
            }
        });

    } else {
        // if there is no token// return an errorreturn res.status(403).send({
            success: false,
            message: 'No token provided.'
        });
    }
});

// API routes always be accessed with authentication
router.get('/', function(req, res) {
    res.json({
        message: 'welcome to our api!!!'
    });
});

router.get('/users', function(req, res) {
    User.find({}, function(err, users) {
        res.json(users);
    });
});

console.log('Server started on the port', +config.port);

We can verify our API's using POSTMAN client.

For GET request, You may pass the generated Token from URL or using x-access-token header.

Thanks for reading !!

To view or add a comment, sign in

Others also viewed

Explore content categories