Skip to content
This repository has been archived by the owner on Jul 12, 2020. It is now read-only.

Commit

Permalink
Add Multi Session and Session Revoke
Browse files Browse the repository at this point in the history
  • Loading branch information
gregfrasco committed Oct 23, 2017
1 parent ee86864 commit 9e5a5b9
Show file tree
Hide file tree
Showing 12 changed files with 2,671 additions and 526 deletions.
2,672 changes: 2,174 additions & 498 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@
"lout": "10.x.x",
"mongo-models": "1.x.x",
"mongodb": "2.x.x",
"uuid": "3.x.x",
"nodemailer": "4.x.x",
"nodemailer-markdown": "1.x.x",
"object-assign": "4.x.x",
"slug": "0.9.x",
"useragent": "^2.2.1",
"uuid": "3.x.x",
"vision": "4.x.x",
"visionary": "6.x.x"
},
Expand Down
48 changes: 45 additions & 3 deletions server/api/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Bcrypt = require('bcrypt');
const Boom = require('boom');
const Config = require('../../config');
const Joi = require('joi');
const Useragent = require('useragent');


const internals = {};
Expand Down Expand Up @@ -83,10 +84,20 @@ internals.applyRoutes = function (server, next) {
});
}
}, {
assign: 'session',
assign: 'existingSession',
method: function (request, reply) {

Session.create(request.pre.user._id.toString(), (err, session) => {
const userAgent = Useragent.lookup(request.headers['user-agent']);
const ip = request.info.remoteAddress;
const browser = userAgent.family;
const os = userAgent.os.toString();

Session.findOne({
userId: request.pre.user._id.toString(),
ip,
browser,
os
}, (err, session) => {

if (err) {
return reply(err);
Expand All @@ -95,11 +106,42 @@ internals.applyRoutes = function (server, next) {
return reply(session);
});
}
}, {
assign: 'validSession',
method: function (request, reply) {

const existingSession = request.pre.existingSession;

if (!existingSession) {

const userAgent = Useragent.lookup(request.headers['user-agent']);
const ip = request.info.remoteAddress;
const browser = userAgent.family;
const os = userAgent.os.toString();

Session.create(request.pre.user._id.toString(), ip, browser, os, (err, session) => {

if (err) {
return reply(err);
}

return reply(session);
});
}
else if (existingSession.revoked) {

return reply(Boom.forbidden('Session is revoked'));
}
else {

return reply(existingSession);
}
}
}]
},
handler: function (request, reply) {

const credentials = request.pre.session._id.toString() + ':' + request.pre.session.key;
const credentials = request.pre.validSession._id.toString() + ':' + request.pre.validSession.key;
const authHeader = 'Basic ' + new Buffer(credentials).toString('base64');

reply({
Expand Down
81 changes: 81 additions & 0 deletions server/api/sessions.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,87 @@ internals.applyRoutes = function (server, next) {
});


server.route({
method: 'PUT',
path: '/sessions/my/{id}',
config: {
auth: {
strategy: 'simple',
scope: 'account'
},
validate: {
payload: {
revoked: Joi.boolean().required()
}
}
},
handler: function (request, reply) {

const id = request.auth.credentials.roles.account._id.toString();
const update = {
$set: {
revoked: request.payload.revoked
}
};

Session.findByIdAndUpdate(id, update, (err, session) => {

if (err) {
return reply(err);
}

if (!session) {
return reply(Boom.notFound('Document not found.'));
}

reply(session);
});
}
});


server.route({
method: 'PUT',
path: '/sessions/{id}',
config: {
auth: {
strategy: 'simple',
scope: 'admin'
},
validate: {
payload: {
revoked: Joi.boolean().required()
}
},
pre: [
AuthPlugin.preware.ensureAdminGroup('root')
]
},
handler: function (request, reply) {

const id = request.params.id;
const update = {
$set: {
revoked: request.payload.revoked
}
};

Session.findByIdAndUpdate(id, update, (err, session) => {

if (err) {
return reply(err);
}

if (!session) {
return reply(Boom.notFound('Document not found.'));
}

reply(session);
});
}
});


server.route({
method: 'DELETE',
path: '/sessions/{id}',
Expand Down
9 changes: 7 additions & 2 deletions server/api/signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const Async = require('async');
const Boom = require('boom');
const Config = require('../../config');
const Joi = require('joi');

const Useragent = require('useragent');

const internals = {};

Expand Down Expand Up @@ -142,7 +142,12 @@ internals.applyRoutes = function (server, next) {
}],
session: ['linkUser', 'linkAccount', function (results, done) {

Session.create(results.user._id.toString(), done);
const userAgent = Useragent.lookup(request.headers['user-agent']);
const ip = request.info.remoteAddress;
const browser = userAgent.family;
const os = userAgent.os.toString();

Session.create(results.user._id.toString(), ip, browser, os, done);
}]
}, (err, results) => {

Expand Down
27 changes: 24 additions & 3 deletions server/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@ internals.applyStrategy = function (server, next) {

Session.findByCredentials(username, password, done);
},
user: ['session', function (results, done) {
sessionRevoked: ['session', function (results, done) {

if (!results.session) {
if (results.session && results.session.revoked) {
return done(Boom.forbidden('Session has been revoked'));
}

return done(null, results.session);
}],
user: ['sessionRevoked', function (results, done) {

if (!results.sessionRevoked) {
return done();
}

User.findById(results.session.userId, done);
User.findById(results.sessionRevoked.userId, done);
}],
roles: ['user', function (results, done) {

Expand All @@ -42,6 +50,19 @@ internals.applyStrategy = function (server, next) {
}

done(null, Object.keys(results.user.roles));
}],
updateSession: ['scope', function (results, done) {

if (!results.roles) {
return done();
}

const update = {
$set: {
lastLogin: new Date()
}
};
Session.findByIdAndUpdate(results.sessionRevoked._id.toString(),update, done);
}]
}, (err, results) => {

Expand Down
25 changes: 13 additions & 12 deletions server/models/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Session extends MongoModels {
});
}

static create(userId, callback) {
static create(userId, ip, browser, os, callback) {

const self = this;

Expand All @@ -44,19 +44,15 @@ class Session extends MongoModels {
const document = {
userId,
key: results.keyHash.hash,
time: new Date()
time: new Date(),
lastLogin: new Date(),
ip,
browser,
os,
revoked: false
};

self.insertOne(document, done);
}],
clean: ['newSession', function (results, done) {

const query = {
userId,
key: { $ne: results.keyHash.hash }
};

self.deleteOne(query, done);
}]
}, (err, results) => {

Expand Down Expand Up @@ -111,7 +107,12 @@ Session.schema = Joi.object().keys({
_id: Joi.object(),
userId: Joi.string().required(),
key: Joi.string().required(),
time: Joi.date().required()
time: Joi.date().required(),
lastLogin: Joi.date().required(),
ip: Joi.string().required(),
browser: Joi.string().required(),
os: Joi.string().required(),
revoked: Joi.boolean().required()
});


Expand Down
Loading

0 comments on commit 9e5a5b9

Please sign in to comment.