diff --git a/core/server/services/auth/authenticate.js b/core/server/services/auth/authenticate.js index 2592c3cdc8..c189dbb762 100644 --- a/core/server/services/auth/authenticate.js +++ b/core/server/services/auth/authenticate.js @@ -1,10 +1,10 @@ -var passport = require('passport'), - authUtils = require('./utils'), - models = require('../../models'), - common = require('../../lib/common'), - authenticate; +const passport = require('passport'); +const authUtils = require('./utils'); +const models = require('../../models'); +const common = require('../../lib/common'); +const session = require('./session'); -authenticate = { +const authenticate = { // ### Authenticate Client Middleware authenticateClient: function authenticateClient(req, res, next) { /** @@ -98,7 +98,9 @@ authenticate = { })); } )(req, res, next); - } + }, + + authenticateAdminAPI: [session.safeGetSession, session.getUser] }; module.exports = authenticate; diff --git a/core/server/services/auth/authorize.js b/core/server/services/auth/authorize.js index df4259b421..0238e2102c 100644 --- a/core/server/services/auth/authorize.js +++ b/core/server/services/auth/authorize.js @@ -1,8 +1,8 @@ -var labs = require('../labs'), - common = require('../../lib/common'), - authorize; +const labs = require('../labs'); +const session = require('./session'); +const common = require('../../lib/common'); -authorize = { +const authorize = { // Workaround for missing permissions // TODO: rework when https://github.com/TryGhost/Ghost/issues/3911 is done requiresAuthorizedUser: function requiresAuthorizedUser(req, res, next) { @@ -35,7 +35,9 @@ authorize = { return next(); }; - } + }, + + authorizeAdminAPI: [session.ensureUser] }; module.exports = authorize; diff --git a/core/server/web/api/v2/admin/middleware.js b/core/server/web/api/v2/admin/middleware.js index 93a106e3dc..7fbf4c1972 100644 --- a/core/server/web/api/v2/admin/middleware.js +++ b/core/server/web/api/v2/admin/middleware.js @@ -4,10 +4,9 @@ const shared = require('../../../shared'); /** * Authentication for private endpoints */ -module.exports.authenticatePrivate = [ - auth.authenticate.authenticateClient, - auth.authenticate.authenticateUser, - auth.authorize.requiresAuthorizedUser, +module.exports.authAdminAPI = [ + auth.authenticate.authenticateAdminAPI, + auth.authorize.authorizeAdminAPI, shared.middlewares.api.cors, shared.middlewares.urlRedirects.adminRedirect, shared.middlewares.prettyUrls diff --git a/core/server/web/api/v2/admin/routes.js b/core/server/web/api/v2/admin/routes.js index 33677feee9..4525e0a255 100644 --- a/core/server/web/api/v2/admin/routes.js +++ b/core/server/web/api/v2/admin/routes.js @@ -2,6 +2,7 @@ const express = require('express'); const os = require('os'); const multer = require('multer'); const api = require('../../../../api'); +const apiv2 = require('../../../../api/v2'); const mw = require('./middleware'); const auth = require('../../../../services/auth'); @@ -22,16 +23,16 @@ module.exports = function apiRoutes() { // ## Configuration router.get('/configuration', api.http(api.configuration.read)); - router.get('/configuration/:key', mw.authenticatePrivate, api.http(api.configuration.read)); + router.get('/configuration/:key', mw.authAdminAPI, api.http(api.configuration.read)); // ## Posts - router.get('/posts', mw.authenticatePrivate, api.http(api.posts.browse)); + router.get('/posts', mw.authAdminAPI, api.http(api.posts.browse)); - router.post('/posts', mw.authenticatePrivate, api.http(api.posts.add)); - router.get('/posts/:id', mw.authenticatePrivate, api.http(api.posts.read)); - router.get('/posts/slug/:slug', mw.authenticatePrivate, api.http(api.posts.read)); - router.put('/posts/:id', mw.authenticatePrivate, api.http(api.posts.edit)); - router.del('/posts/:id', mw.authenticatePrivate, api.http(api.posts.destroy)); + router.post('/posts', mw.authAdminAPI, api.http(api.posts.add)); + router.get('/posts/:id', mw.authAdminAPI, api.http(api.posts.read)); + router.get('/posts/slug/:slug', mw.authAdminAPI, api.http(api.posts.read)); + router.put('/posts/:id', mw.authAdminAPI, api.http(api.posts.edit)); + router.del('/posts/:id', mw.authAdminAPI, api.http(api.posts.destroy)); // ## Schedules router.put('/schedules/posts/:id', [ @@ -40,110 +41,116 @@ module.exports = function apiRoutes() { ], api.http(api.schedules.publishPost)); // ## Settings - router.get('/settings/routes/yaml', mw.authenticatePrivate, api.http(api.settings.download)); + router.get('/settings/routes/yaml', mw.authAdminAPI, api.http(api.settings.download)); router.post('/settings/routes/yaml', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('routes'), shared.middlewares.validation.upload({type: 'routes'}), api.http(api.settings.upload) ); - router.get('/settings', mw.authenticatePrivate, api.http(api.settings.browse)); - router.get('/settings/:key', mw.authenticatePrivate, api.http(api.settings.read)); - router.put('/settings', mw.authenticatePrivate, api.http(api.settings.edit)); + router.get('/settings', mw.authAdminAPI, api.http(api.settings.browse)); + router.get('/settings/:key', mw.authAdminAPI, api.http(api.settings.read)); + router.put('/settings', mw.authAdminAPI, api.http(api.settings.edit)); // ## Users - router.get('/users', mw.authenticatePrivate, api.http(api.users.browse)); - router.get('/users/:id', mw.authenticatePrivate, api.http(api.users.read)); - router.get('/users/slug/:slug', mw.authenticatePrivate, api.http(api.users.read)); + router.get('/users', mw.authAdminAPI, api.http(api.users.browse)); + router.get('/users/:id', mw.authAdminAPI, api.http(api.users.read)); + router.get('/users/slug/:slug', mw.authAdminAPI, api.http(api.users.read)); // NOTE: We don't expose any email addresses via the public api. - router.get('/users/email/:email', mw.authenticatePrivate, api.http(api.users.read)); + router.get('/users/email/:email', mw.authAdminAPI, api.http(api.users.read)); - router.put('/users/password', mw.authenticatePrivate, api.http(api.users.changePassword)); - router.put('/users/owner', mw.authenticatePrivate, api.http(api.users.transferOwnership)); - router.put('/users/:id', mw.authenticatePrivate, api.http(api.users.edit)); - router.del('/users/:id', mw.authenticatePrivate, api.http(api.users.destroy)); + router.put('/users/password', mw.authAdminAPI, api.http(api.users.changePassword)); + router.put('/users/owner', mw.authAdminAPI, api.http(api.users.transferOwnership)); + router.put('/users/:id', mw.authAdminAPI, api.http(api.users.edit)); + router.del('/users/:id', mw.authAdminAPI, api.http(api.users.destroy)); // ## Tags - router.get('/tags', mw.authenticatePrivate, api.http(api.tags.browse)); - router.get('/tags/:id', mw.authenticatePrivate, api.http(api.tags.read)); - router.get('/tags/slug/:slug', mw.authenticatePrivate, api.http(api.tags.read)); - router.post('/tags', mw.authenticatePrivate, api.http(api.tags.add)); - router.put('/tags/:id', mw.authenticatePrivate, api.http(api.tags.edit)); - router.del('/tags/:id', mw.authenticatePrivate, api.http(api.tags.destroy)); + router.get('/tags', mw.authAdminAPI, api.http(api.tags.browse)); + router.get('/tags/:id', mw.authAdminAPI, api.http(api.tags.read)); + router.get('/tags/slug/:slug', mw.authAdminAPI, api.http(api.tags.read)); + router.post('/tags', mw.authAdminAPI, api.http(api.tags.add)); + router.put('/tags/:id', mw.authAdminAPI, api.http(api.tags.edit)); + router.del('/tags/:id', mw.authAdminAPI, api.http(api.tags.destroy)); // ## Subscribers - router.get('/subscribers', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.browse)); - router.get('/subscribers/csv', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.exportCSV)); + router.get('/subscribers', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.browse)); + router.get('/subscribers/csv', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.exportCSV)); router.post('/subscribers/csv', shared.middlewares.labs.subscribers, - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('subscribersfile'), shared.middlewares.validation.upload({type: 'subscribers'}), api.http(api.subscribers.importCSV) ); - router.get('/subscribers/:id', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.read)); - router.get('/subscribers/email/:email', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.read)); - router.post('/subscribers', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.add)); - router.put('/subscribers/:id', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.edit)); - router.del('/subscribers/:id', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.destroy)); - router.del('/subscribers/email/:email', shared.middlewares.labs.subscribers, mw.authenticatePrivate, api.http(api.subscribers.destroy)); + router.get('/subscribers/:id', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.read)); + router.get('/subscribers/email/:email', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.read)); + router.post('/subscribers', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.add)); + router.put('/subscribers/:id', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.edit)); + router.del('/subscribers/:id', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.destroy)); + router.del('/subscribers/email/:email', shared.middlewares.labs.subscribers, mw.authAdminAPI, api.http(api.subscribers.destroy)); // ## Roles - router.get('/roles/', mw.authenticatePrivate, api.http(api.roles.browse)); + router.get('/roles/', mw.authAdminAPI, api.http(api.roles.browse)); // ## Clients router.get('/clients/slug/:slug', api.http(api.clients.read)); // ## Slugs - router.get('/slugs/:type/:name', mw.authenticatePrivate, api.http(api.slugs.generate)); + router.get('/slugs/:type/:name', mw.authAdminAPI, api.http(api.slugs.generate)); // ## Themes - router.get('/themes/', mw.authenticatePrivate, api.http(api.themes.browse)); + router.get('/themes/', mw.authAdminAPI, api.http(api.themes.browse)); router.get('/themes/:name/download', - mw.authenticatePrivate, + mw.authAdminAPI, api.http(api.themes.download) ); router.post('/themes/upload', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('theme'), shared.middlewares.validation.upload({type: 'themes'}), api.http(api.themes.upload) ); router.put('/themes/:name/activate', - mw.authenticatePrivate, + mw.authAdminAPI, api.http(api.themes.activate) ); router.del('/themes/:name', - mw.authenticatePrivate, + mw.authAdminAPI, api.http(api.themes.destroy) ); // ## Notifications - router.get('/notifications', mw.authenticatePrivate, api.http(api.notifications.browse)); - router.post('/notifications', mw.authenticatePrivate, api.http(api.notifications.add)); - router.del('/notifications/:id', mw.authenticatePrivate, api.http(api.notifications.destroy)); + router.get('/notifications', mw.authAdminAPI, api.http(api.notifications.browse)); + router.post('/notifications', mw.authAdminAPI, api.http(api.notifications.add)); + router.del('/notifications/:id', mw.authAdminAPI, api.http(api.notifications.destroy)); // ## DB - router.get('/db', mw.authenticatePrivate, api.http(api.db.exportContent)); + router.get('/db', mw.authAdminAPI, api.http(api.db.exportContent)); router.post('/db', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('importfile'), shared.middlewares.validation.upload({type: 'db'}), api.http(api.db.importContent) ); - router.del('/db', mw.authenticatePrivate, api.http(api.db.deleteAllContent)); + router.del('/db', mw.authAdminAPI, api.http(api.db.deleteAllContent)); // ## Mail - router.post('/mail', mw.authenticatePrivate, api.http(api.mail.send)); - router.post('/mail/test', mw.authenticatePrivate, api.http(api.mail.sendTest)); + router.post('/mail', mw.authAdminAPI, api.http(api.mail.send)); + router.post('/mail/test', mw.authAdminAPI, api.http(api.mail.sendTest)); // ## Slack - router.post('/slack/test', mw.authenticatePrivate, api.http(api.slack.sendTest)); + router.post('/slack/test', mw.authAdminAPI, api.http(api.slack.sendTest)); + + // ## Sessions + router.get('/session', mw.authAdminAPI, api.http(apiv2.session.read)); + // We don't need auth when creating a new session (logging in) + router.post('/session', api.http(apiv2.session.add)); + router.del('/session', mw.authAdminAPI, api.http(apiv2.session.delete)); // ## Authentication router.post('/authentication/passwordreset', @@ -155,22 +162,13 @@ module.exports = function apiRoutes() { router.post('/authentication/invitation', api.http(api.authentication.acceptInvitation)); router.get('/authentication/invitation', api.http(api.authentication.isInvitation)); router.post('/authentication/setup', api.http(api.authentication.setup)); - router.put('/authentication/setup', mw.authenticatePrivate, api.http(api.authentication.updateSetup)); + router.put('/authentication/setup', mw.authAdminAPI, api.http(api.authentication.updateSetup)); router.get('/authentication/setup', api.http(api.authentication.isSetup)); - router.post('/authentication/token', - mw.authenticateClient(), - shared.middlewares.brute.globalBlock, - shared.middlewares.brute.userLogin, - auth.oauth.generateAccessToken - ); - - router.post('/authentication/revoke', mw.authenticatePrivate, api.http(api.authentication.revoke)); - // ## Uploads // @TODO: rename endpoint to /images/upload (or similar) router.post('/uploads', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('uploadimage'), shared.middlewares.validation.upload({type: 'images'}), shared.middlewares.image.normalize, @@ -178,7 +176,7 @@ module.exports = function apiRoutes() { ); router.post('/uploads/profile-image', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('uploadimage'), shared.middlewares.validation.upload({type: 'images'}), shared.middlewares.validation.profileImage, @@ -189,7 +187,7 @@ module.exports = function apiRoutes() { router.post('/db/backup', mw.authenticateClient('Ghost Backup'), api.http(api.db.backupContent)); router.post('/uploads/icon', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('uploadimage'), shared.middlewares.validation.upload({type: 'icons'}), shared.middlewares.validation.blogIcon(), @@ -197,26 +195,26 @@ module.exports = function apiRoutes() { ); // ## Invites - router.get('/invites', mw.authenticatePrivate, api.http(api.invites.browse)); - router.get('/invites/:id', mw.authenticatePrivate, api.http(api.invites.read)); - router.post('/invites', mw.authenticatePrivate, api.http(api.invites.add)); - router.del('/invites/:id', mw.authenticatePrivate, api.http(api.invites.destroy)); + router.get('/invites', mw.authAdminAPI, api.http(api.invites.browse)); + router.get('/invites/:id', mw.authAdminAPI, api.http(api.invites.read)); + router.post('/invites', mw.authAdminAPI, api.http(api.invites.add)); + router.del('/invites/:id', mw.authAdminAPI, api.http(api.invites.destroy)); // ## Redirects (JSON based) - router.get('/redirects/json', mw.authenticatePrivate, api.http(api.redirects.download)); + router.get('/redirects/json', mw.authAdminAPI, api.http(api.redirects.download)); router.post('/redirects/json', - mw.authenticatePrivate, + mw.authAdminAPI, upload.single('redirects'), shared.middlewares.validation.upload({type: 'redirects'}), api.http(api.redirects.upload) ); // ## Webhooks (RESTHooks) - router.post('/webhooks', mw.authenticatePrivate, api.http(api.webhooks.add)); - router.del('/webhooks/:id', mw.authenticatePrivate, api.http(api.webhooks.destroy)); + router.post('/webhooks', mw.authAdminAPI, api.http(api.webhooks.add)); + router.del('/webhooks/:id', mw.authAdminAPI, api.http(api.webhooks.destroy)); // ## Oembed (fetch response from oembed provider) - router.get('/oembed', mw.authenticatePrivate, api.http(api.oembed.read)); + router.get('/oembed', mw.authAdminAPI, api.http(api.oembed.read)); return router; };