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

feat(clerk-js,shared,types,localizations): New client_mismatch status for email link sign in/up #3367

Merged
merged 2 commits into from
May 14, 2024
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
5 changes: 5 additions & 0 deletions .changeset/chilled-laws-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/localizations': minor
---

Added new keys for email link verification under `signIn.emailLink.clientMismatch` and `signUp.emailLink.clientMismatch`
7 changes: 7 additions & 0 deletions .changeset/tricky-tomatoes-repair.md
LekoArts marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@clerk/clerk-js': minor
'@clerk/shared': minor
'@clerk/types': minor
---

Introduce new `client_mismatch` verification status for email link sign-in and sign-up. This error (and its message) will be shown if a verification link was opened in another device/browser from which the user initiated the sign-in/sign-up attempt. This functionality needs to be enabled in the Clerk dashboard.
2 changes: 2 additions & 0 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,8 @@ export class Clerk implements ClerkInterface {
const verificationStatus = getClerkQueryParam('__clerk_status');
if (verificationStatus === 'expired') {
throw new EmailLinkError(EmailLinkErrorCode.Expired);
} else if (verificationStatus === 'client_mismatch') {
throw new EmailLinkError(EmailLinkErrorCode.ClientMismatch);
} else if (verificationStatus !== 'verified') {
throw new EmailLinkError(EmailLinkErrorCode.Failed);
}
Expand Down
8 changes: 8 additions & 0 deletions packages/clerk-js/src/ui/common/EmailLinkCompleteFlowCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const signInLocalizationKeys = {
title: localizationKeys('signIn.emailLink.expired.title'),
subtitle: localizationKeys('signIn.emailLink.expired.subtitle'),
},
client_mismatch: {
title: localizationKeys('signIn.emailLink.clientMismatch.title'),
subtitle: localizationKeys('signIn.emailLink.clientMismatch.subtitle'),
},
};

const signUpLocalizationKeys = {
Expand All @@ -40,6 +44,10 @@ const signUpLocalizationKeys = {
...signInLocalizationKeys.loading,
title: localizationKeys('signUp.emailLink.loading.title'),
},
client_mismatch: {
...signInLocalizationKeys.client_mismatch,
subtitle: localizationKeys('signUp.emailLink.clientMismatch.subtitle'),
},
};

export const SignInEmailLinkFlowComplete = withCardStateProvider((props: Omit<EmailLinkVerifyProps, 'texts'>) => {
Expand Down
2 changes: 2 additions & 0 deletions packages/clerk-js/src/ui/common/EmailLinkStatusCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const StatusToIcon: Record<Exclude<VerificationStatus, 'loading'>, React.Compone
verified_switch_tab: SwitchArrows,
expired: ExclamationTriangle,
failed: ExclamationTriangle,
client_mismatch: ExclamationTriangle,
};

const statusToColor = (theme: InternalTheme, status: Exclude<VerificationStatus, 'loading'>) =>
Expand All @@ -28,6 +29,7 @@ const statusToColor = (theme: InternalTheme, status: Exclude<VerificationStatus,
verified_switch_tab: theme.colors.$primary500,
expired: theme.colors.$warning500,
failed: theme.colors.$danger500,
client_mismatch: theme.colors.$warning500,
}[status]);

export const EmailLinkStatusCard = (props: EmailLinkStatusCardProps) => {
Expand Down
3 changes: 3 additions & 0 deletions packages/clerk-js/src/ui/common/EmailLinkVerify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const EmailLinkVerify = (props: EmailLinkVerifyProps) => {
if (isEmailLinkError(err) && err.code === EmailLinkErrorCode.Expired) {
status = 'expired';
}
if (isEmailLinkError(err) && err.code === EmailLinkErrorCode.ClientMismatch) {
status = 'client_mismatch';
}
setVerificationStatus(status);
}
};
Expand Down
8 changes: 7 additions & 1 deletion packages/clerk-js/src/utils/getClerkQueryParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ type ClerkQueryParamsToValuesMap = {
__clerk_help: string;
};

export type VerificationStatus = 'expired' | 'failed' | 'loading' | 'verified' | 'verified_switch_tab';
export type VerificationStatus =
| 'expired'
| 'failed'
| 'loading'
| 'verified'
| 'verified_switch_tab'
| 'client_mismatch';

export function getClerkQueryParam<T extends ClerkQueryParam>(param: T): ClerkQueryParamsToValuesMap[T] | null {
const val = new URL(window.location.href).searchParams.get(param);
Expand Down
10 changes: 10 additions & 0 deletions packages/localizations/src/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,11 @@ export const enUS: LocalizationResource = {
subtitleNewTab: 'Return to the newly opened tab to continue',
titleNewTab: 'Signed in on other tab',
},
clientMismatch: {
subtitle:
'To continue, open the verification link on the device and browser from which you initiated the sign-in',
title: 'Verification link is invalid for this device',
},
},
forgotPassword: {
formTitle: 'Reset password code',
Expand Down Expand Up @@ -426,6 +431,11 @@ export const enUS: LocalizationResource = {
subtitleNewTab: 'Return to previous tab to continue',
title: 'Successfully verified email',
},
clientMismatch: {
subtitle:
'To continue, open the verification link on the device and browser from which you initiated the sign-up',
title: 'Verification link is invalid for this device',
},
},
phoneCode: {
formSubtitle: 'Enter the verification code sent to your phone number',
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export function isEmailLinkError(err: Error): err is EmailLinkError {
export const EmailLinkErrorCode = {
Expired: 'expired',
Failed: 'failed',
ClientMismatch: 'client_mismatch',
};

const DefaultMessages = Object.freeze({
Expand Down
8 changes: 8 additions & 0 deletions packages/types/src/localization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ type _LocalizationResource = {
subtitle: LocalizationValue;
subtitleNewTab: LocalizationValue;
};
clientMismatch: {
title: LocalizationValue;
subtitle: LocalizationValue;
};
};
emailCode: {
title: LocalizationValue;
Expand Down Expand Up @@ -221,6 +225,10 @@ type _LocalizationResource = {
title: LocalizationValue;
subtitle: LocalizationValue;
};
clientMismatch: {
title: LocalizationValue;
subtitle: LocalizationValue;
};
};
phoneCode: {
title: LocalizationValue;
Expand Down
Loading