Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(experience): fix email/phone identifier conflict handling logic during user registration #7041

Merged
merged 2 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .changeset/loud-beds-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
"@logto/experience": patch
---

fix the email/phone identifier conflict handling logic during user registration.

When a user attempts to register with an email/phone that already exists:

### Previous Behavior

"Sign in instead" modal will be shown when:

- The email/phone identifier has been verified through a verification code validation
- Identifier type (email/phone) was enabled in sign-in methods

This caused an issue when:

- Only password authentication method was enabled in the sign-in method settings.
- When users clicked "Sign in instead" action button, the API call will throw an sign-in method not enabled error. Which is confusing for the user.

Expected behavior: Show the "Email/phone already exists" error modal directly. If only password authentication is enabled. User should not be able to sign in with email/phone directly.

### Fixed Behavior

Shows the "Sign in instead" modal if:

- The email/phone identifier type is enabled in the sign-in method settings and the verification code is enabled for the identifier.

Otherwise, shows the "Email/phone already exists" error modal directly.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const useRegisterFlowCodeVerification = (
const navigate = useNavigate();
const redirectTo = useGlobalRedirectTo();

const { signInMode } = useSieMethods();
const { signInMode, signInMethods } = useSieMethods();

const handleError = useErrorHandler();

Expand All @@ -55,8 +55,12 @@ const useRegisterFlowCodeVerification = (
const identifierExistsErrorHandler = useCallback(async () => {
const { type, value } = identifier;

// Should not redirect user to sign-in if is register-only mode
if (signInMode === SignInMode.Register) {
if (
// Should not redirect user to sign-in if is register-only mode
signInMode === SignInMode.Register ||
// Should not redirect user to sign-in if the verification code authentication method is not enabled for sign-in
!signInMethods.find(({ identifier }) => identifier === type)?.verificationCode
) {
void showIdentifierErrorAlert(IdentifierErrorType.IdentifierAlreadyExists, type, value);

return;
Expand Down Expand Up @@ -87,17 +91,18 @@ const useRegisterFlowCodeVerification = (
},
});
}, [
handleError,
identifier,
navigate,
redirectTo,
signInMode,
signInMethods,
show,
t,
showIdentifierErrorAlert,
preSignInErrorHandler,
signInMode,
signInWithIdentifierAsync,
t,
verificationId,
handleError,
preSignInErrorHandler,
redirectTo,
navigate,
]);

const errorHandlers = useMemo<ErrorHandlers>(
Expand Down
38 changes: 20 additions & 18 deletions packages/experience/src/hooks/use-sie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,27 @@ import { type VerificationCodeIdentifier } from '@/types';

export const useSieMethods = () => {
const { experienceSettings } = useContext(PageContext);
const socialSignInSettings = experienceSettings?.socialSignIn ?? {};
const { identifiers, password, verify } = experienceSettings?.signUp ?? {};
const { password, verify } = experienceSettings?.signUp ?? {};

return {
signUpMethods: identifiers ?? [],
signUpSettings: { password, verify },
signInMethods:
experienceSettings?.signIn.methods.filter(
// Filter out empty settings
({ password, verificationCode }) => password || verificationCode
) ?? [],
socialSignInSettings,
socialConnectors: experienceSettings?.socialConnectors ?? [],
ssoConnectors: experienceSettings?.ssoConnectors ?? [],
signInMode: experienceSettings?.signInMode,
forgotPassword: experienceSettings?.forgotPassword,
customContent: experienceSettings?.customContent,
singleSignOnEnabled: experienceSettings?.singleSignOnEnabled,
};
return useMemo(
() => ({
signUpMethods: experienceSettings?.signUp.identifiers ?? [],
signUpSettings: { password, verify },
signInMethods:
experienceSettings?.signIn.methods.filter(
// Filter out empty settings
({ password, verificationCode }) => password || verificationCode
) ?? [],
socialSignInSettings: experienceSettings?.socialSignIn ?? {},
socialConnectors: experienceSettings?.socialConnectors ?? [],
ssoConnectors: experienceSettings?.ssoConnectors ?? [],
signInMode: experienceSettings?.signInMode,
forgotPassword: experienceSettings?.forgotPassword,
customContent: experienceSettings?.customContent,
singleSignOnEnabled: experienceSettings?.singleSignOnEnabled,
}),
[experienceSettings, password, verify]
);
};

export const usePasswordPolicy = () => {
Expand Down
Loading