diff --git a/lib/build/genericComponentOverrideContext.js b/lib/build/genericComponentOverrideContext.js
index 5b9a429eb..9d97a3933 100644
--- a/lib/build/genericComponentOverrideContext.js
+++ b/lib/build/genericComponentOverrideContext.js
@@ -227,6 +227,54 @@ typeof SuppressedError === "function"
return (e.name = "SuppressedError"), (e.error = error), (e.suppressed = suppressed), e;
};
+/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
+ *
+ * This software is licensed under the Apache License, Version 2.0 (the
+ * "License") as published by the Apache Software Foundation.
+ *
+ * You may not use this file except in compliance with the License. You may
+ * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+var package_version = "0.35.7";
+
+/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
+ *
+ * This software is licensed under the Apache License, Version 2.0 (the
+ * "License") as published by the Apache Software Foundation.
+ *
+ * You may not use this file except in compliance with the License. You may
+ * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+var SUPERTOKENS_DEBUG_NAMESPACE = "com.supertokens.auth-react";
+var __debugLogsEnabled = false;
+function enableLogging() {
+ __debugLogsEnabled = true;
+}
+function logDebugMessage(message) {
+ if (__debugLogsEnabled) {
+ // eslint-disable-next-line no-console
+ console.log(
+ ""
+ .concat(SUPERTOKENS_DEBUG_NAMESPACE, ' {t: "')
+ .concat(new Date().toISOString(), '", message: "')
+ .concat(message, '", supertokens-auth-react-ver: "')
+ .concat(package_version, '"}')
+ );
+ }
+}
+
/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
@@ -1133,6 +1181,10 @@ var SuperTokens = /** @class */ (function () {
];
case 1:
redirectUrl = _a.sent();
+ if (redirectUrl === null) {
+ logDebugMessage("Skipping redirection because the user override returned null");
+ return [2 /*return*/];
+ }
redirectUrl = appendQueryParamsToURL(redirectUrl, queryParams);
return [2 /*return*/, this.redirectToUrl(redirectUrl, options.history)];
}
@@ -1164,9 +1216,9 @@ var SuperTokens = /** @class */ (function () {
translationEventSource: new TranslationController(),
userTranslationFunc: translationConfig.translationFunc,
};
- var enableDebugLogs = false;
- if (config.enableDebugLogs !== undefined) {
- enableDebugLogs = config.enableDebugLogs;
+ var enableDebugLogs = Boolean(config === null || config === void 0 ? void 0 : config.enableDebugLogs);
+ if (enableDebugLogs) {
+ enableLogging();
}
this.userGetRedirectionURL = config.getRedirectionURL;
this.recipeList = config.recipeList.map(function (_a) {
@@ -1323,6 +1375,7 @@ exports.getQueryParams = getQueryParams;
exports.getRedirectToPathFromURL = getRedirectToPathFromURL;
exports.getURLHash = getURLHash;
exports.isTest = isTest;
+exports.logDebugMessage = logDebugMessage;
exports.matchRecipeIdUsingQueryParams = matchRecipeIdUsingQueryParams;
exports.mergeObjects = mergeObjects;
exports.normaliseRecipeModuleConfig = normaliseRecipeModuleConfig;
diff --git a/lib/build/index2.js b/lib/build/index2.js
index 2b9fda041..d42ef5214 100644
--- a/lib/build/index2.js
+++ b/lib/build/index2.js
@@ -1037,6 +1037,15 @@ var SessionAuth = function (_a) {
];
case 1:
failureRedirectInfo = _a.sent();
+ if (failureRedirectInfo.redirectPath === null) {
+ setContext(toSetContext);
+ genericComponentOverrideContext.logDebugMessage(
+ "Skipping redirection because the user override returned null for validator ".concat(
+ JSON.stringify(failureRedirectInfo.failedClaim, null, 2)
+ )
+ );
+ return [2 /*return*/];
+ }
if (!(failureRedirectInfo.redirectPath !== undefined)) return [3 /*break*/, 3];
setContext(toSetContext);
return [
diff --git a/lib/build/logger.d.ts b/lib/build/logger.d.ts
new file mode 100644
index 000000000..a5e767ecb
--- /dev/null
+++ b/lib/build/logger.d.ts
@@ -0,0 +1,2 @@
+export declare function enableLogging(): void;
+export declare function logDebugMessage(message: string): void;
diff --git a/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts b/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts
index bcc6e2b05..8ff8a9b05 100644
--- a/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts
+++ b/lib/build/recipe/emailpassword/components/themes/resetPasswordUsingToken/resetPasswordEmail.d.ts
@@ -1,7 +1,7 @@
///
export declare const ResetPasswordEmail: import("react").ComponentType<
import("../../../../../types").ThemeBaseProps & {
- formFields: Omit[];
+ formFields: import("../../../types").FormFieldThemeProps[];
error: string | undefined;
} & {
recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface;
diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts
index 46dd93ed6..2b40c960b 100644
--- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts
+++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signIn.d.ts
@@ -10,6 +10,6 @@ export declare const SignIn: import("react").ComponentType<
config: import("../../../types").NormalisedConfig;
signUpClicked?: (() => void) | undefined;
forgotPasswordClick: () => void;
- onSuccess: () => void;
+ onSuccess: (result: { user: import("supertokens-web-js/types").User }) => void;
}
>;
diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts
index f57175ca5..7dbc1321c 100644
--- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts
+++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signInForm.d.ts
@@ -1,7 +1,7 @@
///
export declare const SignInForm: import("react").ComponentType<
import("../../../../../types").ThemeBaseProps & {
- formFields: Omit[];
+ formFields: import("../../../types").FormFieldThemeProps[];
error: string | undefined;
} & {
recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface;
diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts
index 1a0268aa8..380a6e333 100644
--- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts
+++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUp.d.ts
@@ -9,6 +9,6 @@ export declare const SignUp: import("react").ComponentType<
onError: (error: string) => void;
config: import("../../../types").NormalisedConfig;
signInClicked?: (() => void) | undefined;
- onSuccess: () => void;
+ onSuccess: (result: { user: import("supertokens-web-js/types").User }) => void;
}
>;
diff --git a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts
index 85b7e4c8d..bbe4a2eb2 100644
--- a/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts
+++ b/lib/build/recipe/emailpassword/components/themes/signInAndUp/signUpForm.d.ts
@@ -1,14 +1,15 @@
///
export declare const SignUpForm: import("react").ComponentType<
import("../../../../../types").ThemeBaseProps & {
+ formFields: import("../../../types").FormFieldThemeProps[];
+ error: string | undefined;
+ } & {
recipeImplementation: import("supertokens-web-js/recipe/emailpassword").RecipeInterface;
clearError: () => void;
onError: (error: string) => void;
config: import("../../../types").NormalisedConfig;
signInClicked?: (() => void) | undefined;
onSuccess: (result: { user: import("supertokens-web-js/types").User }) => void;
- formFields: import("../../../types").FormFieldThemeProps[];
- error: string | undefined;
} & {
header?: JSX.Element | undefined;
footer?: JSX.Element | undefined;
diff --git a/lib/build/recipe/recipeModule/index.d.ts b/lib/build/recipe/recipeModule/index.d.ts
index 83002fb43..8f1ce6015 100644
--- a/lib/build/recipe/recipeModule/index.d.ts
+++ b/lib/build/recipe/recipeModule/index.d.ts
@@ -11,6 +11,6 @@ export default abstract class RecipeModule<
history?: any,
queryParams?: Record
) => Promise;
- getRedirectUrl: (context: GetRedirectionURLContextType) => Promise;
+ getRedirectUrl: (context: GetRedirectionURLContextType) => Promise;
getDefaultRedirectionURL(_: GetRedirectionURLContextType): Promise;
}
diff --git a/lib/build/recipe/recipeModule/types.d.ts b/lib/build/recipe/recipeModule/types.d.ts
index d39ad4720..2aa0c2761 100644
--- a/lib/build/recipe/recipeModule/types.d.ts
+++ b/lib/build/recipe/recipeModule/types.d.ts
@@ -18,7 +18,7 @@ export declare type RecipePreAPIHookFunction = (context: RecipePreAPIHoo
export declare type RecipePostAPIHookFunction = (context: RecipePostAPIHookContext) => Promise;
export declare type RecipeOnHandleEventFunction = (context: EventType) => void;
export declare type UserInput = {
- getRedirectionURL?: (context: GetRedirectionURLContextType) => Promise;
+ getRedirectionURL?: (context: GetRedirectionURLContextType) => Promise;
preAPIHook?: RecipePreAPIHookFunction;
postAPIHook?: RecipePostAPIHookFunction;
onHandleEvent?: RecipeOnHandleEventFunction;
@@ -31,7 +31,7 @@ export declare type Config;
export declare type NormalisedConfig = {
- getRedirectionURL: (context: GetRedirectionURLContextType) => Promise;
+ getRedirectionURL: (context: GetRedirectionURLContextType) => Promise;
onHandleEvent: RecipeOnHandleEventFunction;
useShadowDom: boolean;
rootStyle: string;
diff --git a/lib/build/recipe/session/utils.d.ts b/lib/build/recipe/session/utils.d.ts
index 828d0b578..8b71365ae 100644
--- a/lib/build/recipe/session/utils.d.ts
+++ b/lib/build/recipe/session/utils.d.ts
@@ -13,6 +13,6 @@ export declare const getFailureRedirectionInfo: ({
| undefined;
userContext: any;
}) => Promise<{
- redirectPath?: string | undefined;
+ redirectPath?: string | null | undefined;
failedClaim?: ClaimValidationError | undefined;
}>;
diff --git a/lib/build/recipe/thirdpartyemailpassword/components/themes/translations.d.ts b/lib/build/recipe/thirdpartyemailpassword/components/themes/translations.d.ts
index bb256d116..454ff978e 100644
--- a/lib/build/recipe/thirdpartyemailpassword/components/themes/translations.d.ts
+++ b/lib/build/recipe/thirdpartyemailpassword/components/themes/translations.d.ts
@@ -58,6 +58,9 @@ export declare const defaultTranslationsThirdPartyEmailPassword: {
"Password must contain at least one alphabet": undefined;
"Password must contain at least one number": undefined;
"Email is invalid": undefined;
+ "Reset password link was not created because of account take over risk. Please contact support. (ERR_CODE_001)": undefined;
+ "Cannot sign up due to security reasons. Please try logging in, use a different login method or contact support. (ERR_CODE_007)": undefined;
+ "Cannot sign in due to security reasons. Please try resetting your password, use a different login method or contact support. (ERR_CODE_008)": undefined;
EMAIL_VERIFICATION_RESEND_SUCCESS: string;
EMAIL_VERIFICATION_SEND_TITLE: string;
EMAIL_VERIFICATION_SEND_DESC_START: string;
@@ -86,5 +89,8 @@ export declare const defaultTranslationsThirdPartyEmailPassword: {
THIRD_PARTY_PROVIDER_DEFAULT_BTN_START: string;
THIRD_PARTY_PROVIDER_DEFAULT_BTN_END: string;
THIRD_PARTY_ERROR_NO_EMAIL: string;
+ "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_004)": undefined;
+ "Cannot sign in / up because new email cannot be applied to existing account. Please contact support. (ERR_CODE_005)": undefined;
+ "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_006)": undefined;
};
};
diff --git a/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts b/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts
index dbe4e941e..b24b59e60 100644
--- a/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts
+++ b/lib/build/recipe/thirdpartypasswordless/components/themes/translations.d.ts
@@ -57,6 +57,8 @@ export declare const defaultTranslationsThirdPartyPasswordless: {
"Failed to generate a one time code. Please try again": undefined;
"Phone number is invalid": undefined;
"Email is invalid": undefined;
+ "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_002)": undefined;
+ "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_003)": undefined;
BRANDING_POWERED_BY_START: string;
BRANDING_POWERED_BY_END: string;
SOMETHING_WENT_WRONG_ERROR: string;
@@ -69,5 +71,8 @@ export declare const defaultTranslationsThirdPartyPasswordless: {
THIRD_PARTY_PROVIDER_DEFAULT_BTN_START: string;
THIRD_PARTY_PROVIDER_DEFAULT_BTN_END: string;
THIRD_PARTY_ERROR_NO_EMAIL: string;
+ "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_004)": undefined;
+ "Cannot sign in / up because new email cannot be applied to existing account. Please contact support. (ERR_CODE_005)": undefined;
+ "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_006)": undefined;
};
};
diff --git a/lib/build/recipeModule-shared.js b/lib/build/recipeModule-shared.js
index 5074ca865..24110a4e2 100644
--- a/lib/build/recipeModule-shared.js
+++ b/lib/build/recipeModule-shared.js
@@ -29,6 +29,14 @@ var RecipeModule = /** @class */ (function (_super) {
return [4 /*yield*/, this.getRedirectUrl(context)];
case 1:
redirectUrl = _a.sent();
+ if (redirectUrl === null) {
+ genericComponentOverrideContext.logDebugMessage(
+ "Skipping redirection because the user override returned null for context ".concat(
+ JSON.stringify(context, null, 2)
+ )
+ );
+ return [2 /*return*/];
+ }
redirectUrl = genericComponentOverrideContext.appendQueryParamsToURL(
redirectUrl,
queryParams
diff --git a/lib/build/session-shared2.js b/lib/build/session-shared2.js
index 7d78ccc90..5d424b8a7 100644
--- a/lib/build/session-shared2.js
+++ b/lib/build/session-shared2.js
@@ -248,6 +248,14 @@ var Session = /** @class */ (function (_super) {
];
case 5:
failureRedirectInfo = _a.sent();
+ if (failureRedirectInfo.redirectPath === null) {
+ genericComponentOverrideContext.logDebugMessage(
+ "Skipping redirection because the user override returned null for validator ".concat(
+ JSON.stringify(failureRedirectInfo.failedClaim, null, 2)
+ )
+ );
+ return [2 /*return*/];
+ }
// if redirectPath is string that means failed claim had callback that returns path, we redirect there otherwise continue
if (failureRedirectInfo.redirectPath !== undefined) {
return [
diff --git a/lib/build/superTokens.d.ts b/lib/build/superTokens.d.ts
index b823c6099..154622b99 100644
--- a/lib/build/superTokens.d.ts
+++ b/lib/build/superTokens.d.ts
@@ -25,7 +25,7 @@ export default class SuperTokens {
): RecipeModule;
changeLanguage: (lang: string) => Promise;
loadTranslation(store: TranslationStore): void;
- getRedirectUrl(context: GetRedirectionURLContext): Promise;
+ getRedirectUrl(context: GetRedirectionURLContext): Promise;
redirectToAuth: (options: {
show?: "signin" | "signup" | undefined;
history?: any;
diff --git a/lib/build/types.d.ts b/lib/build/types.d.ts
index ad8f5fb88..220004efb 100644
--- a/lib/build/types.d.ts
+++ b/lib/build/types.d.ts
@@ -13,7 +13,13 @@ export declare type GetRedirectionURLContext = {
showSignIn?: boolean;
};
export declare type ValidationFailureCallback =
- | (({ userContext, reason }: { userContext: any; reason: any }) => Promise | string | undefined)
+ | (({
+ userContext,
+ reason,
+ }: {
+ userContext: any;
+ reason: any;
+ }) => Promise | string | undefined | null)
| undefined;
export declare type SessionClaimValidator = SessionClaimValidatorWebJS & {
showAccessDeniedOnFailure?: boolean;
@@ -40,7 +46,7 @@ export declare type SuperTokensConfig = {
translationFunc?: TranslationFunc;
};
enableDebugLogs?: boolean;
- getRedirectionURL?: (context: GetRedirectionURLContext) => Promise;
+ getRedirectionURL?: (context: GetRedirectionURLContext) => Promise;
};
export declare type WebJSRecipeInterface = Omit;
export declare type CreateRecipeFunction> = (
diff --git a/lib/ts/logger.ts b/lib/ts/logger.ts
new file mode 100644
index 000000000..e8d77c5b8
--- /dev/null
+++ b/lib/ts/logger.ts
@@ -0,0 +1,33 @@
+/* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
+ *
+ * This software is licensed under the Apache License, Version 2.0 (the
+ * "License") as published by the Apache Software Foundation.
+ *
+ * You may not use this file except in compliance with the License. You may
+ * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { package_version as version } from "./version";
+
+const SUPERTOKENS_DEBUG_NAMESPACE = "com.supertokens.auth-react";
+
+let __debugLogsEnabled = false;
+
+export function enableLogging(): void {
+ __debugLogsEnabled = true;
+}
+
+export function logDebugMessage(message: string): void {
+ if (__debugLogsEnabled) {
+ // eslint-disable-next-line no-console
+ console.log(
+ `${SUPERTOKENS_DEBUG_NAMESPACE} {t: "${new Date().toISOString()}", message: "${message}", supertokens-auth-react-ver: "${version}"}`
+ );
+ }
+}
diff --git a/lib/ts/recipe/recipeModule/index.ts b/lib/ts/recipe/recipeModule/index.ts
index 28eb247db..554fa395b 100644
--- a/lib/ts/recipe/recipeModule/index.ts
+++ b/lib/ts/recipe/recipeModule/index.ts
@@ -13,6 +13,7 @@
* under the License.
*/
+import { logDebugMessage } from "../../logger";
import SuperTokens from "../../superTokens";
import { appendQueryParamsToURL } from "../../utils";
@@ -32,12 +33,24 @@ export default abstract class RecipeModule<
queryParams?: Record
): Promise => {
let redirectUrl = await this.getRedirectUrl(context);
+
+ if (redirectUrl === null) {
+ logDebugMessage(
+ `Skipping redirection because the user override returned null for context ${JSON.stringify(
+ context,
+ null,
+ 2
+ )}`
+ );
+ return;
+ }
+
redirectUrl = appendQueryParamsToURL(redirectUrl, queryParams);
return SuperTokens.getInstanceOrThrow().redirectToUrl(redirectUrl, history);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
- getRedirectUrl = async (context: GetRedirectionURLContextType): Promise => {
+ getRedirectUrl = async (context: GetRedirectionURLContextType): Promise => {
// If getRedirectionURL provided by user.
const redirectUrl = await this.config.getRedirectionURL(context);
if (redirectUrl !== undefined) {
diff --git a/lib/ts/recipe/recipeModule/types.ts b/lib/ts/recipe/recipeModule/types.ts
index 16e6a91fb..243c07233 100644
--- a/lib/ts/recipe/recipeModule/types.ts
+++ b/lib/ts/recipe/recipeModule/types.ts
@@ -22,7 +22,7 @@ export type RecipePostAPIHookFunction = (context: RecipePostAPIHookConte
export type RecipeOnHandleEventFunction = (context: EventType) => void;
export type UserInput = {
- getRedirectionURL?: (context: GetRedirectionURLContextType) => Promise;
+ getRedirectionURL?: (context: GetRedirectionURLContextType) => Promise;
preAPIHook?: RecipePreAPIHookFunction;
postAPIHook?: RecipePostAPIHookFunction;
onHandleEvent?: RecipeOnHandleEventFunction;
@@ -37,7 +37,7 @@ export type Config;
export type NormalisedConfig = {
- getRedirectionURL: (context: GetRedirectionURLContextType) => Promise;
+ getRedirectionURL: (context: GetRedirectionURLContextType) => Promise;
onHandleEvent: RecipeOnHandleEventFunction;
useShadowDom: boolean;
rootStyle: string;
diff --git a/lib/ts/recipe/recipeModule/utils.ts b/lib/ts/recipe/recipeModule/utils.ts
index 6abd98a4b..a816eaefb 100644
--- a/lib/ts/recipe/recipeModule/utils.ts
+++ b/lib/ts/recipe/recipeModule/utils.ts
@@ -12,7 +12,7 @@ export function normaliseRecipeModuleConfig(config?: Config):
if (getRedirectionURL === undefined) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- getRedirectionURL = async (_: unknown): Promise => undefined;
+ getRedirectionURL = async (_: unknown): Promise => undefined;
}
if (preAPIHook === undefined) {
diff --git a/lib/ts/recipe/session/recipe.tsx b/lib/ts/recipe/session/recipe.tsx
index 46f1ffb96..35ef2b1ae 100644
--- a/lib/ts/recipe/session/recipe.tsx
+++ b/lib/ts/recipe/session/recipe.tsx
@@ -19,6 +19,7 @@
import SessionWebJS from "supertokens-web-js/recipe/session";
import WebJSSessionRecipe from "supertokens-web-js/recipe/session";
+import { logDebugMessage } from "../../logger";
import SuperTokens from "../../superTokens";
import { getLocalStorage, isTest, removeFromLocalStorage, setLocalStorage } from "../../utils";
import RecipeModule from "../recipeModule";
@@ -145,6 +146,17 @@ export default class Session extends RecipeModule> = ({ children,
overrideGlobalClaimValidators: props.overrideGlobalClaimValidators,
userContext,
});
+
+ if (failureRedirectInfo.redirectPath === null) {
+ setContext(toSetContext);
+ logDebugMessage(
+ `Skipping redirection because the user override returned null for validator ${JSON.stringify(
+ failureRedirectInfo.failedClaim,
+ null,
+ 2
+ )}`
+ );
+ return;
+ }
+
if (failureRedirectInfo.redirectPath !== undefined) {
setContext(toSetContext);
return await SuperTokens.getInstanceOrThrow().redirectToUrl(
diff --git a/lib/ts/recipe/session/utils.ts b/lib/ts/recipe/session/utils.ts
index abc350ef9..5a0a2b679 100644
--- a/lib/ts/recipe/session/utils.ts
+++ b/lib/ts/recipe/session/utils.ts
@@ -57,7 +57,7 @@ export const getFailureRedirectionInfo = async ({
userContext: any
) => SessionClaimValidator[];
userContext: any;
-}): Promise<{ redirectPath?: string; failedClaim?: ClaimValidationError }> => {
+}): Promise<{ redirectPath?: string | null; failedClaim?: ClaimValidationError }> => {
const globalValidators = getGlobalClaimValidators({
overrideGlobalClaimValidators,
userContext,
diff --git a/lib/ts/superTokens.tsx b/lib/ts/superTokens.tsx
index 3449197cc..a0c4f3d45 100644
--- a/lib/ts/superTokens.tsx
+++ b/lib/ts/superTokens.tsx
@@ -22,6 +22,7 @@ import { PostSuperTokensInitCallbacks } from "supertokens-web-js/utils/postSuper
import { WindowHandlerReference } from "supertokens-web-js/utils/windowHandler";
import { SSR_ERROR } from "./constants";
+import { enableLogging, logDebugMessage } from "./logger";
import Multitenancy from "./recipe/multitenancy/recipe";
import { saveCurrentLanguage, TranslationController } from "./translation/translationHelpers";
import {
@@ -90,9 +91,10 @@ export default class SuperTokens {
userTranslationFunc: translationConfig.translationFunc,
};
- let enableDebugLogs = false;
- if (config.enableDebugLogs !== undefined) {
- enableDebugLogs = config.enableDebugLogs;
+ const enableDebugLogs = Boolean(config?.enableDebugLogs);
+
+ if (enableDebugLogs) {
+ enableLogging();
}
this.userGetRedirectionURL = config.getRedirectionURL;
@@ -165,7 +167,7 @@ export default class SuperTokens {
this.languageTranslations.translationEventSource.emit("TranslationLoaded", store);
}
- async getRedirectUrl(context: GetRedirectionURLContext): Promise {
+ async getRedirectUrl(context: GetRedirectionURLContext): Promise {
if (this.userGetRedirectionURL) {
const userRes = await this.userGetRedirectionURL(context);
if (userRes !== undefined) {
@@ -197,6 +199,11 @@ export default class SuperTokens {
action: "TO_AUTH",
showSignIn: options.show === "signin",
});
+
+ if (redirectUrl === null) {
+ logDebugMessage("Skipping redirection because the user override returned null");
+ return;
+ }
redirectUrl = appendQueryParamsToURL(redirectUrl, queryParams);
return this.redirectToUrl(redirectUrl, options.history);
};
diff --git a/lib/ts/types.ts b/lib/ts/types.ts
index 0f7771175..1d3419984 100644
--- a/lib/ts/types.ts
+++ b/lib/ts/types.ts
@@ -30,7 +30,13 @@ export type GetRedirectionURLContext = {
};
export type ValidationFailureCallback =
- | (({ userContext, reason }: { userContext: any; reason: any }) => Promise | string | undefined)
+ | (({
+ userContext,
+ reason,
+ }: {
+ userContext: any;
+ reason: any;
+ }) => Promise | string | undefined | null)
| undefined;
export type SessionClaimValidator = SessionClaimValidatorWebJS & {
@@ -98,7 +104,7 @@ export type SuperTokensConfig = {
translationFunc?: TranslationFunc;
};
enableDebugLogs?: boolean;
- getRedirectionURL?: (context: GetRedirectionURLContext) => Promise;
+ getRedirectionURL?: (context: GetRedirectionURLContext) => Promise;
};
export type WebJSRecipeInterface = Omit;
diff --git a/test/unit/recipe/emailpassword/emailPassword.test.tsx b/test/unit/recipe/emailpassword/emailPassword.test.tsx
index 7718ea095..3382b7c7e 100644
--- a/test/unit/recipe/emailpassword/emailPassword.test.tsx
+++ b/test/unit/recipe/emailpassword/emailPassword.test.tsx
@@ -626,4 +626,18 @@ describe("EmailPassword", function () {
}
}
});
+
+ it("Initializing EmailPassword and return null from getRedirectionURL", async function () {
+ EmailPassword.init({
+ async getRedirectionURL() {
+ return null;
+ },
+ }).authReact(SuperTokens.getInstanceOrThrow().appInfo, false);
+
+ assert(
+ (await EmailPassword.getInstanceOrThrow().getRedirectUrl({ action: "SUCCESS", isNewRecipeUser: false })) ===
+ null
+ );
+ assert((await EmailPassword.getInstanceOrThrow().getRedirectUrl({ action: "RESET_PASSWORD" })) === null);
+ });
});
diff --git a/test/with-typescript/src/App.tsx b/test/with-typescript/src/App.tsx
index 25ee1151f..9931adcc5 100644
--- a/test/with-typescript/src/App.tsx
+++ b/test/with-typescript/src/App.tsx
@@ -1460,3 +1460,44 @@ Multitenancy.init({
}),
},
});
+
+// Testing that 'null' is allowed to be returned from getRedirectionURL
+SuperTokens.init({
+ appInfo: {
+ appName: "",
+ apiDomain: "",
+ websiteDomain: "",
+ },
+
+ async getRedirectionURL(context) {
+ return null;
+ },
+ recipeList: [
+ EmailPassword.init({
+ async getRedirectionURL(context) {
+ return null;
+ },
+ }),
+ ThirdParty.init({
+ async getRedirectionURL(context) {
+ return null;
+ },
+ }),
+ ThirdPartyEmailPassword.init({
+ async getRedirectionURL(context) {
+ return null;
+ },
+ }),
+ EmailVerification.init({
+ async getRedirectionURL(context) {
+ return null;
+ },
+ }),
+ Passwordless.init({
+ contactMethod: "EMAIL",
+ async getRedirectionURL(context) {
+ return null;
+ },
+ }),
+ ],
+});