Permalink
Browse files

upgrade hapi and hawk; have PUT payload return timestamp

  • Loading branch information...
1 parent b41b70a commit 56ec355e9175c1cf48929ae78fb4ebe9347cb0d2 @zaach zaach committed Jan 17, 2013
View
10 bin/api
@@ -28,7 +28,7 @@ function credentialsFunc(id, callback) {
var credentials = {
id: id,
key: new Buffer(key, 'base64'),
- algorithm: 'hmac-sha-256',
+ algorithm: 'sha256',
user: id
};
@@ -41,7 +41,7 @@ options.auth.getCredentialsFunc = credentialsFunc;
// modify default error format
options.format = {
error: function (result) {
- Hapi.Log.event(['error'], result.message);
+ console.error('Error: ', result);
return {
code: result.code,
payload: { success: false, errorCode: result.code, errorMessage: result.message },
@@ -54,8 +54,10 @@ options.format = {
var bindTo = config.process.api;
var server = new Hapi.Server(bindTo.host, bindTo.port, options);
-// don't require authorization for docs (may change after hapi 0.9.2)
-server._routes['get'][0].config.auth = config.hapi.docs.auth;
+if (config.hapi.docs) {
+ server.addRoute({ method: 'GET', path: '/docs', handler: { docs: true }, auth: { mode: 'none' } });
+}
+
console.log("api starting up");
View
@@ -214,12 +214,20 @@ var GombotCrypto = (function() {
url.port = (url.scheme === 'https' ? '443' : '80');
}
+ var hash = null;
+ if (args.payload) {
+ var bitArray = sjcl.hash.sha256.hash(args.payload);
+ hash = sjcl.codec.hex.fromBits(bitArray);
+ }
+
setTimeout(function() {
if (typeof Hawk === 'undefined') {
var hmac = new sjcl.misc.hmac(keyBits);
- var body =
+ var body = 'hawk.1.header\n' +
// string representation of seconds since epoch
args.date.toString() + "\n" +
+ // random nonce
+ args.nonce + '\n' +
// normalized method
args.method + '\n' +
// path
@@ -228,19 +236,26 @@ var GombotCrypto = (function() {
url.host + '\n' +
// port
url.port + '\n' +
- // random nonce
- args.nonce + '\n';
+ // hash of body
+ (hash || '') + '\n' +
+ // extra app data
+ (args.ext || '') + '\n';
var mac = sjcl.codec.base64.fromBits(hmac.mac(body));
- var header = 'Hawk id="' + args.email + '", ts="' + args.date + (args.nonce ? '", ext="' + args.nonce : '') + '", mac="' + mac + '"';
+ var header = 'Hawk id="' + args.email +
+ '", ts="' + args.date +
+ '", nonce="' + args.nonce +
+ (hash ? '", hash="' + hash : '') +
+ (args.ext ? '", ext="' + args.ext : '') +
+ '", mac="' + mac + '"';
var headers = {
Authorization: header
};
} else {
var credentials = {
id: args.email,
key: new Buffer(args.keys.authKey, 'hex'),
- algorithm: 'hmac-sha-256'
+ algorithm: 'sha256'
};
var headers = {
View
@@ -21,11 +21,7 @@ var config = module.exports = {
},
hapi: {
name: "Gombot API Server",
- docs: {
- auth: {
- mode: 'none'
- }
- },
+ docs: true,
auth: {
scheme: 'hawk',
hostHeaderName: process.env.HOST_HEADER || 'X-Forwarded-Host'
View
@@ -2,7 +2,8 @@ var crypto = require('crypto'),
Hapi = require('hapi');
var N = Hapi.Types.Number,
- S = Hapi.Types.String;
+ S = Hapi.Types.String,
+ B = Hapi.Types.Boolean;
module.exports = {
method: 'GET',
@@ -13,8 +14,11 @@ module.exports = {
},
description: 'Get "context" for subsequent operations',
response: {
- server_time: N(),
- entropy: S()
+ schema: {
+ success: B(),
+ server_time: N(),
+ entropy: S()
+ }
}
}
};
@@ -24,7 +28,8 @@ function handler(request) {
if (err) return request.reply(Hapi.Error.internal("error attaining entropy"));
request.reply({
server_time: Math.round((new Date()).getTime() / 1000),
- entropy: bytes.toString('base64')
+ entropy: bytes.toString('base64'),
+ success: true
});
});
};
View
@@ -30,9 +30,11 @@ module.exports = [
config: {
description: 'Retreive user credentials',
response: {
- success: B(),
- payload: S().required(),
- updated: N().required()
+ schema: {
+ success: B(),
+ payload: S().required(),
+ updated: N().required()
+ }
}
}
}
@@ -41,11 +43,12 @@ module.exports = [
function put(request) {
var id = request.session.id;
var payload = request.payload.payload;
- console.log('storing payload', payload);
- db.storePayload(id, payload, function(err) {
+
+ db.storePayload(id, payload, function(err, timestamp) {
if (err) return request.reply(Hapi.Error.internal("Could not store payload: " + err));
request.reply({
- success: true
+ success: true,
+ updated: timestamp
});
});
}
@@ -14,8 +14,10 @@ module.exports = {
config: {
description: 'Retreive last update time of user credentials',
response: {
- success: B(),
- updated: N().required()
+ schema: {
+ success: B(),
+ updated: N().required()
+ }
}
}
};
View
@@ -11,7 +11,9 @@ module.exports = {
config: {
description: 'Check authorization status',
response: {
- success: B()
+ schema: {
+ success: B()
+ }
}
}
};
View
@@ -58,10 +58,11 @@ module.exports = {
return this;
},
storePayload: function(id, payload, cb) {
- db.set(id + '-payload', {payload: payload, timestamp: +new Date},
+ var time = +new Date;
+ db.set(id + '-payload', {payload: payload, timestamp: time},
function (err, meta) {
if (err) cb(err);
- else cb(null);
+ else cb(null, time);
});
return this;
},
View
@@ -44,9 +44,10 @@ module.exports = {
return this;
},
storePayload: function(id, payload, cb) {
+ var timestamp = +new Date;
setTimeout(function() {
- db[id + '-payload'] = {payload: payload, timestamp: +new Date};
- cb(null);
+ db[id + '-payload'] = { payload: payload, timestamp: timestamp };
+ cb(null, timestamp);
}, 0);
return this;
},
View
@@ -4,14 +4,14 @@
"version": "0.0.1",
"private": true,
"dependencies": {
- "hapi": "0.9.2",
+ "hapi": "0.11.3",
"walkdir": "0.0.5",
"express": "3.0.2",
"nunjucks": "0.1.5",
"irc": "0.3.3",
- "awsbox": "0.3.3",
+ "awsbox": "0.3.5",
"temp": "0.4.0",
- "hawk": "0.0.6"
+ "hawk": "0.5.3"
},
"optionalDependencies": {
"couchbase": "0.0.7"
View
@@ -26,6 +26,7 @@ describe("/api/v1/context", function() {
should.exist(r.session_context);
(r.server_time).should.be.a('number');
(r.entropy).should.be.a('string');
+ (r.success).should.be.a('boolean');
done();
});
});
View
@@ -16,12 +16,15 @@ describe('the servers', function() {
should.exist(r);
servers = r;
client = new Client('http://' + servers.host + ':' + servers.port + '/api');
- done();
+ client.context({}, function (err) {
+ done();
+ });
});
});
});
function createAccount(email, pass, cb) {
+ console.error('creating account');
client.account({
email: email,
pass: pass
@@ -33,24 +36,25 @@ function createAccount(email, pass, cb) {
describe("/api/v1/payload", function() {
it ('should store payload', function(done) {
- createAccount(test_user, test_pass, function() {
+ createAccount(test_user, test_pass, function(err) {
try {
client.storePayload({
payload: 'foo'
}, function(err, r) {
should.not.exist(err);
should.exist(r);
- done();
+ should.exist(r.updated);
+ return done();
});
} catch (e) {
- done(e);
+ return done(e);
}
+ //done(err);
});
});
it ('should get payload', function(done) {
try {
client.getPayload({}, function(err, r) {
- console.error('??????', r);
should.not.exist(err);
should.exist(r);
should.exist(r.updated);
View
@@ -80,7 +80,7 @@ describe('GumbotCrypto.sign', function() {
should.not.exist(err);
should.exist(rez);
(rez.Authorization).should.be.a('string');
- (rez.Authorization).should.equal('Hawk id="bar", ts="1352177818", ext="one time only please", mac="6b+dMvKSWdAD0hFHR/Ik3MzkIS6mPdzRc31DGNM8dbI="');
+ (rez.Authorization).should.equal('Hawk id="bar", ts="1352177818", nonce="one time only please", hash="2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881", mac="hXcx942Qj1tazZiKlw8VZ+fa0jUl4wFavD6dBPNLQvc="');
done();
});
});

0 comments on commit 56ec355

Please sign in to comment.