From c1e808f9e807fc49508acbde0d8b3f2b901a1638 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 29 May 2022 09:50:43 +1000 Subject: [PATCH] feat: selectively enable / disable default authentication adapters (#7953) --- DEPRECATIONS.md | 1 + spec/AuthenticationAdapters.spec.js | 26 ++++++++++++++++++++++++++ src/Options/Definitions.js | 9 ++++++++- src/Options/docs.js | 7 ++++++- src/Options/index.js | 10 +++++++++- src/RestWrite.js | 10 +++++++++- 6 files changed, 59 insertions(+), 4 deletions(-) diff --git a/DEPRECATIONS.md b/DEPRECATIONS.md index 986522477b..e4ca0d41d9 100644 --- a/DEPRECATIONS.md +++ b/DEPRECATIONS.md @@ -9,6 +9,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h | DEPPS3 | Config option `enforcePrivateUsers` defaults to `true` | [#7319](https://github.com/parse-community/parse-server/pull/7319) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | | DEPPS4 | Remove convenience method for http request `Parse.Cloud.httpRequest` | [#7589](https://github.com/parse-community/parse-server/pull/7589) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | | DEPPS5 | Config option `allowClientClassCreation` defaults to `false` | [#7925](https://github.com/parse-community/parse-server/pull/7925) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | +| DEPPS6 | Auth providers disabled by default | [#7953](https://github.com/parse-community/parse-server/pull/7953) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | [i_deprecation]: ## "The version and date of the deprecation." [i_removal]: ## "The version and date of the planned removal." diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index bfb64502cd..dff8b42258 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -477,6 +477,32 @@ describe('AuthenticationProviders', function () { expect(appIds).toEqual(['a', 'b']); expect(providerOptions).toEqual(options.custom); }); + + it('can disable provider', async () => { + await reconfigureServer({ + auth: { + myoauth: { + enabled: false, + module: path.resolve(__dirname, 'support/myoauth'), // relative path as it's run from src + }, + }, + }); + const provider = getMockMyOauthProvider(); + Parse.User._registerAuthenticationProvider(provider); + await expectAsync(Parse.User._logInWith('myoauth')).toBeRejectedWith( + new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.') + ); + }); + + it('can depreciate', async () => { + const Deprecator = require('../lib/Deprecator/Deprecator'); + const spy = spyOn(Deprecator, 'logRuntimeDeprecation').and.callFake(() => {}); + const provider = getMockMyOauthProvider(); + Parse.User._registerAuthenticationProvider(provider); + await Parse.User._logInWith('myoauth'); + expect(spy).toHaveBeenCalledWith({ usage: 'auth.myoauth', solution: 'auth.myoauth.enabled: true' }); + }); + }); describe('instagram auth adapter', () => { diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index f8b8eab633..c9a316db36 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -95,7 +95,7 @@ module.exports.ParseServerOptions = { env: 'PARSE_SERVER_AUTH_PROVIDERS', help: 'Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication', - action: parsers.objectParser, + action: parsers.arrayParser, }, cacheAdapter: { env: 'PARSE_SERVER_CACHE_ADAPTER', @@ -876,3 +876,10 @@ module.exports.DatabaseOptions = { default: false, }, }; +module.exports.AuthAdapter = { + enabled: { + help: 'Is `true` if the auth adapter is enabled, `false` otherwise.', + action: parsers.booleanParser, + default: true, + }, +}; diff --git a/src/Options/docs.js b/src/Options/docs.js index 24b60c46a9..e8601bd4e5 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -19,7 +19,7 @@ * @property {Adapter} analyticsAdapter Adapter module for the analytics * @property {String} appId Your Parse Application ID * @property {String} appName Sets the app name - * @property {Any} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication + * @property {AuthAdapter[]} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication * @property {Adapter} cacheAdapter Adapter module for the cache * @property {Number} cacheMaxSize Sets the maximum size for the in memory cache, defaults to 10000 * @property {Number} cacheTTL Sets the TTL for the in memory cache (in ms), defaults to 5000 (5 seconds) @@ -208,3 +208,8 @@ * @interface DatabaseOptions * @property {Boolean} enableSchemaHooks Enables database real-time hooks to update single schema cache. Set to `true` if using multiple Parse Servers instances connected to the same database. Failing to do so will cause a schema change to not propagate to all instances and re-syncing will only happen when the instances restart. To use this feature with MongoDB, a replica set cluster with [change stream](https://docs.mongodb.com/manual/changeStreams/#availability) support is required. */ + +/** + * @interface AuthAdapter + * @property {Boolean} enabled Is `true` if the auth adapter is enabled, `false` otherwise. + */ diff --git a/src/Options/index.js b/src/Options/index.js index 8124446f99..c298bc78e2 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -140,7 +140,7 @@ export interface ParseServerOptions { allowCustomObjectId: ?boolean; /* Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication :ENV: PARSE_SERVER_AUTH_PROVIDERS */ - auth: ?any; + auth: ?(AuthAdapter[]); /* Max file size for uploads, defaults to 20mb :DEFAULT: 20mb */ maxUploadSize: ?string; @@ -506,3 +506,11 @@ export interface DatabaseOptions { :DEFAULT: false */ enableSchemaHooks: ?boolean; } + +export interface AuthAdapter { + /* Is `true` if the auth adapter is enabled, `false` otherwise. + :DEFAULT: true + :ENV: + */ + enabled: ?boolean; +} diff --git a/src/RestWrite.js b/src/RestWrite.js index 0b9bf2a8d4..fd81561732 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -15,6 +15,7 @@ var ClientSDK = require('./ClientSDK'); import RestQuery from './RestQuery'; import _ from 'lodash'; import logger from './logger'; +import Deprecator from './Deprecator/Deprecator'; import { requiredColumns } from './Controllers/SchemaController'; // query and data are both provided in REST API format. So data @@ -430,7 +431,14 @@ RestWrite.prototype.handleAuthDataValidation = function (authData) { return Promise.resolve(); } const validateAuthData = this.config.authDataManager.getValidatorForProvider(provider); - if (!validateAuthData) { + const authProvider = (this.config.auth || {})[provider] || {}; + if (authProvider.enabled == null) { + Deprecator.logRuntimeDeprecation({ + usage: `auth.${provider}`, + solution: `auth.${provider}.enabled: true`, + }); + } + if (!validateAuthData || authProvider.enabled === false) { throw new Parse.Error( Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.'