add tests that token is destroyed

adds the `buf` module, which helps converting between buffers and hex strings.
there were errors before, so this helped fix the tests.
This commit is contained in:
Sean McArthur 2014-06-30 11:20:53 -07:00
Родитель 52584b389e
Коммит 02977b3345
10 изменённых файлов: 52 добавлений и 44 удалений

Просмотреть файл

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const unbuf = require('buf').unbuf.hex;
const P = require('../promise');
const config = require('../config');
@ -9,21 +11,6 @@ const logger = require('../logging').getLogger('fxa.db');
const mysql = require('./mysql');
const memory = require('./memory');
function buffer(obj) {
if (Buffer.isBuffer(obj)) {
return obj;
} else if (typeof obj === 'string') {
return Buffer(obj, 'hex');
}
}
function unbuf(buf) {
if (Buffer.isBuffer(buf)) {
return buf.toString('hex');
}
return buf;
}
function preClients() {
var clients = config.get('clients');
if (clients && clients.length) {
@ -53,8 +40,6 @@ function withDriver() {
}
return p.then(function(store) {
logger.debug('connected to "%s" store', config.get('db.driver'));
store._unbuf = unbuf;
store._buf = buffer;
driver = store;
}).then(preClients).then(function() {
return driver;
@ -96,3 +81,4 @@ exports.disconnect = function disconnect() {
exports._initialClients = function() {
return preClients();
};

Просмотреть файл

@ -2,6 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const buf = require('buf').hex;
const unbuf = require('buf').unbuf.hex;
const encrypt = require('../encrypt');
const logger = require('../logging').getLogger('fxa.db.memory');
const P = require('../promise');
@ -70,11 +73,11 @@ MemoryStore.prototype = {
registerClient: function registerClient(client) {
if (client.id) {
logger.debug('registerClient: client already has ID?', client.id);
client.id = this._buf(client.id);
client.id = buf(client.id);
} else {
client.id = unique.id();
}
var hex = this._unbuf(client.id);
var hex = unbuf(client.id);
logger.debug('registerClient', client.name, hex);
client.createdAt = new Date();
this.clients[hex] = client;
@ -82,7 +85,7 @@ MemoryStore.prototype = {
return P.resolve(client);
},
getClient: function getClient(id) {
return P.resolve(this.clients[this._unbuf(id)]);
return P.resolve(this.clients[unbuf(id)]);
},
generateCode: function generateCode(clientId, userId, email, scope) {
var code = {};
@ -93,14 +96,14 @@ MemoryStore.prototype = {
code.createdAt = new Date();
var _code = unique.code();
code.code = encrypt.hash(_code);
this.codes[this._unbuf(code.code)] = code;
this.codes[unbuf(code.code)] = code;
return P.resolve(_code);
},
getCode: function getCode(code) {
return P.resolve(this.codes[this._unbuf(encrypt.hash(code))]);
return P.resolve(this.codes[unbuf(encrypt.hash(code))]);
},
removeCode: function removeCode(id) {
delete this.codes[this._unbuf(id)];
delete this.codes[unbuf(id)];
return P.resolve();
},
generateToken: function generateToken(code) {
@ -116,16 +119,16 @@ MemoryStore.prototype = {
var _token = unique.token();
var ret = clone(token);
token.token = encrypt.hash(_token);
store.tokens[store._unbuf(token.token)] = token;
store.tokens[unbuf(token.token)] = token;
ret.token = _token;
return ret;
});
},
getToken: function getToken(token) {
return P.resolve(this.tokens[this._unbuf(encrypt.hash(token))]);
return P.resolve(this.tokens[unbuf(token)]);
},
removeToken: function removeToken(id) {
delete this.tokens[this._unbuf(id)];
delete this.tokens[unbuf(id)];
return P.resolve();
}
};

Просмотреть файл

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const buf = require('buf').hex;
const mysql = require('mysql');
const encrypt = require('../encrypt');
@ -99,7 +100,7 @@ MysqlStore.prototype = {
var id;
if (client.id) {
logger.debug('registerClient: client already has ID?', client.id);
id = this._buf(client.id);
id = buf(client.id);
} else {
id = unique.id();
}
@ -127,7 +128,7 @@ MysqlStore.prototype = {
},
getClient: function getClient(_id) {
var d = P.defer();
var id = this._buf(_id);
var id = buf(_id);
this._connection.query(QUERY_CLIENT_GET, [id], function(err, rows) {
if (err) {
return d.reject(err);
@ -205,7 +206,7 @@ MysqlStore.prototype = {
getToken: function getToken(token) {
var d = P.defer();
this._connection.query(QUERY_TOKEN_FIND, [encrypt.hash(token)],
this._connection.query(QUERY_TOKEN_FIND, [buf(token)],
function(err, rows) {
if (err) {
logger.error('getToken:', err);
@ -223,7 +224,7 @@ MysqlStore.prototype = {
removeToken: function removeToken(id) {
var d = P.defer();
this._connection.query(QUERY_TOKEN_DELETE, [id], function(err) {
this._connection.query(QUERY_TOKEN_DELETE, [buf(id)], function(err) {
if (err) {
return d.reject(err);
}

Просмотреть файл

@ -4,10 +4,12 @@
const crypto = require('crypto');
const buf = require('buf').hex;
const config = require('./config');
exports.hash = function hash(value) {
var sha = crypto.createHash(config.get('encrypt.hashAlg'));
sha.update(value);
sha.update(buf(value));
return sha.digest();
};

Просмотреть файл

@ -4,6 +4,7 @@
const util = require('util');
const unbuf = require('buf').unbuf.hex;
const intel = require('intel');
function JsonFormatter(options) {
@ -33,7 +34,7 @@ JsonFormatter.prototype.format = function jsonFormat(record) {
}
} else {
for (var k in record.args[0]) {
rec[k] = record.args[0][k];
rec[k] = unbuf(record.args[0][k]);
}
}

Просмотреть файл

@ -5,16 +5,14 @@
const Joi = require('joi');
const unbuf = require('buf').unbuf.hex;
const AppError = require('../error');
const config = require('../config');
const db = require('../db');
const encrypt = require('../encrypt');
const HEX_STRING = /^[0-9a-f]+$/;
function eq(orig, unhashed) {
return orig.toString('hex') === encrypt.hash(unhashed).toString('hex');
}
module.exports = {
validate: {
payload: {
@ -29,18 +27,18 @@ module.exports = {
}
},
handler: function destroyToken(req, reply) {
var token = req.payload.token;
var secret = req.payload.client_secret;
var token = encrypt.hash(req.payload.token);
var secret = encrypt.hash(req.payload.client_secret);
db.getToken(Buffer(token, 'hex'))
db.getToken(token)
.then(function(tok) {
if (!tok) {
throw AppError.invalidToken();
}
return db.getClient(tok.clientId);
}).then(function(client) {
if (client && !eq(client.secret, secret)) {
throw AppError.incorrectSecret(client && client.id.toString('hex'));
if (client && (unbuf(client.secret) !== unbuf(secret))) {
throw AppError.incorrectSecret(client && unbuf(client.id));
}
// if client doesn't exist, but token does, then just clean up
return db.removeToken(token);

Просмотреть файл

@ -7,6 +7,7 @@ const Joi = require('joi');
const AppError = require('../error');
const config = require('../config');
const db = require('../db');
const encrypt = require('../encrypt');
const HEX_STRING = /^[0-9a-f]+$/;
@ -27,7 +28,7 @@ module.exports = {
}
},
handler: function verify(req, reply) {
db.getToken(Buffer(req.payload.token, 'hex'))
db.getToken(encrypt.hash(req.payload.token))
.then(function(token) {
if (!token) {
throw AppError.invalidToken();

4
npm-shrinkwrap.json сгенерированный
Просмотреть файл

@ -7,6 +7,10 @@
"from": "bluebird@1.2.4",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-1.2.4.tgz"
},
"buf": {
"version": "0.1.0",
"from": "buf@0.1.0"
},
"convict": {
"version": "0.4.2",
"from": "convict@0.4.2",

Просмотреть файл

@ -22,6 +22,7 @@
},
"dependencies": {
"bluebird": "1.2.4",
"buf": "0.1.0",
"convict": "0.4.2",
"hapi": "5.1.0",
"intel": "1.0.0-b2",

Просмотреть файл

@ -11,6 +11,7 @@ const nock = require('nock');
const config = require('../lib/config');
const db = require('../lib/db');
const encrypt = require('../lib/encrypt');
const P = require('../lib/promise');
const Server = require('./lib/server');
const unique = require('../lib/unique');
@ -586,30 +587,40 @@ describe('/v1', function() {
describe('/destroy', function() {
it('should destroy tokens', function() {
var token;
return newToken().then(function(res) {
token = res.result.access_token;
return Server.api.post({
url: '/destroy',
payload: {
token: res.result.access_token,
token: token,
client_secret: secret
}
});
}).then(function(res) {
assert.equal(res.statusCode, 200);
return db.getToken(encrypt.hash(token)).then(function(tok) {
assert.equal(tok, undefined);
});
});
});
it('should not allow unauthorized destruction', function() {
var token;
return newToken().then(function(res) {
token = res.result.access_token;
return Server.api.post({
url: '/destroy',
payload: {
token: res.result.access_token,
token: token,
client_secret: badSecret
}
});
}).then(function(res) {
assert.equal(res.statusCode, 400);
return db.getToken(encrypt.hash(token)).then(function(tok) {
assert(tok);
});
});
});
});