Friday, 14 April 2017

JWT Authentication & Authorization

I'm trying to find a way to protect each user resource from another user that is correctly authorized. So this is the wrong flow:

enter image description here

As you can see, Alice has the right JWT token and she is able to get Johns information if she (somehow) manages to get John's id. I want to protect this from happening... How can I do it?

This is the code I'm using for passport authentication. Everything works fine, I'm just trying to add that extra layer of security.

passportTest.js

'use strict';
// load environment variables
require('dotenv').config();
/**
*Module dependencies
*/

const passport = require('passport');
const User = require('../models/user');
let jwt = require('jsonwebtoken');
/**

*Configuration and Settings
*/
const utilities = require('../models/utilities');

const errHandler = utilities.errHandler;
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const LocalStrategy = require('passport-local').Strategy;
const jwtOptions = {
  // Telling Passport to check authorization headers for JWT
  jwtFromRequest: ExtractJwt.fromAuthHeader(),
  // Telling Passport where to find the secret
  secretOrKey: process.env.SECRET
};


// Configure Passport to use JWT strategy to look up Users.
passport.use('jwt', new JwtStrategy(jwtOptions, function (jwt_payload, done) {
  User.findById({ _id: jwt_payload._doc._id }, (err, user) => {
    if (err) {
      return done(err, false);
    }

    if (user) {
      return done(null, user);
    } else {
      return done(null, false);
    }
  })
}));


passport.use('local-login', new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password',
  passReqToCallback: true
},
  function (req, email, password, done) {
    User.findOne({ email: email }, (err, user) => {
      if (err) {
        return errHandler(err);
      }

      if (!user) {
        return done(null, false, {
          errMsg: 'User does not exist, please' +
          ' <a class="errMsg" href="/signup">signup</a>'
        });
      }

      if (!user.validPassword(password)) {
        return done(null, false, { errMsg: 'Invalid password try again' });
      }

      return done(null, user);
    });

  }));
/**
*Export Module
*/
module.exports = passport;

Routes.js

'use strict';
// load environment variables
require('dotenv').config();
/**
*Module dependencies
*/
const express = require('express');
const passport = require('../config/passport');
const authChecker = require('../config/authentication-checker');
const passportTest = require('../config/passport-jwt');
let jwt = require('jsonwebtoken');
const utilities = require('../models/utilities');
const userController = require('../controllers/user.controller');
const expressJwt = require('express-jwt');

//==============================================================================
/**
*Create router instance
*/
var router = express.Router();
//==============================================================================
/**
*Module Variables
*/
//needed to protect the '/dashboard' route
function isLoggedIn(req, res, next) {
  if (req.headers.authorization) {
    passportTest.authenticate('jwt', { session: false }, (err, user) => {
      if (err) { return res.status(401); }

      if (user) {
        req.user = user;
        return next();
      } else {
        return res.status(401);
      }
    })(req, res, next);
  } else {
    return res.redirect('/login');
  }
}
//==============================================================================
/**
*Middleware
*/
router.use(passport.initialize());
router.use(passport.session());
// Authenticate the user and get a JSON Web Token to include in the header of future requests.
router.route('/auth').post((req, res, next) => {
  passportTest.authenticate('local-login', function (err, user, info) {
    if (err) {
      return next(err); // will generate a 500 error
    }
    if (!user) {
      return res.status(409).render('pages/login', { errMsg: info.errMsg });
    }
    req.login(user, function (err) {
      if (err) {
        console.error(err);
        return res.status(409);
      }
      return res.status(200).json(generateToken(user));
    });
  })(req, res, next);
}
);

// Example of required auth: protect dashboard route with JWT
router.get('/secure', isLoggedIn, function (req, res) {
  return res.send('It worked' + req.user);
});
router.route('/signup')
  .get(function (req, res) {
    return res.render('pages/signup');
  })
  .post(function (req, res, next) {
    passport.authenticate('local-signup', function (err, user, info) {
      if (err) {
        return next(err); // will generate a 500 error
      }
      if (!user) {
        return res.status(409).render('pages/signup', { errMsg: info.errMsg });
      }
      req.login(user, function (err) {
        if (err) {
          console.error(err);
          return next(err);
        }
        return res.redirect('/dashboard');
      });
    })(req, res, next);
  });
router.route('/api/users/id/:id').get(isLoggedIn, userController.getUserById)

Thanks in advance.



via Ricardo

No comments:

Post a Comment