Removed oauth experiment

refs: https://github.com/TryGhost/Team/issues/1625

- this didn't work the way we wanted to
- removing this will free up the namespaces to start over
This commit is contained in:
Hannah Wolfe 2022-05-16 17:03:02 +01:00
parent 18cf73c3b3
commit 12aff14dff
17 changed files with 12 additions and 274 deletions

View File

@ -14,7 +14,6 @@ module.exports = {
'accent_color',
'url',
'version',
'oauth',
'sentry_dsn',
'sentry_env'
])

View File

@ -69,8 +69,6 @@ const SETTING_KEYS_BLOCKLIST = [
'stripe_publishable_key',
'members_stripe_webhook_id',
'members_stripe_webhook_secret',
'oauth_client_id',
'oauth_client_secret',
'email_verification_required'
];

View File

@ -18,7 +18,9 @@ const settingsToRemove = [
'newsletter_title_font_category',
'newsletter_show_feature_image',
'newsletter_body_font_category',
'newsletter_footer_content'
'newsletter_footer_content',
'oauth_client_id',
'oauth_client_secret'
];
// Settings that cannot be removed, but should not be used anymore

View File

@ -433,16 +433,6 @@
"type": "array"
}
},
"oauth": {
"oauth_client_id" : {
"defaultValue": null,
"type": "string"
},
"oauth_client_secret" : {
"defaultValue": null,
"type": "string"
}
},
"editor": {
"editor_default_email_recipients": {
"defaultValue": "visibility",

View File

@ -2,7 +2,6 @@ const ghostVersion = require('@tryghost/version');
const settingsCache = require('../../../shared/settings-cache');
const config = require('../../../shared/config');
const urlUtils = require('../../../shared/url-utils');
const labs = require('../../../shared/labs');
module.exports = function getSiteProperties() {
const siteProperties = {
@ -15,11 +14,6 @@ module.exports = function getSiteProperties() {
version: ghostVersion.safe
};
if (labs.isSet('oauthLogin') && settingsCache.get('oauth_client_id') && settingsCache.get('oauth_client_secret')) {
// Only set the oauth flag if oauth is enabled to avoid API changes
siteProperties.oauth = true;
}
if (config.get('client_sentry') && !config.get('client_sentry').disabled) {
siteProperties.sentry_dsn = config.get('client_sentry').dsn;
siteProperties.sentry_env = config.get('env');

View File

@ -1,153 +0,0 @@
const debug = require('@tryghost/debug')('web:oauth:app');
const {URL} = require('url');
const express = require('../../../shared/express');
const urlUtils = require('../../../shared/url-utils');
const settingsCache = require('../../../shared/settings-cache');
const models = require('../../models');
const auth = require('../../services/auth');
const labs = require('../../../shared/labs');
function randomPassword() {
return require('crypto').randomBytes(128).toString('hex');
}
module.exports = function setupOAuthApp() {
debug('OAuth App setup start');
const oauthApp = express('oauth');
function labsMiddleware(req, res, next) {
if (labs.isSet('oauthLogin')) {
return next();
}
res.sendStatus(404);
}
oauthApp.use(labsMiddleware);
/**
* Configure the passport.authenticate middleware
* We need to configure it on each request because clientId and secret
* will change (when the Owner is changing these settings)
*/
function googleOAuthMiddleware(clientId, secret) {
return (req, res, next) => {
// Lazy-required to save boot time
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const adminURL = urlUtils.urlFor('admin', true);
//Create the callback url to be sent to Google
const callbackUrl = new URL('oauth/google/callback', adminURL);
passport.authenticate(new GoogleStrategy({
clientID: clientId,
clientSecret: secret,
callbackURL: callbackUrl.href
}, async function (accessToken, refreshToken, profile) {
// This is the verify function that checks that a Google-authenticated user
// is matching one of our users (or invite).
if (req.user) {
// CASE: the user already has an active Ghost session
const emails = profile.emails.filter(email => email.verified === true).map(email => email.value);
if (!emails.includes(req.user.get('email'))) {
return res.redirect(new URL('#/staff?message=oauth-linking-failed', adminURL));
}
// TODO: configure the oauth data for this user (row in the oauth table)
//Associate logged-in user with oauth account
req.user.set('password', randomPassword());
await req.user.save();
} else {
// CASE: the user is logging-in or accepting an invite
//Find user in DB and log-in
//TODO: instead find the oauth row with the email use the provider id
const emails = profile.emails.filter(email => email.verified === true);
if (emails.length < 1) {
return res.redirect(new URL('#/signin?message=login-failed', adminURL));
}
const email = emails[0].value;
let user = await models.User.findOne({
email: email
});
if (!user) {
// CASE: the user is accepting an invite
// TODO: move this code in the invitations service
const options = {context: {internal: true}};
let invite = await models.Invite.findOne({email, status: 'sent'}, options);
if (!invite || invite.get('expires') < Date.now()) {
return res.redirect(new URL('#/signin?message=login-failed', adminURL));
}
//Accept invite
user = await models.User.add({
email: email,
name: profile.displayName,
password: randomPassword(),
roles: [invite.toJSON().role_id]
}, options);
await invite.destroy(options);
// TODO: create an oauth model link to user
}
req.user = user;
}
await auth.session.sessionService.createSessionForUser(req, res, req.user);
return res.redirect(adminURL);
}), {
scope: ['profile', 'email'],
session: false,
prompt: 'consent',
accessType: 'offline'
})(req, res, next);
};
}
oauthApp.get('/:provider', auth.authenticate.authenticateAdminApi, (req, res, next) => {
if (req.params.provider !== 'google') {
return res.sendStatus(404);
}
const clientId = settingsCache.get('oauth_client_id');
const secret = settingsCache.get('oauth_client_secret');
if (clientId && secret) {
return googleOAuthMiddleware(clientId, secret)(req, res, next);
}
res.sendStatus(404);
});
oauthApp.get('/:provider/callback', (req, res, next) => {
// Set the referrer as the ghost instance domain so that the session is linked to the ghost instance domain
req.headers.referrer = urlUtils.getAdminUrl();
next();
}, auth.authenticate.authenticateAdminApi, (req, res, next) => {
if (req.params.provider !== 'google') {
return res.sendStatus(404);
}
const clientId = settingsCache.get('oauth_client_id');
const secret = settingsCache.get('oauth_client_secret');
if (clientId && secret) {
return googleOAuthMiddleware(clientId, secret)(req, res, next);
}
res.sendStatus(404);
});
debug('OAuth App setup end');
return oauthApp;
};

View File

@ -1 +0,0 @@
module.exports = require('./app');

View File

@ -13,7 +13,6 @@ module.exports = () => {
const backendApp = express('backend');
backendApp.lazyUse(BASE_API_PATH, require('../api'));
backendApp.lazyUse('/ghost/oauth', require('../oauth'));
backendApp.lazyUse('/ghost/.well-known', require('../well-known'));
backendApp.use('/ghost', require('../../services/auth/session').createSessionFromToken, require('../admin')());

View File

@ -35,7 +35,6 @@ const BETA_FEATURES = [
];
const ALPHA_FEATURES = [
'oauthLogin',
'urlCache',
'beforeAfterCard',
'tweetGridCard'

View File

@ -173,8 +173,6 @@
"nconf": "0.12.0",
"node-jose": "2.1.1",
"oembed-parser": "1.4.9",
"passport": "0.5.2",
"passport-google-oauth": "2.0.0",
"path-match": "1.2.4",
"probe-image-size": "7.2.3",
"rss": "1.2.2",

View File

@ -230,7 +230,7 @@ Object {
},
Object {
"key": "labs",
"value": "{\\"activitypub\\":true,\\"oauthLogin\\":true,\\"urlCache\\":true,\\"beforeAfterCard\\":true,\\"tweetGridCard\\":true,\\"multipleProducts\\":true,\\"tierWelcomePages\\":true,\\"tierName\\":true,\\"selectablePortalLinks\\":true,\\"membersTableStatus\\":true,\\"improvedOnboarding\\":true,\\"multipleNewsletters\\":true,\\"multipleNewslettersUI\\":true,\\"membersActivityFeed\\":true,\\"publishingFlow\\":true,\\"dashboardV5\\":true,\\"members\\":true}",
"value": "{\\"activitypub\\":true,\\"urlCache\\":true,\\"beforeAfterCard\\":true,\\"tweetGridCard\\":true,\\"multipleProducts\\":true,\\"tierWelcomePages\\":true,\\"tierName\\":true,\\"selectablePortalLinks\\":true,\\"membersTableStatus\\":true,\\"improvedOnboarding\\":true,\\"multipleNewsletters\\":true,\\"multipleNewslettersUI\\":true,\\"membersActivityFeed\\":true,\\"publishingFlow\\":true,\\"dashboardV5\\":true,\\"members\\":true}",
},
Object {
"key": "slack_url",
@ -248,14 +248,6 @@ Object {
"key": "shared_views",
"value": "[]",
},
Object {
"key": "oauth_client_id",
"value": null,
},
Object {
"key": "oauth_client_secret",
"value": null,
},
Object {
"key": "editor_default_email_recipients",
"value": "visibility",
@ -288,7 +280,7 @@ exports[`Settings API Browse Can request all settings 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3777",
"content-length": "3675",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",

View File

@ -1,8 +1,8 @@
const assert = require('assert');
const {agentProvider, fixtureManager, mockManager, matchers} = require('../../utils/e2e-framework');
const {stringMatching, anyEtag, anyObjectId, anyISODateTime} = matchers;
const {stringMatching, anyEtag} = matchers;
const CURRENT_SETTINGS_COUNT = 69;
const CURRENT_SETTINGS_COUNT = 67;
const settingsMatcher = {};

View File

@ -5,7 +5,7 @@ const db = require('../../../core/server/data/db');
// Stuff we are testing
const models = require('../../../core/server/models');
const SETTINGS_LENGTH = 79;
const SETTINGS_LENGTH = 77;
describe('Settings Model', function () {
before(models.init);

View File

@ -37,7 +37,7 @@ describe('DB version integrity', function () {
// Only these variables should need updating
const currentSchemaHash = '2f4266e6e5087ad92dd30f3e721d46e5';
const currentFixturesHash = '2509ff2c1f6e0293a3c3d84f08593b2f';
const currentSettingsHash = '840ed1334fc8a1d5387bb4ceb134845f';
const currentSettingsHash = '0b138cdd40e48b5b7dc4ebac2a7819a7';
const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';
// If this test is failing, then it is likely a change has been made that requires a DB version bump,

View File

@ -57,6 +57,7 @@ describe('Labs Service', function () {
// NOTE: this test should be rewritten to test the alpha flag independently of the internal ALPHA_FEATURES list
// otherwise we end up in the endless maintenance loop and need to update it every time a feature graduates from alpha
labs.getAll().should.eql(expectedLabsObject({
oauthLogin: true,
members: true
}));

View File

@ -433,16 +433,6 @@
"type": "array"
}
},
"oauth": {
"oauth_client_id" : {
"defaultValue": null,
"type": "string"
},
"oauth_client_secret" : {
"defaultValue": null,
"type": "string"
}
},
"editor": {
"editor_default_email_recipients": {
"defaultValue": "visibility",

View File

@ -2937,7 +2937,7 @@ base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
base64url@3.x.x, base64url@^3.0.1:
base64url@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
@ -9036,11 +9036,6 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
oauth@0.9.x:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@ -9382,61 +9377,6 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
passport-google-oauth1@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz#af74a803df51ec646f66a44d82282be6f108e0cc"
integrity sha1-r3SoA99R7GRvZqRNgigr5vEI4Mw=
dependencies:
passport-oauth1 "1.x.x"
passport-google-oauth20@2.x.x:
version "2.0.0"
resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef"
integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==
dependencies:
passport-oauth2 "1.x.x"
passport-google-oauth@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/passport-google-oauth/-/passport-google-oauth-2.0.0.tgz#f6eb4bc96dd6c16ec0ecfdf4e05ec48ca54d4dae"
integrity sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA==
dependencies:
passport-google-oauth1 "1.x.x"
passport-google-oauth20 "2.x.x"
passport-oauth1@1.x.x:
version "1.2.0"
resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.2.0.tgz#5229d431781bf5b265bec86ce9a9cce58a756cf9"
integrity sha512-Sv2YWodC6jN12M/OXwmR4BIXeeIHjjbwYTQw4kS6tHK4zYzSEpxBgSJJnknBjICA5cj0ju3FSnG1XmHgIhYnLg==
dependencies:
oauth "0.9.x"
passport-strategy "1.x.x"
utils-merge "1.x.x"
passport-oauth2@1.x.x:
version "1.6.1"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.6.1.tgz#c5aee8f849ce8bd436c7f81d904a3cd1666f181b"
integrity sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==
dependencies:
base64url "3.x.x"
oauth "0.9.x"
passport-strategy "1.x.x"
uid2 "0.0.x"
utils-merge "1.x.x"
passport-strategy@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=
passport@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/passport/-/passport-0.5.2.tgz#0cb38dd8a71552c8390dfa6a9a6f7f3909954bcf"
integrity sha512-w9n/Ot5I7orGD4y+7V3EFJCQEznE5RxHamUxcqLT2QoJY0f2JdN8GyHonYFvN0Vz+L6lUJfVhrk2aZz2LbuREw==
dependencies:
passport-strategy "1.x.x"
pause "0.0.1"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
@ -9501,11 +9441,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0:
dependencies:
isarray "0.0.1"
pause@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
@ -11625,11 +11560,6 @@ uid-safe@~2.1.5:
dependencies:
random-bytes "~1.0.0"
uid2@0.0.x:
version "0.0.4"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44"
integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==
unbox-primitive@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
@ -11872,7 +11802,7 @@ utils-indexof@^1.0.0:
validate.io-array-like "^1.0.1"
validate.io-integer-primitive "^1.0.0"
utils-merge@1.0.1, utils-merge@1.x.x:
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=