Skip to content
Browse files

Begun implementing WSSE authentication

  • Loading branch information...
1 parent 4af844b commit 4afec1e2c5c563b2ded2f1e32930b77ae059d829 @GothAck committed Mar 31, 2012
Showing with 68 additions and 2 deletions.
  1. +38 −2 app/models/account.js
  2. +30 −0 lib/filters.js
View
40 app/models/account.js
@@ -3,7 +3,8 @@ var Schema = mongoose.Schema;
var Email = mongoose.SchemaTypes.Email;
var bcrypt = require('bcrypt')
- , crypto = require('crypto');
+ , crypto = require('crypto')
+ , date = require('date');
var AccountSchema = new Schema({
// eMail address
@@ -28,7 +29,9 @@ var AccountSchema = new Schema({
new: {},
edit: {}
} }
- }
+ },
+
+ api_key: { type: String }
});
AccountSchema.virtual('password', {forms_type: 'password', forms_required: true, forms_confirm: true, forms: {
@@ -55,6 +58,21 @@ AccountSchema.method('checkPassword', function (password, callback) {
bcrypt.compare(password, this.hash, callback);
});
+AccountSchema.method('checkToken', function (nonce, created, digest, callback) {
+ if (! this.api_key)
+ return callback('No API key on account, please contact us!');
+ created = Date.ISO(created);
+ if (!created)
+ return callback('Invalid date');
+ if ( ( ((new Date()) - created) / 1000/60) > 5)
+ return callback('Digest too old');
+ var shasum = crypto.createHash('sha256');
+ shasum.update(nonce + created.toISOString() + this.api_key);
+ if (digest !== shasum.digest('base64'))
+ return callback('Invalid digest');
+ callback(null, true);
+});
+
AccountSchema.virtual('confirmation_hash').get(function () {
if (this.confirmed) return null;
var shasum = crypto.createHash('sha1');
@@ -87,4 +105,22 @@ AccountSchema.static('authenticate', function (email, password, callback) {
});
});
+AccountSchema.static('authenticateToken', function(email, nonce, created, digest, callback) {
+ this.findOne({ email: email}, function(err, user) {
+ if (err)
+ return callback(err);
+ if (!user)
+ return callback(null, false);
+ if (!user.confirmed)
+ return callback(null, false);
+ user.checkToken(nonce, created, digest, function (err, authed) {
+ if (err)
+ return callback(err);
+ if (!authed)
+ return callback(null, false);
+ return callback(null, user);
+ });
+ });
+});
+
module.exports = mongoose.model('Account', AccountSchema);
View
30 lib/filters.js
@@ -1,3 +1,5 @@
+var Account = require('../app/models/account');
+
/*
* Model -> form converstion
*/
@@ -62,3 +64,31 @@ module.exports.notAuth = function (next) {
}
next();
}
+
+reWsse = /^UsernameToken.*?Username=\"(.*?)\",.*?PasswordDigest=\"(.*?)\",.*?Nonce=\"(.*?)\",.*?Created=\"(.*?)\"/
+// TODO: Stop duplicate digests!
+module.exports.authApiToken = function (next) {
+ var self = this
+ , auth_header = this.req.header('Authorization')
+ , wsse_header = this.req.header('X-WSSE')
+ , email, nonce, created, digest;
+ if (auth_header !== 'WSSE profile="UsernameToken"')
+ return next('Invalid Authorization header');
+ var match;
+ if (!(match = reWsse.exec(wsse_header)))
+ return next('Invalid X-WSSE Header');
+ email = match[1];
+ digest = match[2];
+ nonce = match[3];
+ created = match[4];
+ if (!(email && nonce && created && digest))
+ return next('Need email, nonce, created, digest!');
+ Account.authenticateToken (email, nonce, created, digest, function (err, authed) {
+ if (err)
+ return callback(err);
+ if (!user)
+ return callback('Not authenticated');
+ self.user = user;
+ next();
+ });
+}

0 comments on commit 4afec1e

Please sign in to comment.
Something went wrong with that request. Please try again.