mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Shortened content api key lengths (#10322)
* Lowered the min length for api keys to 26 * Updated ApiKey model to use shorter secrets for content keys
This commit is contained in:
parent
dd1cf5ffc7
commit
b6152684a8
3 changed files with 34 additions and 4 deletions
|
@ -355,7 +355,7 @@ module.exports = {
|
||||||
maxlength: 191,
|
maxlength: 191,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
unique: true,
|
unique: true,
|
||||||
validations: {isLength: {min: 128, max: 128}}
|
validations: {isLength: {min: 26, max: 128}}
|
||||||
},
|
},
|
||||||
role_id: {type: 'string', maxlength: 24, nullable: true},
|
role_id: {type: 'string', maxlength: 24, nullable: true},
|
||||||
// integration_id is nullable to allow "internal" API keys that don't show in the UI
|
// integration_id is nullable to allow "internal" API keys that don't show in the UI
|
||||||
|
|
|
@ -2,14 +2,34 @@ const crypto = require('crypto');
|
||||||
const ghostBookshelf = require('./base');
|
const ghostBookshelf = require('./base');
|
||||||
const {Role} = require('./role');
|
const {Role} = require('./role');
|
||||||
|
|
||||||
const createSecret = () => crypto.randomBytes(64).toString('hex');
|
/*
|
||||||
|
* Uses birthday problem estimation to calculate chance of collision
|
||||||
|
* d = 16^26 // 26 char hex string
|
||||||
|
* n = 10,000,000 // 10 million
|
||||||
|
*
|
||||||
|
* (-n x (n-1)) / 2d
|
||||||
|
* 1 - e^
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 17
|
||||||
|
* ~= 4 x 10^
|
||||||
|
*
|
||||||
|
* ref: https://medium.freecodecamp.org/how-long-should-i-make-my-api-key-833ebf2dc26f
|
||||||
|
* ref: https://en.wikipedia.org/wiki/Birthday_problem#Approximations
|
||||||
|
*
|
||||||
|
* 26 char hex string = 13 bytes
|
||||||
|
* 512 bit JWT secret = 64 bytes
|
||||||
|
*/
|
||||||
|
const createSecret = (type) => {
|
||||||
|
const bytes = type === 'content' ? 13 : 64;
|
||||||
|
return crypto.randomBytes(bytes).toString('hex');
|
||||||
|
};
|
||||||
|
|
||||||
const ApiKey = ghostBookshelf.Model.extend({
|
const ApiKey = ghostBookshelf.Model.extend({
|
||||||
tableName: 'api_keys',
|
tableName: 'api_keys',
|
||||||
|
|
||||||
defaults() {
|
defaults() {
|
||||||
// 512bit key for HS256 JWT signing
|
const secret = createSecret(this.get('type'));
|
||||||
const secret = createSecret();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
secret
|
secret
|
||||||
|
|
|
@ -29,6 +29,16 @@ describe('Unit: models/api_key', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sets default secret for content key', function () {
|
||||||
|
const attrs = {
|
||||||
|
type: 'content'
|
||||||
|
};
|
||||||
|
|
||||||
|
return models.ApiKey.add(attrs).then((api_key) => {
|
||||||
|
api_key.get('secret').length.should.eql(26);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('sets hardcoded role for key type', function () {
|
it('sets hardcoded role for key type', function () {
|
||||||
// roles[5] = 'Admin Integration'
|
// roles[5] = 'Admin Integration'
|
||||||
const role_id = testUtils.DataGenerator.forKnex.roles[5].id;
|
const role_id = testUtils.DataGenerator.forKnex.roles[5].id;
|
||||||
|
|
Loading…
Add table
Reference in a new issue