From 78679906434dbaa9701dc9fec25f48c661d40fb0 Mon Sep 17 00:00:00 2001 From: akashrajum7 Date: Sat, 31 Aug 2024 15:26:45 +0530 Subject: [PATCH 1/4] feat: skip field validations on non signup routes --- .../emailpassword/api/generatePasswordResetToken.ts | 3 ++- lib/ts/recipe/emailpassword/api/implementation.ts | 8 ++++---- lib/ts/recipe/emailpassword/api/passwordReset.ts | 3 ++- lib/ts/recipe/emailpassword/api/signin.ts | 3 ++- lib/ts/recipe/emailpassword/api/utils.ts | 11 +++++++---- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/ts/recipe/emailpassword/api/generatePasswordResetToken.ts b/lib/ts/recipe/emailpassword/api/generatePasswordResetToken.ts index fb600bb05..a92b3dd91 100644 --- a/lib/ts/recipe/emailpassword/api/generatePasswordResetToken.ts +++ b/lib/ts/recipe/emailpassword/api/generatePasswordResetToken.ts @@ -40,7 +40,8 @@ export default async function generatePasswordResetToken( options.config.resetPasswordUsingTokenFeature.formFieldsForGenerateTokenForm, requestBody.formFields, tenantId, - userContext + userContext, + false ); let result = await apiImplementation.generatePasswordResetTokenPOST({ diff --git a/lib/ts/recipe/emailpassword/api/implementation.ts b/lib/ts/recipe/emailpassword/api/implementation.ts index 7467c2957..45050f0c6 100644 --- a/lib/ts/recipe/emailpassword/api/implementation.ts +++ b/lib/ts/recipe/emailpassword/api/implementation.ts @@ -65,7 +65,7 @@ export default function getAPIImplementation(): APIInterface { | { status: "PASSWORD_RESET_NOT_ALLOWED"; reason: string } | GeneralErrorResponse > { - const email = formFields.filter((f) => f.id === "email")[0].value; + const email = formFields.find((f) => f.id === "email")?.value ?? ""; // this function will be reused in different parts of the flow below.. async function generateAndSendPasswordResetToken( @@ -451,7 +451,7 @@ export default function getAPIImplementation(): APIInterface { } } - let newPassword = formFields.filter((f) => f.id === "password")[0].value; + let newPassword = formFields.find((f) => f.id === "password")?.value || ""; let tokenConsumptionResponse = await options.recipeImplementation.consumePasswordResetToken({ token, @@ -631,8 +631,8 @@ export default function getAPIImplementation(): APIInterface { "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_012)", }, }; - let email = formFields.filter((f) => f.id === "email")[0].value; - let password = formFields.filter((f) => f.id === "password")[0].value; + let email = formFields.find((f) => f.id === "email")?.value ?? ""; + let password = formFields.find((f) => f.id === "password")?.value ?? ""; const recipeId = "emailpassword"; diff --git a/lib/ts/recipe/emailpassword/api/passwordReset.ts b/lib/ts/recipe/emailpassword/api/passwordReset.ts index c6a26c010..ec3de7324 100644 --- a/lib/ts/recipe/emailpassword/api/passwordReset.ts +++ b/lib/ts/recipe/emailpassword/api/passwordReset.ts @@ -44,7 +44,8 @@ export default async function passwordReset( options.config.resetPasswordUsingTokenFeature.formFieldsForPasswordResetForm, requestBody.formFields, tenantId, - userContext + userContext, + false ); let token = requestBody.token; diff --git a/lib/ts/recipe/emailpassword/api/signin.ts b/lib/ts/recipe/emailpassword/api/signin.ts index 77c1161ff..f3a0b63cc 100644 --- a/lib/ts/recipe/emailpassword/api/signin.ts +++ b/lib/ts/recipe/emailpassword/api/signin.ts @@ -38,7 +38,8 @@ export default async function signInAPI( options.config.signInFeature.formFields, (await options.req.getJSONBody()).formFields, tenantId, - userContext + userContext, + false ); let session = await Session.getSession( diff --git a/lib/ts/recipe/emailpassword/api/utils.ts b/lib/ts/recipe/emailpassword/api/utils.ts index ae944e1f9..4af0014f0 100644 --- a/lib/ts/recipe/emailpassword/api/utils.ts +++ b/lib/ts/recipe/emailpassword/api/utils.ts @@ -21,7 +21,8 @@ export async function validateFormFieldsOrThrowError( configFormFields: NormalisedFormField[], formFieldsRaw: any, tenantId: string, - userContext: UserContext + userContext: UserContext, + runValidators: boolean = true ): Promise< { id: string; @@ -69,9 +70,11 @@ export async function validateFormFieldsOrThrowError( return field; }); - // then run validators through them----------------------- - await validateFormOrThrowError(formFields, configFormFields, tenantId, userContext); - + // Run form field validators for only signup, see: https://github.com/supertokens/supertokens-node/issues/447 + if (runValidators) { + // then run validators through them----------------------- + await validateFormOrThrowError(formFields, configFormFields, tenantId, userContext); + } return formFields; } From 814e56c5ea72088efadeafe555df2b384deddb7b Mon Sep 17 00:00:00 2001 From: akashrajum7 Date: Sat, 31 Aug 2024 16:11:08 +0530 Subject: [PATCH 2/4] fix: add explicit form validation in signup --- lib/ts/recipe/emailpassword/api/signup.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ts/recipe/emailpassword/api/signup.ts b/lib/ts/recipe/emailpassword/api/signup.ts index ec9a2781d..385cee75a 100644 --- a/lib/ts/recipe/emailpassword/api/signup.ts +++ b/lib/ts/recipe/emailpassword/api/signup.ts @@ -42,7 +42,8 @@ export default async function signUpAPI( options.config.signUpFeature.formFields, requestBody.formFields, tenantId, - userContext + userContext, + true ); let session = await Session.getSession( From 344f42f55018f8409a85fcb420b7b4b70a3f30a2 Mon Sep 17 00:00:00 2001 From: akashrajum7 Date: Sat, 31 Aug 2024 16:19:02 +0530 Subject: [PATCH 3/4] misc: run build command after changes --- .../api/generatePasswordResetToken.js | 3 ++- .../emailpassword/api/implementation.js | 27 ++++++++++++++++--- .../recipe/emailpassword/api/passwordReset.js | 3 ++- lib/build/recipe/emailpassword/api/signin.js | 3 ++- lib/build/recipe/emailpassword/api/signup.js | 3 ++- lib/build/recipe/emailpassword/api/utils.d.ts | 3 ++- lib/build/recipe/emailpassword/api/utils.js | 15 ++++++++--- 7 files changed, 45 insertions(+), 12 deletions(-) diff --git a/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js b/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js index f4e469a9d..bf7f8badf 100644 --- a/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js +++ b/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js @@ -27,7 +27,8 @@ async function generatePasswordResetToken(apiImplementation, tenantId, options, options.config.resetPasswordUsingTokenFeature.formFieldsForGenerateTokenForm, requestBody.formFields, tenantId, - userContext + userContext, + false ); let result = await apiImplementation.generatePasswordResetTokenPOST({ formFields, diff --git a/lib/build/recipe/emailpassword/api/implementation.js b/lib/build/recipe/emailpassword/api/implementation.js index 703c9462a..3868818d7 100644 --- a/lib/build/recipe/emailpassword/api/implementation.js +++ b/lib/build/recipe/emailpassword/api/implementation.js @@ -40,7 +40,12 @@ function getAPIImplementation() { }; }, generatePasswordResetTokenPOST: async function ({ formFields, tenantId, options, userContext }) { - const email = formFields.filter((f) => f.id === "email")[0].value; + var _a, _b; + const email = + (_b = (_a = formFields.find((f) => f.id === "email")) === null || _a === void 0 ? void 0 : _a.value) !== + null && _b !== void 0 + ? _b + : ""; // this function will be reused in different parts of the flow below.. async function generateAndSendPasswordResetToken(primaryUserId, recipeUserId) { // the user ID here can be primary or recipe level. @@ -259,6 +264,7 @@ function getAPIImplementation() { ); }, passwordResetPOST: async function ({ formFields, token, tenantId, options, userContext }) { + var _a; async function markEmailAsVerified(recipeUserId, email) { const emailVerificationInstance = recipe_2.default.getInstance(); if (emailVerificationInstance) { @@ -355,7 +361,9 @@ function getAPIImplementation() { }; } } - let newPassword = formFields.filter((f) => f.id === "password")[0].value; + let newPassword = + ((_a = formFields.find((f) => f.id === "password")) === null || _a === void 0 ? void 0 : _a.value) || + ""; let tokenConsumptionResponse = await options.recipeImplementation.consumePasswordResetToken({ token, tenantId, @@ -482,6 +490,7 @@ function getAPIImplementation() { } }, signInPOST: async function ({ formFields, tenantId, session, options, userContext }) { + var _a, _b, _c, _d; const errorCodeMap = { SIGN_IN_NOT_ALLOWED: "Cannot sign in due to security reasons. Please try resetting your password, use a different login method or contact support. (ERR_CODE_008)", @@ -496,8 +505,18 @@ function getAPIImplementation() { "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_012)", }, }; - let email = formFields.filter((f) => f.id === "email")[0].value; - let password = formFields.filter((f) => f.id === "password")[0].value; + let email = + (_b = (_a = formFields.find((f) => f.id === "email")) === null || _a === void 0 ? void 0 : _a.value) !== + null && _b !== void 0 + ? _b + : ""; + let password = + (_d = + (_c = formFields.find((f) => f.id === "password")) === null || _c === void 0 + ? void 0 + : _c.value) !== null && _d !== void 0 + ? _d + : ""; const recipeId = "emailpassword"; const checkCredentialsOnTenant = async (tenantId) => { return ( diff --git a/lib/build/recipe/emailpassword/api/passwordReset.js b/lib/build/recipe/emailpassword/api/passwordReset.js index 0565d8dcd..f2914cedf 100644 --- a/lib/build/recipe/emailpassword/api/passwordReset.js +++ b/lib/build/recipe/emailpassword/api/passwordReset.js @@ -36,7 +36,8 @@ async function passwordReset(apiImplementation, tenantId, options, userContext) options.config.resetPasswordUsingTokenFeature.formFieldsForPasswordResetForm, requestBody.formFields, tenantId, - userContext + userContext, + false ); let token = requestBody.token; if (token === undefined) { diff --git a/lib/build/recipe/emailpassword/api/signin.js b/lib/build/recipe/emailpassword/api/signin.js index 0ddb015d1..0ab4419d5 100644 --- a/lib/build/recipe/emailpassword/api/signin.js +++ b/lib/build/recipe/emailpassword/api/signin.js @@ -32,7 +32,8 @@ async function signInAPI(apiImplementation, tenantId, options, userContext) { options.config.signInFeature.formFields, (await options.req.getJSONBody()).formFields, tenantId, - userContext + userContext, + false ); let session = await session_1.default.getSession( options.req, diff --git a/lib/build/recipe/emailpassword/api/signup.js b/lib/build/recipe/emailpassword/api/signup.js index 0987b15fb..cfff267f7 100644 --- a/lib/build/recipe/emailpassword/api/signup.js +++ b/lib/build/recipe/emailpassword/api/signup.js @@ -34,7 +34,8 @@ async function signUpAPI(apiImplementation, tenantId, options, userContext) { options.config.signUpFeature.formFields, requestBody.formFields, tenantId, - userContext + userContext, + true ); let session = await session_1.default.getSession( options.req, diff --git a/lib/build/recipe/emailpassword/api/utils.d.ts b/lib/build/recipe/emailpassword/api/utils.d.ts index d797f42e3..5e79c4d0f 100644 --- a/lib/build/recipe/emailpassword/api/utils.d.ts +++ b/lib/build/recipe/emailpassword/api/utils.d.ts @@ -5,7 +5,8 @@ export declare function validateFormFieldsOrThrowError( configFormFields: NormalisedFormField[], formFieldsRaw: any, tenantId: string, - userContext: UserContext + userContext: UserContext, + runValidators?: boolean ): Promise< { id: string; diff --git a/lib/build/recipe/emailpassword/api/utils.js b/lib/build/recipe/emailpassword/api/utils.js index ead402cfb..fb6f33b44 100644 --- a/lib/build/recipe/emailpassword/api/utils.js +++ b/lib/build/recipe/emailpassword/api/utils.js @@ -8,7 +8,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateFormFieldsOrThrowError = void 0; const error_1 = __importDefault(require("../error")); const constants_1 = require("../constants"); -async function validateFormFieldsOrThrowError(configFormFields, formFieldsRaw, tenantId, userContext) { +async function validateFormFieldsOrThrowError( + configFormFields, + formFieldsRaw, + tenantId, + userContext, + runValidators = true +) { // first we check syntax ---------------------------- if (formFieldsRaw === undefined) { throw newBadRequestError("Missing input param: formFields"); @@ -39,8 +45,11 @@ async function validateFormFieldsOrThrowError(configFormFields, formFieldsRaw, t } return field; }); - // then run validators through them----------------------- - await validateFormOrThrowError(formFields, configFormFields, tenantId, userContext); + // Run form field validators for only signup, see: https://github.com/supertokens/supertokens-node/issues/447 + if (runValidators) { + // then run validators through them----------------------- + await validateFormOrThrowError(formFields, configFormFields, tenantId, userContext); + } return formFields; } exports.validateFormFieldsOrThrowError = validateFormFieldsOrThrowError; From dab7d0c73cda5e51712d5a734abc4574361f90ab Mon Sep 17 00:00:00 2001 From: akashrajum7 Date: Sat, 31 Aug 2024 16:22:49 +0530 Subject: [PATCH 4/4] docs: update changelog and version --- CHANGELOG.md | 2 ++ lib/build/version.d.ts | 2 +- lib/build/version.js | 2 +- lib/ts/version.ts | 2 +- package.json | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 674c6db72..4c6f9d195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +- Remove form validation on signin and password reset routes in emailpassword recipe + ## [20.0.4] - 2024-08-30 - Improves thirdParty debug logging to help with debugging issues with JSON parsing. diff --git a/lib/build/version.d.ts b/lib/build/version.d.ts index 34ebb2116..93718a872 100644 --- a/lib/build/version.d.ts +++ b/lib/build/version.d.ts @@ -1,4 +1,4 @@ // @ts-nocheck -export declare const version = "20.0.4"; +export declare const version = "20.0.5"; export declare const cdiSupported: string[]; export declare const dashboardVersion = "0.13"; diff --git a/lib/build/version.js b/lib/build/version.js index ccd6143d0..e256659d6 100644 --- a/lib/build/version.js +++ b/lib/build/version.js @@ -15,7 +15,7 @@ exports.dashboardVersion = exports.cdiSupported = exports.version = void 0; * License for the specific language governing permissions and limitations * under the License. */ -exports.version = "20.0.4"; +exports.version = "20.0.5"; exports.cdiSupported = ["5.1"]; // Note: The actual script import for dashboard uses v{DASHBOARD_VERSION} exports.dashboardVersion = "0.13"; diff --git a/lib/ts/version.ts b/lib/ts/version.ts index deab8f43b..9f9d7d051 100644 --- a/lib/ts/version.ts +++ b/lib/ts/version.ts @@ -12,7 +12,7 @@ * License for the specific language governing permissions and limitations * under the License. */ -export const version = "20.0.4"; +export const version = "20.0.5"; export const cdiSupported = ["5.1"]; diff --git a/package.json b/package.json index 4951f4d13..b32c64b53 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-node", - "version": "20.0.4", + "version": "20.0.5", "description": "NodeJS driver for SuperTokens core", "main": "index.js", "scripts": {