Skip to content

Commit c2190da

Browse files
authored
feat!: make passwordless link sent, otp input and mfa screens clear the login attempt info if it is missing some props (#852)
1 parent 7990896 commit c2190da

File tree

7 files changed

+118
-22
lines changed

7 files changed

+118
-22
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [unreleased]
99

10+
## [0.46.0] - 2024-08-26
11+
1012
### Breaking changes
1113

14+
- The prebuilt UI now clears the login attempt info if the stored data doesn't contain all the required properties. This should help migration from a custom UI to the prebuilt UI.
1215
- Changed `redirectToFactor` to accept an object instead of multiple arguments.
1316
- Changed `redirectToFactorChooser` to accept an object instead of multiple arguments.
1417
- Made MFA related screens do a success redirection if MFA is already completed and the `stepUp` query param is not set to `true`.

lib/build/passwordless-shared.js

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/passwordlessprebuiltui.js

Lines changed: 69 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/recipe/passwordless/utils.d.ts

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/ts/recipe/passwordless/components/features/mfa/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import SessionRecipe from "../../../../session/recipe";
4343
import Session from "../../../../session/recipe";
4444
import { defaultPhoneNumberValidator } from "../../../defaultPhoneNumberValidator";
4545
import { getPhoneNumberUtils } from "../../../phoneNumberUtils";
46+
import { checkAdditionalLoginAttemptInfoProperties } from "../../../utils";
4647
import MFAThemeWrapper from "../../themes/mfa";
4748
import { defaultTranslationsPasswordless } from "../../themes/translations";
4849

@@ -315,7 +316,11 @@ function useOnLoad(
315316

316317
const factorId = props.contactMethod === "EMAIL" ? FactorIds.OTP_EMAIL : FactorIds.OTP_PHONE;
317318

318-
if (loginAttemptInfo && props.contactMethod !== loginAttemptInfo.contactMethod) {
319+
if (
320+
loginAttemptInfo &&
321+
(props.contactMethod !== loginAttemptInfo.contactMethod ||
322+
!checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo))
323+
) {
319324
await recipeImplementation?.clearLoginAttemptInfo({ userContext });
320325
loginAttemptInfo = undefined;
321326
}

lib/ts/recipe/passwordless/prebuiltui.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import UserInputCodeFeature from "./components/features/userInputCode";
1818
import MFAThemeWrapper from "./components/themes/mfa";
1919
import { defaultTranslationsPasswordless } from "./components/themes/translations";
2020
import Passwordless from "./recipe";
21+
import { checkAdditionalLoginAttemptInfoProperties } from "./utils";
2122

2223
import type { AdditionalLoginAttemptInfoProperties, LoginAttemptInfo } from "./types";
2324
import type { GenericComponentOverrideMap } from "../../components/componentOverride/componentOverrideContext";
@@ -187,6 +188,13 @@ export class PasswordlessPreBuiltUI extends RecipeRouter {
187188
) {
188189
await Passwordless.getInstanceOrThrow().webJSRecipe?.clearLoginAttemptInfo({ userContext });
189190
loginAttemptInfo = undefined;
191+
} else if (!checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo)) {
192+
// If these properties are not set, it means that the user likely started logging in
193+
// using a custom UI and then switched to the pre-built UI. In that case, we should clear
194+
// the login attempt info so that the user is prompted to login again, since the pre-built UI
195+
// requires these properties to be set in order to show the correct UI.
196+
await Passwordless.getInstanceOrThrow().webJSRecipe?.clearLoginAttemptInfo({ userContext });
197+
loginAttemptInfo = undefined;
190198
}
191199
}
192200

@@ -234,6 +242,13 @@ export class PasswordlessPreBuiltUI extends RecipeRouter {
234242
) {
235243
await Passwordless.getInstanceOrThrow().webJSRecipe?.clearLoginAttemptInfo({ userContext });
236244
loginAttemptInfo = undefined;
245+
} else if (!checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo)) {
246+
// If these properties are not set, it means that the user likely started logging in
247+
// using a custom UI and then switched to the pre-built UI. In that case, we should clear
248+
// the login attempt info so that the user is prompted to login again, since the pre-built UI
249+
// requires these properties to be set in order to show the correct UI.
250+
await Passwordless.getInstanceOrThrow().webJSRecipe?.clearLoginAttemptInfo({ userContext });
251+
loginAttemptInfo = undefined;
237252
}
238253
}
239254
if (loginAttemptInfo === undefined || loginAttemptInfo.flowType === "MAGIC_LINK") {

lib/ts/recipe/passwordless/utils.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { normaliseAuthRecipe } from "../authRecipe/utils";
1717

1818
import { defaultEmailValidator } from "./validators";
1919

20-
import type { Config, NormalisedConfig, SignInUpFeatureConfigInput } from "./types";
20+
import type { Config, LoginAttemptInfo, NormalisedConfig, SignInUpFeatureConfigInput } from "./types";
2121
import type { FeatureBaseConfig, NormalisedBaseConfig } from "../../types";
2222
import type { RecipeInterface } from "supertokens-web-js/recipe/passwordless";
2323

@@ -115,3 +115,14 @@ function normalisePasswordlessBaseConfig<T>(config?: T & FeatureBaseConfig): T &
115115
style,
116116
};
117117
}
118+
119+
export function checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo: LoginAttemptInfo) {
120+
if (
121+
loginAttemptInfo.contactInfo === undefined ||
122+
loginAttemptInfo.contactMethod === undefined ||
123+
loginAttemptInfo.lastResend === undefined
124+
) {
125+
return false;
126+
}
127+
return true;
128+
}

0 commit comments

Comments
 (0)