2016-09-30 14:45:59 +03:00
|
|
|
var ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
|
|
|
|
BearerStrategy = require('passport-http-bearer').Strategy,
|
|
|
|
GhostOAuth2Strategy = require('passport-ghost').Strategy,
|
|
|
|
passport = require('passport'),
|
2016-11-08 17:21:25 +03:00
|
|
|
_ = require('lodash'),
|
2016-10-25 14:17:43 +03:00
|
|
|
debug = require('debug')('ghost:auth'),
|
2016-09-30 14:45:59 +03:00
|
|
|
Promise = require('bluebird'),
|
|
|
|
authStrategies = require('./auth-strategies'),
|
|
|
|
errors = require('../errors'),
|
2016-11-08 17:21:25 +03:00
|
|
|
events = require('../events'),
|
2016-10-06 15:27:35 +03:00
|
|
|
logging = require('../logging'),
|
2016-09-30 14:45:59 +03:00
|
|
|
models = require('../models'),
|
2016-11-08 17:21:25 +03:00
|
|
|
_private = {};
|
2016-09-30 14:45:59 +03:00
|
|
|
|
2016-11-08 17:21:25 +03:00
|
|
|
/**
|
|
|
|
* Update client name and description if changes in the blog settings
|
|
|
|
*/
|
|
|
|
_private.registerEvents = function registerEvents() {
|
|
|
|
events.on('settings.edited', function onSettingsChanged(settingModel) {
|
|
|
|
var titleHasChanged = settingModel.attributes.key === 'title' && settingModel.attributes.value !== settingModel._updatedAttributes.value,
|
|
|
|
descriptionHasChanged = settingModel.attributes.key === 'description' && settingModel.attributes.value !== settingModel._updatedAttributes.value,
|
|
|
|
options = {
|
|
|
|
ghostOAuth2Strategy: passport._strategies.ghost
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!titleHasChanged && !descriptionHasChanged) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (titleHasChanged) {
|
|
|
|
options.clientName = settingModel.attributes.value;
|
|
|
|
debug('Ghost Auth Client title has changed: ' + options.clientName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (descriptionHasChanged) {
|
|
|
|
options.clientDescription = settingModel.attributes.value;
|
|
|
|
debug('Ghost AuthClient description has changed: ' + options.clientDescription);
|
|
|
|
}
|
|
|
|
|
|
|
|
_private.updateClient(options).catch(function onUpdatedClientError(err) {
|
|
|
|
// @TODO: see https://github.com/TryGhost/Ghost/issues/7627
|
|
|
|
if (_.isArray(err)) {
|
|
|
|
err = err[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
logging.error(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* smart function
|
|
|
|
*/
|
|
|
|
_private.updateClient = function updateClient(options) {
|
2016-09-30 14:45:59 +03:00
|
|
|
var ghostOAuth2Strategy = options.ghostOAuth2Strategy,
|
2016-11-08 17:21:25 +03:00
|
|
|
redirectUri = options.redirectUri,
|
|
|
|
clientUri = options.clientUri,
|
2016-11-07 14:38:05 +03:00
|
|
|
clientName = options.clientName,
|
2016-11-08 17:21:25 +03:00
|
|
|
clientDescription = options.clientDescription;
|
2016-09-30 14:45:59 +03:00
|
|
|
|
2016-10-12 14:11:56 +03:00
|
|
|
return models.Client.findOne({slug: 'ghost-auth'}, {context: {internal: true}})
|
2016-11-08 17:21:25 +03:00
|
|
|
.then(function (client) {
|
|
|
|
// CASE: we have to create the client
|
|
|
|
if (!client) {
|
|
|
|
debug('Client does not exist');
|
|
|
|
|
|
|
|
return ghostOAuth2Strategy.registerClient({
|
|
|
|
name: clientName,
|
|
|
|
description: clientDescription
|
|
|
|
}).then(function registeredRemoteClient(credentials) {
|
|
|
|
debug('Registered remote client: ' + JSON.stringify(credentials));
|
2016-09-30 14:45:59 +03:00
|
|
|
|
2016-10-12 14:11:56 +03:00
|
|
|
return models.Client.add({
|
2016-11-08 17:21:25 +03:00
|
|
|
name: credentials.name,
|
|
|
|
description: credentials.description,
|
2016-10-12 14:11:56 +03:00
|
|
|
slug: 'ghost-auth',
|
|
|
|
uuid: credentials.client_id,
|
2016-10-21 18:08:17 +03:00
|
|
|
secret: credentials.client_secret,
|
2016-11-08 17:21:25 +03:00
|
|
|
redirection_uri: credentials.redirect_uri,
|
|
|
|
client_uri: credentials.blog_uri
|
2016-10-12 14:11:56 +03:00
|
|
|
}, {context: {internal: true}});
|
2016-11-08 17:21:25 +03:00
|
|
|
}).then(function addedLocalClient(client) {
|
|
|
|
debug('Added local client: ' + JSON.stringify(client.toJSON()));
|
|
|
|
|
2016-10-12 14:11:56 +03:00
|
|
|
return {
|
|
|
|
client_id: client.get('uuid'),
|
|
|
|
client_secret: client.get('secret')
|
|
|
|
};
|
|
|
|
});
|
2016-11-08 17:21:25 +03:00
|
|
|
}
|
2016-10-06 15:27:35 +03:00
|
|
|
|
2016-11-08 17:21:25 +03:00
|
|
|
// CASE: nothing changed
|
|
|
|
if (client.get('redirection_uri') === redirectUri &&
|
|
|
|
client.get('name') === clientName &&
|
|
|
|
client.get('description') === clientDescription &&
|
|
|
|
client.get('client_uri') === clientUri) {
|
|
|
|
debug('Client did not change');
|
|
|
|
|
|
|
|
return {
|
|
|
|
client_id: client.get('uuid'),
|
|
|
|
client_secret: client.get('secret')
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
debug('Update client...');
|
|
|
|
return ghostOAuth2Strategy.updateClient(_.omit({
|
|
|
|
clientId: client.get('uuid'),
|
|
|
|
clientSecret: client.get('secret'),
|
|
|
|
redirectUri: redirectUri,
|
|
|
|
blogUri: clientUri,
|
|
|
|
name: clientName,
|
|
|
|
description: clientDescription
|
|
|
|
}, _.isUndefined)).then(function updatedRemoteClient(updatedRemoteClient) {
|
|
|
|
debug('Update remote client: ' + JSON.stringify(updatedRemoteClient));
|
|
|
|
|
|
|
|
client.set('redirection_uri', updatedRemoteClient.redirect_uri);
|
|
|
|
client.set('client_uri', updatedRemoteClient.blog_uri);
|
|
|
|
client.set('name', updatedRemoteClient.name);
|
|
|
|
client.set('description', updatedRemoteClient.description);
|
|
|
|
|
|
|
|
return client.save(null, {context: {internal: true}});
|
|
|
|
}).then(function updatedLocalClient() {
|
|
|
|
return {
|
|
|
|
client_id: client.get('uuid'),
|
|
|
|
client_secret: client.get('secret')
|
|
|
|
};
|
|
|
|
});
|
|
|
|
});
|
2016-09-30 14:45:59 +03:00
|
|
|
};
|
|
|
|
|
2016-10-12 14:11:56 +03:00
|
|
|
/**
|
|
|
|
* auth types:
|
|
|
|
* - password: local login
|
|
|
|
* - ghost: remote login at Ghost.org
|
|
|
|
*/
|
2016-09-30 14:45:59 +03:00
|
|
|
exports.init = function initPassport(options) {
|
2016-11-07 14:38:05 +03:00
|
|
|
var authType = options.authType,
|
|
|
|
clientName = options.clientName,
|
2016-11-08 17:21:25 +03:00
|
|
|
clientDescription = options.clientDescription,
|
2016-11-07 14:38:05 +03:00
|
|
|
ghostAuthUrl = options.ghostAuthUrl,
|
|
|
|
redirectUri = options.redirectUri,
|
2016-11-08 17:21:25 +03:00
|
|
|
clientUri = options.clientUri;
|
2016-09-30 14:45:59 +03:00
|
|
|
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
passport.use(new ClientPasswordStrategy(authStrategies.clientPasswordStrategy));
|
|
|
|
passport.use(new BearerStrategy(authStrategies.bearerStrategy));
|
|
|
|
|
2016-11-07 14:38:05 +03:00
|
|
|
if (authType !== 'ghost') {
|
2016-09-30 14:45:59 +03:00
|
|
|
return resolve({passport: passport.initialize()});
|
|
|
|
}
|
|
|
|
|
|
|
|
var ghostOAuth2Strategy = new GhostOAuth2Strategy({
|
2016-11-08 17:21:25 +03:00
|
|
|
redirectUri: redirectUri,
|
|
|
|
blogUri: clientUri,
|
2016-11-07 14:38:05 +03:00
|
|
|
url: ghostAuthUrl,
|
2016-09-30 14:45:59 +03:00
|
|
|
passReqToCallback: true
|
|
|
|
}, authStrategies.ghostStrategy);
|
|
|
|
|
2016-11-08 17:21:25 +03:00
|
|
|
_private.updateClient({
|
2016-10-12 14:11:56 +03:00
|
|
|
ghostOAuth2Strategy: ghostOAuth2Strategy,
|
2016-11-07 14:38:05 +03:00
|
|
|
clientName: clientName,
|
2016-11-08 17:21:25 +03:00
|
|
|
clientDescription: clientDescription,
|
|
|
|
redirectUri: redirectUri,
|
|
|
|
clientUri: clientUri
|
2016-10-12 14:11:56 +03:00
|
|
|
}).then(function setClient(client) {
|
|
|
|
ghostOAuth2Strategy.setClient(client);
|
|
|
|
passport.use(ghostOAuth2Strategy);
|
2016-11-08 17:21:25 +03:00
|
|
|
_private.registerEvents();
|
2016-10-12 14:11:56 +03:00
|
|
|
return resolve({passport: passport.initialize()});
|
2016-11-08 17:21:25 +03:00
|
|
|
}).catch(function onError(err) {
|
2017-02-14 15:09:52 +03:00
|
|
|
debug('Public registration failed:' + err.message);
|
|
|
|
|
2016-11-08 17:21:25 +03:00
|
|
|
// @TODO: see https://github.com/TryGhost/Ghost/issues/7627
|
2017-02-14 15:09:52 +03:00
|
|
|
// CASE: can happen if database query fails
|
2016-11-08 17:21:25 +03:00
|
|
|
if (_.isArray(err)) {
|
|
|
|
err = err[0];
|
|
|
|
}
|
|
|
|
|
2017-02-14 15:09:52 +03:00
|
|
|
if (!errors.utils.isIgnitionError(err)) {
|
|
|
|
err = new errors.GhostError({
|
|
|
|
err: err
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
err.level = 'critical';
|
|
|
|
err.context = err.context || 'Public client registration failed';
|
|
|
|
err.help = err.help || 'Please verify the configured url: ' + ghostOAuth2Strategy.url;
|
2016-11-08 17:21:25 +03:00
|
|
|
|
2017-02-14 15:09:52 +03:00
|
|
|
return reject(err);
|
2016-11-08 17:21:25 +03:00
|
|
|
});
|
2016-09-30 14:45:59 +03:00
|
|
|
});
|
|
|
|
};
|