mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Added JWT authentication for non-versioned API
refs https://github.com/TryGhost/Toolbox/issues/169 - As Ghost prepares to drop API versioning in future major release it the authentication mechanism should take into account non-versioned token audience support. The audience for non-versioned api requests would be limited to "admin" rather than "canary/admin"
This commit is contained in:
parent
6b730cf201
commit
cd1183c9d8
2 changed files with 40 additions and 5 deletions
|
@ -3,6 +3,7 @@ const url = require('url');
|
|||
const models = require('../../../models');
|
||||
const errors = require('@tryghost/errors');
|
||||
const limitService = require('../../../services/limits');
|
||||
const config = require('../../../../shared/config');
|
||||
const tpl = require('@tryghost/tpl');
|
||||
const _ = require('lodash');
|
||||
|
||||
|
@ -139,12 +140,20 @@ const authenticateWithToken = async (req, res, next, {token, JWT_OPTIONS}) => {
|
|||
const secret = Buffer.from(apiKey.get('secret'), 'hex');
|
||||
|
||||
const {pathname} = url.parse(req.originalUrl);
|
||||
const [hasMatch, version = 'v4', api = 'admin'] = pathname.match(/ghost\/api\/([^/]+)\/([^/]+)\/(.+)*/); // eslint-disable-line no-unused-vars
|
||||
const [hasMatch, version, api] = pathname.match(/ghost\/api\/([^/]+)\/([^/]+)\/(.+)*/); // eslint-disable-line no-unused-vars
|
||||
|
||||
// ensure the token was meant for this api version
|
||||
const options = Object.assign({
|
||||
audience: new RegExp(`\/?${version}\/${api}\/?$`) // eslint-disable-line no-useless-escape
|
||||
}, JWT_OPTIONS);
|
||||
// ensure the token was meant for this api
|
||||
let options;
|
||||
if (!config.get('api:versions:all').includes(version)) {
|
||||
// CASE: non-versioned api request
|
||||
options = Object.assign({
|
||||
audience: new RegExp(`\/?${version}\/?$`) // eslint-disable-line no-useless-escape
|
||||
}, JWT_OPTIONS);
|
||||
} else {
|
||||
options = Object.assign({
|
||||
audience: new RegExp(`\/?${version}\/${api}\/?$`) // eslint-disable-line no-useless-escape
|
||||
}, JWT_OPTIONS);
|
||||
}
|
||||
|
||||
try {
|
||||
jwt.verify(token, secret, options);
|
||||
|
|
|
@ -7,6 +7,7 @@ const models = require('../../../../../../core/server/models');
|
|||
|
||||
describe('Admin API Key Auth', function () {
|
||||
const ADMIN_API_URL = '/ghost/api/canary/admin/';
|
||||
const ADMIN_API_URL_NON_VERSIONED = '/ghost/api/admin/';
|
||||
|
||||
before(models.init);
|
||||
|
||||
|
@ -56,6 +57,31 @@ describe('Admin API Key Auth', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should authenticate known+valid non-versioned API key', function (done) {
|
||||
const token = jwt.sign({
|
||||
}, this.secret, {
|
||||
keyid: this.fakeApiKey.id,
|
||||
algorithm: 'HS256',
|
||||
expiresIn: '5m',
|
||||
audience: '/admin/',
|
||||
issuer: this.fakeApiKey.id
|
||||
});
|
||||
|
||||
const req = {
|
||||
originalUrl: `${ADMIN_API_URL_NON_VERSIONED}session/`,
|
||||
headers: {
|
||||
authorization: `Ghost ${token}`
|
||||
}
|
||||
};
|
||||
const res = {};
|
||||
|
||||
apiKeyAuth.admin.authenticate(req, res, (err) => {
|
||||
should.not.exist(err);
|
||||
req.api_key.should.eql(this.fakeApiKey);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('shouldn\'t authenticate with missing Ghost token', function (done) {
|
||||
const token = '';
|
||||
const req = {
|
||||
|
|
Loading…
Add table
Reference in a new issue