r-oauth2
Version:
A RethinkDB and Express implementation of OAuth2
198 lines (194 loc) • 7.11 kB
JavaScript
var r, db, oauthTable, tokenTable, expiry, useBcrypt;
var crypto = require('crypto-js');
var async = require('async');
var bcrypt = require('bcrypt');
process.env.BLUEBIRD_DEBUG = 0;
module.exports = {
init: function(config) {
var rCfg = {};
if (config) {
if (config.db) { db = config.db } else { db = "oauth2" };
if (config.oauthTable) { oauthTable = config.oauthTable } else { oauthTable = "users" };
if (config.tokenTable) { tokenTable = config.tokenTable } else { tokenTable = "token" };
if (config.expiry) { expiry = config.expiry} else { expiry = 360000 }
if (config.r) { r = config.r } else { r = require('rethinkdbdash')() }
if (config.bcrypt) { useBcrypt = config.bcrypt } else { useBcrypt = false }
} else {
db = "oauth2";
oauthTable = "users";
tokenTable = "token";
expiry = 360000;
useBcrypt = false;
r = require('rethinkdbdash')();
}
},
generateClient: function(clientId, clientSecret, grantType) {
return function(req,res,next) {
var client = {};
var unique = false;
async.whilst(
function() {
return unique == false;
},
function(callback) {
var random = Math.random().toString();
if (useBcrypt == true) {
if (!req.body.clientSecret) {
return res.status(400).send({
"msg": "Must supply a client secret."
})
}
client.clientId = req.body.clientId
var random = Math.random().toString();
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync(req.body.clientSecret, salt);
client.clientSecret = hash;
unique = true;
callback(null, unique);
} else {
client.clientId = clientId || crypto.HmacSHA3('clientId', random).toString().substr(0,50);
client.clientSecret = crypto.HmacSHA3('clientSecret', random).toString().substr(0,50);
}
r.db(db).table(oauthTable).filter(client).then(function(result) {
console.log(result.length);
if (result.length > 0) {
unique = false;
callback(null, unique)
} else {
unique = true;
callback(null, unique)
}
})
},
function(err) {
var grantType = req.body.grantType;
client.grantType = grantType;
r.db(db).table(oauthTable).insert(client).then(function() {
res.send(client);
})
}
)
}
},
generateToken: function() {
return function(req,res,next) {
var obj = req.body.client;
r.db(db).table(oauthTable).filter({
'clientId': obj.clientId
}).then(function(result) {
if (result.length > 0) {
if (useBcrypt == true) {
var validate = bcrypt.compareSync(obj.clientSecret, result[0].clientSecret);
if (validate == false) {
console.log("Test");
return res.status(403).send({ 'msg': 'Invalid permissions' });
}
} else if (useBcrypt == false && obj.clientSecret != result[0].clientSecret && obj.grantType != result[0].grantType) {
return res.status(403).send({ 'msg': 'Invalid permissions' });
}
var session = {};
session.clientId = obj.clientId;
session.grantType = obj.grantType;
session.expiry = new Number(new Date()) + expiry;
var unique = false;
async.whilst(
function() {
return unique == false;
},
function(callback) {
var random = Math.random().toString();
session.accessToken = crypto.HmacSHA3('accessToken', random).toString().substr(0,30);
var random = Math.random().toString();
session.refreshToken = crypto.HmacSHA3('refreshToken', random).toString().substr(0,30);
r.db(db).table(tokenTable).filter({
'accessToken': session.accessToken,
'refreshToken': session.refreshToken
}).then(function(result) {
if (result.length > 0) {
unique = false;
callback(null, unique)
} else {
unique = true;
callback(null, unique)
}
})
},
function(err) {
if (obj.store) {
session.store = obj.store;
}
r.db(db).table(tokenTable).insert(session).then(function() {
res.send({
'accessToken': session.accessToken,
'refreshToken': session.refreshToken,
'expiry': session.expiry
});
})
}
)
} else {
res.status(403).send({ 'msg': 'No document with that id found.' })
}
})
}
},
refreshToken: function() {
return function(req,res,next) {
var refreshToken = req.body.refreshToken;
r.db(db).table(tokenTable).filter({
refreshToken: refreshToken
}).then(function(result) {
if (result.length > 0) {
var session = result[0];
var random = Math.random().toString();
session.accessToken = crypto.HmacSHA3('accessToken', random).toString().substr(0,30);
var random = Math.random().toString();
session.refreshToken = crypto.HmacSHA3('refreshToken', random).toString().substr(0,30);
session.expiry = new Number(new Date()) + expiry;
r.db(db).table(oauthTable).insert(session).then(function() {
res.send({
'accessToken': session.accessToken,
'refreshToken': session.refreshToken,
'expiry': session.expiry
})
})
} else {
res.send({
'msg': 'Invalid refresh token.'
})
}
});
}
},
authenticate: function() {
return function(req,res,next) {
var accessToken = req.headers.authorization || req.query.accessToken;
if (!accessToken) {
return res.status(403).send({ message: 'No token provided.' })
}
if (accessToken.indexOf('Bearer') !== -1) {
accessToken = accessToken.replace('Bearer ', '');
}
r.db(db).table(tokenTable).filter({
accessToken: accessToken
}).then(function(result) {
if (result.length > 0) {
var session = result[0];
var expiryDate = session.expiry;
if (expiryDate > Number(new Date())) {
if (session.store) {
req.store = session.store
}
req.grantType = session.grantType;
req.clientId = session.clientId;
next();
} else {
return res.status(403).send({ msg: 'Token expired.' })
}
} else {
return res.status(403).send({ msg: 'Resource Forbidden.' })
}
})
}
}
}