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,localizations,shared,types): Prompt user to reset pwned… #3034

Merged
merged 1 commit into from
Mar 29, 2024

Conversation

yourtallness
Copy link
Contributor

… password at sign-in

Description

If admin has enabled password_settings.enforce_on_sign_in and HIBP is enabled, then a password could potentially be detected as pwned at a subsequent sign-in.

The API will respond with error code form_password_pwned, in which case we will show a corresponding error and show the alternative method list, prompting them to reset their password.

Checklist

  • npm test runs as expected.
  • npm run build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Copy link

changeset-bot bot commented Mar 22, 2024

🦋 Changeset detected

Latest commit: a95a202

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@clerk/localizations Minor
@clerk/clerk-js Minor
@clerk/shared Minor
@clerk/types Minor
@clerk/chrome-extension Patch
@clerk/clerk-expo Patch
@clerk/backend Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/clerk-react Patch
@clerk/remix Patch
@clerk/clerk-sdk-node Patch
gatsby-plugin-clerk Patch
@clerk/themes Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@@ -135,6 +138,10 @@ export function _SignInFactorOne(): JSX.Element {
}}
onForgotPasswordMethodClick={resetPasswordFactor ? toggleForgotPasswordStrategies : toggleAllStrategies}
onShowAlternativeMethodsClick={toggleAllStrategies}
onPasswordPwned={() => {
setIsPasswordPwned(true);
toggleForgotPasswordStrategies();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could potentially also trigger the reset flow to start, but preferred to allow them to click it themselves.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

@@ -40,12 +41,13 @@ const usePasswordControl = (props: SignInFactorOnePasswordProps) => {
: onShowAlternativeMethodsClick
? onShowAlternativeMethodsClick
: () => null,
// onPasswordPwned,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assumed I would need to include it here as were, but this causes the following error:

Warning: Unknown event handler property onPasswordPwned. It will be ignored.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why you need it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me neither :-D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@desiprisg do we not need to export is like the other handlers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we don't need it, can we remove the comment ?

@@ -58,6 +60,7 @@ export const SignInFactorOnePasswordCard = (props: SignInFactorOnePasswordProps)
const clerk = useClerk();

const goBack = () => {
card.setError(undefined);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work, the error is not cleared.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, this was not the correct location to do it.

@@ -83,6 +86,14 @@ export const SignInFactorOnePasswordCard = (props: SignInFactorOnePasswordProps)
return clerk.__internal_navigateWithError('..', err.errors[0]);
}

if (isPasswordPwnedError(err)) {
if (onPasswordPwned) {
card.setError({ ...err.errors[0], code: err.errors[0].code + '__sign_in' });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add a suffix to target the l10n key we want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say just hardcode it here since the type will always be the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

@@ -83,6 +86,14 @@ export const SignInFactorOnePasswordCard = (props: SignInFactorOnePasswordProps)
return clerk.__internal_navigateWithError('..', err.errors[0]);
}

if (isPasswordPwnedError(err)) {
if (onPasswordPwned) {
card.setError({ ...err.errors[0], code: err.errors[0].code + '__sign_in' });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say just hardcode it here since the type will always be the same.

@@ -58,6 +60,7 @@ export const SignInFactorOnePasswordCard = (props: SignInFactorOnePasswordProps)
const clerk = useClerk();

const goBack = () => {
card.setError(undefined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we ignore undefined ? Or maybe there's a function to clear the error? Could you check the implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It worked when I moved it to the proper back handlers.

@@ -40,12 +41,13 @@ const usePasswordControl = (props: SignInFactorOnePasswordProps) => {
: onShowAlternativeMethodsClick
? onShowAlternativeMethodsClick
: () => null,
// onPasswordPwned,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why you need it here?

@@ -135,6 +138,10 @@ export function _SignInFactorOne(): JSX.Element {
}}
onForgotPasswordMethodClick={resetPasswordFactor ? toggleForgotPasswordStrategies : toggleAllStrategies}
onShowAlternativeMethodsClick={toggleAllStrategies}
onPasswordPwned={() => {
setIsPasswordPwned(true);
toggleForgotPasswordStrategies();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

@yourtallness yourtallness force-pushed the yourtallness/hibp_on_sign_in branch 2 times, most recently from e98fd3d to 2503592 Compare March 27, 2024 17:17
@yourtallness yourtallness marked this pull request as ready for review March 27, 2024 17:17
@yourtallness yourtallness force-pushed the yourtallness/hibp_on_sign_in branch 2 times, most recently from 2982469 to f5198a2 Compare March 28, 2024 10:43
Copy link
Contributor

@desiprisg desiprisg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we could also get a couple of tests in to make sure this functionality doesn't break in the future, that would be superb!

Edit: Was looking at a commit. Re-reviewing..

@yourtallness
Copy link
Contributor Author

If we could also get a couple of tests in to make sure this functionality doesn't break in the future, that would be superb!

I have added 2 tests (phone + pwned, email + pwned), can you recommend more scenarios?

@@ -40,12 +41,13 @@ const usePasswordControl = (props: SignInFactorOnePasswordProps) => {
: onShowAlternativeMethodsClick
? onShowAlternativeMethodsClick
: () => null,
// onPasswordPwned,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we don't need it, can we remove the comment ?

@@ -67,6 +67,10 @@ export function isUserLockedError(err: any) {
return isClerkAPIResponseError(err) && err.errors?.[0]?.code === 'user_locked';
}

export function isPasswordPwnedError(err: any) {
return isClerkAPIResponseError(err) && err.errors?.[0]?.code === 'form_password_pwned';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we use the first error item ? Will this always be the case from FAPI ? I see that we are doing the same above, just asking tho.

@yourtallness yourtallness merged commit fc3ffd8 into main Mar 29, 2024
10 checks passed
@yourtallness yourtallness deleted the yourtallness/hibp_on_sign_in branch March 29, 2024 11:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants