Skip to content

Commit

Permalink
feat!: make passwordless link sent, otp input and mfa screens clear t…
Browse files Browse the repository at this point in the history
…he login attempt info if it is missing some props (#852)
  • Loading branch information
porcellus authored Aug 23, 2024
1 parent 7990896 commit c2190da
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

## [0.46.0] - 2024-08-26

### Breaking changes

- 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.
- Changed `redirectToFactor` to accept an object instead of multiple arguments.
- Changed `redirectToFactorChooser` to accept an object instead of multiple arguments.
- Made MFA related screens do a success redirection if MFA is already completed and the `stepUp` query param is not set to `true`.
Expand Down
11 changes: 11 additions & 0 deletions lib/build/passwordless-shared.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 69 additions & 19 deletions lib/build/passwordlessprebuiltui.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/build/recipe/passwordless/utils.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion lib/ts/recipe/passwordless/components/features/mfa/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import SessionRecipe from "../../../../session/recipe";
import Session from "../../../../session/recipe";
import { defaultPhoneNumberValidator } from "../../../defaultPhoneNumberValidator";
import { getPhoneNumberUtils } from "../../../phoneNumberUtils";
import { checkAdditionalLoginAttemptInfoProperties } from "../../../utils";
import MFAThemeWrapper from "../../themes/mfa";
import { defaultTranslationsPasswordless } from "../../themes/translations";

Expand Down Expand Up @@ -315,7 +316,11 @@ function useOnLoad(

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

if (loginAttemptInfo && props.contactMethod !== loginAttemptInfo.contactMethod) {
if (
loginAttemptInfo &&
(props.contactMethod !== loginAttemptInfo.contactMethod ||
!checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo))
) {
await recipeImplementation?.clearLoginAttemptInfo({ userContext });
loginAttemptInfo = undefined;
}
Expand Down
15 changes: 15 additions & 0 deletions lib/ts/recipe/passwordless/prebuiltui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import UserInputCodeFeature from "./components/features/userInputCode";
import MFAThemeWrapper from "./components/themes/mfa";
import { defaultTranslationsPasswordless } from "./components/themes/translations";
import Passwordless from "./recipe";
import { checkAdditionalLoginAttemptInfoProperties } from "./utils";

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

Expand Down Expand Up @@ -234,6 +242,13 @@ export class PasswordlessPreBuiltUI extends RecipeRouter {
) {
await Passwordless.getInstanceOrThrow().webJSRecipe?.clearLoginAttemptInfo({ userContext });
loginAttemptInfo = undefined;
} else if (!checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo)) {
// If these properties are not set, it means that the user likely started logging in
// using a custom UI and then switched to the pre-built UI. In that case, we should clear
// the login attempt info so that the user is prompted to login again, since the pre-built UI
// requires these properties to be set in order to show the correct UI.
await Passwordless.getInstanceOrThrow().webJSRecipe?.clearLoginAttemptInfo({ userContext });
loginAttemptInfo = undefined;
}
}
if (loginAttemptInfo === undefined || loginAttemptInfo.flowType === "MAGIC_LINK") {
Expand Down
13 changes: 12 additions & 1 deletion lib/ts/recipe/passwordless/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { normaliseAuthRecipe } from "../authRecipe/utils";

import { defaultEmailValidator } from "./validators";

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

Expand Down Expand Up @@ -115,3 +115,14 @@ function normalisePasswordlessBaseConfig<T>(config?: T & FeatureBaseConfig): T &
style,
};
}

export function checkAdditionalLoginAttemptInfoProperties(loginAttemptInfo: LoginAttemptInfo) {
if (
loginAttemptInfo.contactInfo === undefined ||
loginAttemptInfo.contactMethod === undefined ||
loginAttemptInfo.lastResend === undefined
) {
return false;
}
return true;
}

0 comments on commit c2190da

Please sign in to comment.