-
-
Save frankzwang/8d7e090bae23808a1c68 to your computer and use it in GitHub Desktop.
JwtHelper.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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."}); | |
} | |
}); | |
} | |
} | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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