Skip to content
This repository has been archived by the owner on Aug 30, 2021. It is now read-only.

JWT Authentication simplified #1300

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion config/env/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ module.exports = {
minPhraseLength: 20,
minOptionalTestsToPass: 4
}
},
jwt: {
secret: process.env.JWT_SECRET || 'M3@N_R0CK5',
options: {
expiresIn: process.env.JWT_EXPIRES_IN || '1d'
}
}

};
51 changes: 51 additions & 0 deletions config/lib/authorization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

var config = require('../config'),
jwt = require('jsonwebtoken'),
lodash = require('lodash'),
passport = require('passport');

var auth = {
signToken: signToken,
authorize: authorizeRequest
};

// Export the token auth service
module.exports = auth;

function authorizeRequest(req, res, next) {
passport.authenticate('jwt', { session: false }, function (err, user) {
if (err) {
return next(new Error(err));
}

if (user) {
req.user = user;
}

next();
})(req, res, next);
}

// Sign the Token
function signToken(user, options) {
var payload,
token,
jwtOptions;

if (!user || !user._id) {
return null;
}

options = options || {};

payload = {
user: user._id.toString()
};

jwtOptions = lodash.merge(config.jwt.options, options);

token = jwt.sign(payload, config.jwt.secret, jwtOptions);

return token;
}
9 changes: 5 additions & 4 deletions config/lib/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ var config = require('../config'),
hbs = require('express-hbs'),
path = require('path'),
_ = require('lodash'),
lusca = require('lusca');
lusca = require('lusca'),
authorization = require('./authorization');

/**
* Initialize local variables
Expand Down Expand Up @@ -89,6 +90,9 @@ module.exports.initMiddleware = function (app) {
// Add the cookie parser and flash middleware
app.use(cookieParser());
app.use(flash());

// Authorize Request
app.use(authorization.authorize);
};

/**
Expand Down Expand Up @@ -238,9 +242,6 @@ module.exports.init = function (db) {
// Initialize modules static client routes, before session!
this.initModulesClientRoutes(app);

// Initialize Express session
this.initSession(app, db);

// Initialize Modules configuration
this.initModulesConfiguration(app);

Expand Down
68 changes: 29 additions & 39 deletions config/lib/socket.io.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ var config = require('../config'),
fs = require('fs'),
http = require('http'),
https = require('https'),
cookieParser = require('cookie-parser'),
passport = require('passport'),
socketio = require('socket.io'),
session = require('express-session'),
MongoStore = require('connect-mongo')(session);
socketio = require('socket.io');

// Define the Socket.io configuration method
module.exports = function (app, db) {
Expand Down Expand Up @@ -69,49 +66,42 @@ module.exports = function (app, db) {
// Create a new Socket.io server
var io = socketio.listen(server);

// Create a MongoDB storage object
var mongoStore = new MongoStore({
mongooseConnection: db.connection,
collection: config.sessionCollection
// Configure SocketIO Authentication
require('socketio-auth')(io, {
authenticate: authenticate,
postAuthenticate: postAuthenticate,
timeout: 1000
});

// Intercept Socket.io's handshake request
io.use(function (socket, next) {
// Use the 'cookie-parser' module to parse the request cookies
cookieParser(config.sessionSecret)(socket.request, {}, function (err) {
// Get the session id from the request cookies
var sessionId = socket.request.signedCookies ? socket.request.signedCookies[config.sessionKey] : undefined;
return server;

if (!sessionId) return next(new Error('sessionId was not found in socket.request'), false);
// Handler for authenticating the SocketIO connection
function authenticate(socket, data, callback) {
// Set the Authorization header using the provided token
socket.request.headers.authorization = 'JWT ' + data.token;

// Use the mongoStorage instance to get the Express session information
mongoStore.get(sessionId, function (err, session) {
if (err) return next(err, false);
if (!session) return next(new Error('session was not found for ' + sessionId), false);
// Use Passport to populate the user details
passport.authenticate('jwt', { session: false }, function (err, user) {
if (err) {
return callback(new Error(err));
}

// Set the Socket.io session information
socket.request.session = session;
if (!user) {
return callback(new Error('User not found'));
}

// Use Passport to populate the user details
passport.initialize()(socket.request, {}, function () {
passport.session()(socket.request, {}, function () {
if (socket.request.user) {
next(null, true);
} else {
next(new Error('User is not authenticated'), false);
}
});
});
});
});
});
// Set the socket user
socket.request.user = user;

return callback(null, true);
})(socket.request, socket.request.res, callback);
}

// Add an event listener to the 'connection' event
io.on('connection', function (socket) {
// Handler for post-Authentication
function postAuthenticate(socket, data) {
// Configure the server-side Socket listeners
config.files.server.sockets.forEach(function (socketConfiguration) {
require(path.resolve(socketConfiguration))(io, socket);
});
});

return server;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
it('should send a POST request with the form input values and then locate to new object URL', inject(function (ArticlesService) {
// Set POST response
$httpBackend.expectPOST('/api/articles', sampleArticlePostData).respond(mockArticle);
$httpBackend.when('GET', '/api/users/me').respond(200, 'Fred');

// Run controller functionality
$scope.vm.save(true);
Expand All @@ -107,6 +108,7 @@
$httpBackend.expectPOST('/api/articles', sampleArticlePostData).respond(400, {
message: errorMessage
});
$httpBackend.when('GET', '/api/users/me').respond(200, 'Fred');

$scope.vm.save(true);
$httpBackend.flush();
Expand All @@ -124,6 +126,7 @@
it('should update a valid article', inject(function (ArticlesService) {
// Set PUT response
$httpBackend.expectPUT(/api\/articles\/([0-9a-fA-F]{24})$/).respond();
$httpBackend.when('GET', '/api/users/me').respond(200, 'Fred');

// Run controller functionality
$scope.vm.save(true);
Expand All @@ -140,6 +143,7 @@
$httpBackend.expectPUT(/api\/articles\/([0-9a-fA-F]{24})$/).respond(400, {
message: errorMessage
});
$httpBackend.when('GET', '/api/users/me').respond(200, 'Fred');

$scope.vm.save(true);
$httpBackend.flush();
Expand All @@ -159,6 +163,7 @@
spyOn(window, 'confirm').and.returnValue(true);

$httpBackend.expectDELETE(/api\/articles\/([0-9a-fA-F]{24})$/).respond(204);
$httpBackend.when('GET', '/api/users/me').respond(200, 'Fred');

$scope.vm.remove();
$httpBackend.flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
it('should send a GET request and return all articles', inject(function (ArticlesService) {
// Set POST response
$httpBackend.expectGET('/api/articles').respond(mockArticleList);

$httpBackend.when('GET', '/api/users/me').respond(200, 'Fred');

$httpBackend.flush();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
Authentication = _Authentication_;
ArticlesService = _ArticlesService_;

$httpBackend.whenGET('/api/users/me').respond({});

// create mock article
mockArticle = new ArticlesService({
_id: '525a8422f6d0f87f0e407a33',
Expand Down
4 changes: 4 additions & 0 deletions modules/articles/tests/client/articles.client.routes.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
ArticlesService = _ArticlesService_;
}));

afterEach(inject(function (Authentication) {
Authentication.signout();
}));

describe('Route Config', function () {
describe('Main Route', function () {
var mainstate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
spyOn($state, 'go');
}));

afterEach(inject(function (Authentication) {
Authentication.signout();
}));

describe('Instantiate', function () {
var mockArticleList;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ describe('Article Admin CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
Expand Down Expand Up @@ -119,6 +120,7 @@ describe('Article Admin CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
Expand All @@ -132,6 +134,7 @@ describe('Article Admin CRUD tests', function () {

// Update an existing article
agent.put('/api/articles/' + articleSaveRes.body._id)
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleUpdateErr, articleUpdateRes) {
Expand Down Expand Up @@ -169,6 +172,7 @@ describe('Article Admin CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(422)
.end(function (articleSaveErr, articleSaveRes) {
Expand Down Expand Up @@ -196,6 +200,7 @@ describe('Article Admin CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
Expand All @@ -206,6 +211,7 @@ describe('Article Admin CRUD tests', function () {

// Delete an existing article
agent.delete('/api/articles/' + articleSaveRes.body._id)
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleDeleteErr, articleDeleteRes) {
Expand Down Expand Up @@ -243,6 +249,7 @@ describe('Article Admin CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
Expand All @@ -253,6 +260,7 @@ describe('Article Admin CRUD tests', function () {

// Get the article
agent.get('/api/articles/' + articleSaveRes.body._id)
.set('Authorization', 'JWT ' + signinRes.body.token)
.expect(200)
.end(function (articleInfoErr, articleInfoRes) {
// Handle article error
Expand Down
7 changes: 7 additions & 0 deletions modules/articles/tests/server/article.server.routes.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ describe('Article CRUD tests', function () {
}

agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(403)
.end(function (articleSaveErr, articleSaveRes) {
Expand Down Expand Up @@ -101,6 +102,7 @@ describe('Article CRUD tests', function () {
}

agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(403)
.end(function (articleSaveErr, articleSaveRes) {
Expand Down Expand Up @@ -181,6 +183,7 @@ describe('Article CRUD tests', function () {
}

agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(403)
.end(function (articleSaveErr, articleSaveRes) {
Expand Down Expand Up @@ -252,6 +255,7 @@ describe('Article CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
Expand Down Expand Up @@ -279,6 +283,7 @@ describe('Article CRUD tests', function () {

// Get the article
agent.get('/api/articles/' + articleSaveRes.body._id)
.set('Authorization', 'JWT ' + res.body.token)
.expect(200)
.end(function (articleInfoErr, articleInfoRes) {
// Handle article error
Expand Down Expand Up @@ -359,6 +364,7 @@ describe('Article CRUD tests', function () {

// Save a new article
agent.post('/api/articles')
.set('Authorization', 'JWT ' + signinRes.body.token)
.send(article)
.expect(200)
.end(function (articleSaveErr, articleSaveRes) {
Expand All @@ -384,6 +390,7 @@ describe('Article CRUD tests', function () {

// Get the article
agent.get('/api/articles/' + articleSaveRes.body._id)
.set('Authorization', 'JWT ' + res.body.token)
.expect(200)
.end(function (articleInfoErr, articleInfoRes) {
// Handle article error
Expand Down
Loading