Skip to content

Instantly share code, notes, and snippets.

@ChrisRisner
Last active January 1, 2016 11:58
Show Gist options
  • Save ChrisRisner/8141068 to your computer and use it in GitHub Desktop.
Save ChrisRisner/8141068 to your computer and use it in GitHub Desktop.
JwtHelper.js
var crypto = require('crypto');
var iterations = 1000;
var bytes = 32;
exports.createSalt = function() {
return new Buffer(crypto.randomBytes(bytes)).toString('base64');
}
exports.hash = function hash(text, salt, callback) {
crypto.pbkdf2(text, salt, iterations, bytes, function(err, derivedKey){
if (err) { callback(err); }
else {
var h = new Buffer(derivedKey).toString('base64');
callback(null, h);
}
});
}
exports.zumoJwt = function zumoJwt(aud, userId, masterKey) {
function base64(input) {
return new Buffer(input, 'utf8').toString('base64');
}
function urlFriendly(b64) {
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(new RegExp("=", "g"), '');
}
function signature(input) {
var key = crypto.createHash('sha256').update(masterKey + "JWTSig").digest('binary');
var str = crypto.createHmac('sha256', key).update(input).digest('base64');
return urlFriendly(str);
}
var s1 = '{"alg":"HS256","typ":"JWT","kid":0}';
var j2 = {
"exp": new Date().setUTCDate(new Date().getUTCDate() + 4000),
"iss":"urn:microsoft:windows-azure:zumo",
"ver":1,
"aud":aud,
"uid":userId
};
var s2 = JSON.stringify(j2);
var b1 = urlFriendly(base64(s1));
var b2 = urlFriendly(base64(s2));
var b3 = signature(b1 + "." + b2);
console.log('jwt: ', [b1,b2,b3].join("."));
return [b1,b2,b3].join(".");
}
exports.slowEquals = function(a, b) {
var diff = a.length ^ b.length;
for (var i = 0; i < a.length && i < b.length; i++) {
diff |= (a[i] ^ b[i]);
}
return diff === 0;
}
var jwthelper = require('../shared/jwthelper.js');
var aud = "Custom";
exports.post = function(request, response) {
var accounts = request.service.tables.getTable('AccountData');
var item = { emailOrUserName : request.body.members.emailOrUsername,
password : request.body.members.password
};
accounts.where(function(item) {
return this.email == item.emailOrUserName || this.username == item.emailOrUserName;
},item).read({
success: function(results) {
if (results.length === 0) {
response.send(200, { Status : "FAIL", Error : "Incorrect username or password"});
}
else {
var account = results[0];
console.log(account);
jwthelper.hash(item.password, account.salt, function(err, h) {
var incoming = h;
if (jwthelper.slowEquals(incoming, account.password)) {
var userId = aud + ":" + account.id;
response.send(200, {
userId: userId,
token: jwthelper.zumoJwt(aud, userId, request.service.config.masterKey),
status: "SUCCESS",
username: account.username,
email: account.email
});
}
else {
console.error('incorrect username or password');
response.send(200, { Status : "FAIL", Error: "Incorrect username or password."});
}
});
}
}
});
};
var jwthelper = require('../shared/jwthelper.js');
var aud = "Custom";
var currentRequest;
exports.post = function(request, response) {
currentRequest = request;
var accounts = currentRequest.service.tables.getTable('AccountData');
var item = {
password : currentRequest.body.members.password,
email : currentRequest.body.members.email,
dob : currentRequest.body.members.dob,
username : '',
privacyReceive: 'Just Friends',
privacyShare: 'Just Friends'
};
if (item.password.length < 7) {
response.send(200, { Status : 'FAIL', Error: 'Invalid password (at least 7 chars required)'});
return;
}
accounts.where({ email : item.email}).read({
success: function(results) {
if (results.length > 0) {
response.send(200, { Status : 'FAIL', Error: 'This email already exists'});
return;
}
else {
console.log("Creating account data");
item.salt = jwthelper.createSalt();
jwthelper.hash(item.password, item.salt, function(err, h) {
item.password = h;
item.status = 'NewAccount';
item.createDate = new Date();
item.updateDate = new Date();
accounts.insert(item, {
success: function () {
var userId = aud + ":" + item.id;
//update our record with the user id
item.userId = userId;
accounts.update(item);
// We don't want the salt or the password going back to the client
delete item.password;
delete item.salt;
delete item.status;
item.token = jwthelper.zumoJwt(aud, userId, request.service.config.masterKey);
item.Status = 'User registered';
response.send(201, item);
}
});
});
}
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment