({
- // userContext,
- // });
- // }
}
- // if (deviceInfo && !isAllowedToSetup) {
- // await recipeImpl.removeDevice({ deviceName: deviceInfo.deviceName, userContext });
- // deviceInfo = undefined;
- // }
// No need to check if the component is unmounting, since this has no effect then.
dispatch({ type: "load", deviceInfo, error });
@@ -189,6 +189,27 @@ export function useChildProps(
onShowSecretClick: () => {
dispatch({ type: "showSecret" });
},
+ onBackButtonClicked: async () => {
+ if (state.deviceInfo) {
+ await recipeImplementation.removeDevice({
+ deviceName: state.deviceInfo.deviceName,
+ userContext,
+ });
+ }
+ // If we don't have history available this would mean we are not using react-router-dom, so we use window's history
+ if (history === undefined) {
+ return WindowHandlerReference.getReferenceOrThrow().windowHandler.getWindowUnsafe().history.back();
+ }
+ // If we do have history and goBack function on it this means we are using react-router-dom v5 or lower
+ if (history.goBack !== undefined) {
+ return history.goBack();
+ }
+ // If we reach this code this means we are using react-router-dom v6
+ return history(-1);
+ },
+ onRetryClicked() {
+ dispatch({ type: "restartFlow", error: undefined });
+ },
onSuccess: () => {
const redirectToPath = getRedirectToPathFromURL();
const redirectInfo =
@@ -293,7 +314,11 @@ function getModifiedRecipeImplementation(
const res = await originalImpl.verifyCode(input);
if (res.status === "LIMIT_REACHED_ERROR") {
- dispatch({ type: "setBlocked", error: "ERROR_SIGN_IN_UP_CODE_VERIFY_BLOCKED", nextRetryAt: Date.now() + res.retryAfterMs });
+ dispatch({
+ type: "setBlocked",
+ error: "ERROR_SIGN_IN_UP_CODE_VERIFY_BLOCKED",
+ nextRetryAt: Date.now() + res.retryAfterMs,
+ });
} else if (res.status === "INVALID_TOTP_ERROR") {
dispatch({ type: "setError", error: "ERROR_SIGN_IN_UP_CODE_VERIFY_INVALID_TOTP" });
}
@@ -305,7 +330,11 @@ function getModifiedRecipeImplementation(
const res = await originalImpl.verifyDevice(input);
if (res.status === "LIMIT_REACHED_ERROR") {
- dispatch({ type: "setBlocked", error: "ERROR_TOTP_MFA_VERIFY_DEVICE_BLOCKED", nextRetryAt: Date.now() + res.retryAfterMs });
+ dispatch({
+ type: "setBlocked",
+ error: "ERROR_TOTP_MFA_VERIFY_DEVICE_BLOCKED",
+ nextRetryAt: Date.now() + res.retryAfterMs,
+ });
} else if (res.status === "INVALID_TOTP_ERROR") {
dispatch({ type: "setError", error: "ERROR_TOTP_MFA_VERIFY_DEVICE_INVALID_TOTP" });
} else if (res.status === "UNKNOWN_DEVICE_ERROR") {
diff --git a/lib/ts/recipe/totp/components/themes/mfa/blockedScreen.tsx b/lib/ts/recipe/totp/components/themes/mfa/blockedScreen.tsx
index 4d77f9fe6..7570be1dd 100644
--- a/lib/ts/recipe/totp/components/themes/mfa/blockedScreen.tsx
+++ b/lib/ts/recipe/totp/components/themes/mfa/blockedScreen.tsx
@@ -16,7 +16,7 @@ import { BlockedIcon } from "../../../../../components/assets/blockedIcon";
import { withOverride } from "../../../../../components/componentOverride/withOverride";
import { useTranslation } from "../../../../../translation/translationContext";
-const TOTPBlockedScreen: React.FC = (props: { onRestartClicked: () => void }) => {
+const TOTPBlockedScreen: React.FC = () => {
const t = useTranslation();
return (
@@ -25,9 +25,8 @@ const TOTPBlockedScreen: React.FC = (props: { onRestartClicked: () => void }) =>
{t("TOTP_BLOCKED_TITLE")}
-
- {t("TOTP_BLOCKED_SUBTITLE")}
-
+ {t("TOTP_BLOCKED_SUBTITLE")}
+
);
diff --git a/lib/ts/recipe/totp/components/themes/mfa/totpDeviceInfoSection.tsx b/lib/ts/recipe/totp/components/themes/mfa/totpDeviceInfoSection.tsx
index 8b9a16824..8b30bf113 100644
--- a/lib/ts/recipe/totp/components/themes/mfa/totpDeviceInfoSection.tsx
+++ b/lib/ts/recipe/totp/components/themes/mfa/totpDeviceInfoSection.tsx
@@ -13,12 +13,13 @@
* under the License.
*/
+import QRCode from "react-qr-code";
+
import { withOverride } from "../../../../../components/componentOverride/withOverride";
+import { useTranslation } from "../../../../../translation/translationContext";
import type { TOTPMFACommonProps } from "../../../types";
import type { DeviceInfo } from "supertokens-web-js/recipe/totp";
-import QRCode from "react-qr-code";
-import { useTranslation } from "../../../../../translation/translationContext";
export const DeviceInfoSection = withOverride(
"TOTPDeviceInfoSection",
diff --git a/lib/ts/recipe/totp/components/themes/translations.ts b/lib/ts/recipe/totp/components/themes/translations.ts
index faacc5a7c..8c0a3b14e 100644
--- a/lib/ts/recipe/totp/components/themes/translations.ts
+++ b/lib/ts/recipe/totp/components/themes/translations.ts
@@ -16,5 +16,7 @@ export const defaultTranslationsTOTP = {
TOTP_CODE_INPUT_LABEL: "Please enter TOTP from the app",
TOTP_CODE_CONTINUE_BUTTON: "Continue",
TOTP_REMOVE_DEVICE_LINK: "Choose another factor",
+ TOTP_BLOCKED_TITLE: "Account locked",
+ TOTP_BLOCKED_SUBTITLE: "Account locked due to multiple failed login attempts.",
},
};
diff --git a/lib/ts/recipe/totp/recipe.tsx b/lib/ts/recipe/totp/recipe.tsx
index c49c45a5c..0c7345719 100644
--- a/lib/ts/recipe/totp/recipe.tsx
+++ b/lib/ts/recipe/totp/recipe.tsx
@@ -25,6 +25,7 @@ import { OTPIcon } from "../../components/assets/otpIcon";
import { SSR_ERROR } from "../../constants";
import MultiFactorAuth from "../multifactorauth/recipe";
import RecipeModule from "../recipeModule";
+import Session from "../session/recipe";
import { DEFAULT_TOTP_PATH } from "./constants";
import { getFunctionOverrides } from "./functionOverrides";
@@ -39,7 +40,6 @@ import type {
} from "./types";
import type { NormalisedConfigWithAppInfoAndRecipeID, RecipeInitResult, WebJSRecipeInterface } from "../../types";
import type { NormalisedAppInfo } from "../../types";
-import Session from "../session/recipe";
export default class TOTP extends RecipeModule<
GetRedirectionURLContext,
diff --git a/lib/ts/recipe/totp/types.ts b/lib/ts/recipe/totp/types.ts
index cf736bf85..3c65e2a78 100644
--- a/lib/ts/recipe/totp/types.ts
+++ b/lib/ts/recipe/totp/types.ts
@@ -102,17 +102,6 @@ export type TOTPMFAScreenConfig = {
loadingScreenStyle: string; // TODO: ??
};
-/**
- * When calling getLoginAttemptInfo/setLoginAttemptInfo from web-js we use generics to get
- * access to properties in local storage that web-js does not set by default.
- * This allows us to strongly type the response while keeping it dynamic.
- *
- * In the context of auth-react this type indicates all the additional properties we need.
- */
-export type AdditionalDeviceInfoProperties = {
- redirectToPath?: string;
-};
-
// Config is what does in the constructor of the recipe.
export type UserInput = {
totpMFAScreen?: Partial;