From 273d403638578f98bc8bd7bbaa2e3df8adabb332 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 3 Oct 2022 22:35:23 +0100 Subject: [PATCH 1/4] Add and use reCAPTCHA server environment variable --- packages/toolpad-app/src/server/config.ts | 2 ++ packages/toolpad-app/src/server/data.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/toolpad-app/src/server/config.ts b/packages/toolpad-app/src/server/config.ts index aeac419816e..cc6ec4798b0 100644 --- a/packages/toolpad-app/src/server/config.ts +++ b/packages/toolpad-app/src/server/config.ts @@ -18,6 +18,7 @@ export type ServerConfig = { encryptionKeys: string[]; basicAuthUser?: string; basicAuthPassword?: string; + recaptchaSecretKey?: string; } & BasicAuthConfig; function readConfig(): ServerConfig & typeof sharedConfig { @@ -52,6 +53,7 @@ function readConfig(): ServerConfig & typeof sharedConfig { googleSheetsClientId: process.env.TOOLPAD_DATASOURCE_GOOGLESHEETS_CLIENT_ID, googleSheetsClientSecret: process.env.TOOLPAD_DATASOURCE_GOOGLESHEETS_CLIENT_SECRET, externalUrl: process.env.TOOLPAD_EXTERNAL_URL || `http://localhost:${process.env.PORT || 3000}`, + recaptchaSecretKey: process.env.TOOLPAD_RECAPTCHA_SECRET_KEY, encryptionKeys, }; } diff --git a/packages/toolpad-app/src/server/data.ts b/packages/toolpad-app/src/server/data.ts index 8b5c73bb5e7..9e06f5ff71a 100644 --- a/packages/toolpad-app/src/server/data.ts +++ b/packages/toolpad-app/src/server/data.ts @@ -11,6 +11,7 @@ import applyTransform from './applyTransform'; import { excludeFields } from '../utils/prisma'; import { getAppTemplateDom } from './appTemplateDoms/doms'; import { validateRecaptchaToken } from '../utils/recaptcha'; +import config from './config'; const SELECT_RELEASE_META = excludeFields(prisma.Prisma.ReleaseScalarFieldEnum, ['snapshot']); const SELECT_APP_META = excludeFields(prisma.Prisma.AppScalarFieldEnum, ['dom']); @@ -197,7 +198,7 @@ export type CreateAppOptions = { export async function createApp(name: string, opts: CreateAppOptions = {}): Promise { const { from } = opts; - const recaptchaSecretKey = process.env.TOOLPAD_RECAPTCHA_SECRET_KEY; + const recaptchaSecretKey = config.recaptchaSecretKey; if (recaptchaSecretKey) { const isRecaptchaTokenValid = await validateRecaptchaToken( recaptchaSecretKey, From 8ec6c3dbff03c1e4201a1be183e12c0db71a87d1 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Tue, 4 Oct 2022 16:06:36 +0100 Subject: [PATCH 2/4] Split server side methods, safer URL --- .../toolpad-app/src/server/utils/recaptcha.ts | 22 +++++++++++++ .../toolpad-app/src/toolpad/Home/index.tsx | 6 ++-- packages/toolpad-app/src/utils/recaptcha.ts | 31 ------------------- 3 files changed, 26 insertions(+), 33 deletions(-) create mode 100644 packages/toolpad-app/src/server/utils/recaptcha.ts delete mode 100644 packages/toolpad-app/src/utils/recaptcha.ts diff --git a/packages/toolpad-app/src/server/utils/recaptcha.ts b/packages/toolpad-app/src/server/utils/recaptcha.ts new file mode 100644 index 00000000000..b4218278aa5 --- /dev/null +++ b/packages/toolpad-app/src/server/utils/recaptcha.ts @@ -0,0 +1,22 @@ +const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify'; +const SCORE_THRESHOLD = 0.5; + +export const validateRecaptchaToken = async ( + secretKey: string, + token: string, +): Promise => { + const siteVerifyUrl = new URL(SITE_VERIFY_URL); + siteVerifyUrl.searchParams.set('secret', secretKey); + siteVerifyUrl.searchParams.set('response', token); + + const recaptchaResponse = await fetch(siteVerifyUrl, { + method: 'POST', + }); + + const { success, score } = await recaptchaResponse.json(); + if (!success || score < SCORE_THRESHOLD) { + return false; + } + + return true; +}; diff --git a/packages/toolpad-app/src/toolpad/Home/index.tsx b/packages/toolpad-app/src/toolpad/Home/index.tsx index ef2161e22d4..782f097f334 100644 --- a/packages/toolpad-app/src/toolpad/Home/index.tsx +++ b/packages/toolpad-app/src/toolpad/Home/index.tsx @@ -54,7 +54,6 @@ import { ConfirmDialog } from '../../components/SystemDialogs'; import config from '../../config'; import { AppTemplateId } from '../../types'; import { errorFrom } from '../../utils/errors'; -import { getRecaptchaToken } from '../../utils/recaptcha'; export const APP_TEMPLATE_OPTIONS = { blank: { @@ -112,7 +111,10 @@ function CreateAppDialog({ onClose, ...props }: CreateAppDialogProps) { let recaptchaToken; if (config.recaptchaSiteKey) { - recaptchaToken = await getRecaptchaToken(config.recaptchaSiteKey); + await new Promise((resolve) => grecaptcha.ready(resolve)); + recaptchaToken = await grecaptcha.execute(config.recaptchaSiteKey, { + action: 'submit', + }); } const appDom = dom.trim() ? JSON.parse(dom) : null; diff --git a/packages/toolpad-app/src/utils/recaptcha.ts b/packages/toolpad-app/src/utils/recaptcha.ts deleted file mode 100644 index 8c8660a4c0a..00000000000 --- a/packages/toolpad-app/src/utils/recaptcha.ts +++ /dev/null @@ -1,31 +0,0 @@ -export const getRecaptchaToken = async (siteKey: string): Promise => { - await new Promise((resolve) => grecaptcha.ready(resolve)); - return grecaptcha.execute(siteKey, { - action: 'submit', - }); -}; - -const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify'; -const SCORE_THRESHOLD = 0.5; - -export const validateRecaptchaToken = async ( - secretKey: string, - token: string, -): Promise => { - const recaptchaParams = new URLSearchParams({ - secret: secretKey, - response: token, - }); - const siteVerifyUrlWithParams = `${SITE_VERIFY_URL}?${recaptchaParams}`; - - const recaptchaResponse = await fetch(siteVerifyUrlWithParams, { - method: 'POST', - }); - - const { success, score } = await recaptchaResponse.json(); - if (!success || score < SCORE_THRESHOLD) { - return false; - } - - return true; -}; From ae9e39b268cc4f9a13fec8ee6e3d7a7764a35d46 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Tue, 4 Oct 2022 16:17:22 +0100 Subject: [PATCH 3/4] Fix import --- packages/toolpad-app/src/server/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/toolpad-app/src/server/data.ts b/packages/toolpad-app/src/server/data.ts index 9e06f5ff71a..e2046704d58 100644 --- a/packages/toolpad-app/src/server/data.ts +++ b/packages/toolpad-app/src/server/data.ts @@ -10,7 +10,7 @@ import { decryptSecret, encryptSecret } from './secrets'; import applyTransform from './applyTransform'; import { excludeFields } from '../utils/prisma'; import { getAppTemplateDom } from './appTemplateDoms/doms'; -import { validateRecaptchaToken } from '../utils/recaptcha'; +import { validateRecaptchaToken } from './utils/recaptcha'; import config from './config'; const SELECT_RELEASE_META = excludeFields(prisma.Prisma.ReleaseScalarFieldEnum, ['snapshot']); From e9584b65db5a2977686292f2130faa2eee5a9bf3 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Tue, 4 Oct 2022 16:25:31 +0100 Subject: [PATCH 4/4] Remove server utils folder --- packages/toolpad-app/src/server/data.ts | 2 +- .../server/{utils/recaptcha.ts => validateRecaptchaToken.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/toolpad-app/src/server/{utils/recaptcha.ts => validateRecaptchaToken.ts} (100%) diff --git a/packages/toolpad-app/src/server/data.ts b/packages/toolpad-app/src/server/data.ts index e2046704d58..c2b915fd9c6 100644 --- a/packages/toolpad-app/src/server/data.ts +++ b/packages/toolpad-app/src/server/data.ts @@ -10,7 +10,7 @@ import { decryptSecret, encryptSecret } from './secrets'; import applyTransform from './applyTransform'; import { excludeFields } from '../utils/prisma'; import { getAppTemplateDom } from './appTemplateDoms/doms'; -import { validateRecaptchaToken } from './utils/recaptcha'; +import { validateRecaptchaToken } from './validateRecaptchaToken'; import config from './config'; const SELECT_RELEASE_META = excludeFields(prisma.Prisma.ReleaseScalarFieldEnum, ['snapshot']); diff --git a/packages/toolpad-app/src/server/utils/recaptcha.ts b/packages/toolpad-app/src/server/validateRecaptchaToken.ts similarity index 100% rename from packages/toolpad-app/src/server/utils/recaptcha.ts rename to packages/toolpad-app/src/server/validateRecaptchaToken.ts