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

🐞🔨Authentication Prevent race condition when double-tapping sign-in #1892

Merged
merged 2 commits into from
Oct 14, 2023

Conversation

zspencer
Copy link
Member

OK, so my working assumption is that the bug is caused by two requests being processed at the same time for a new email address, and the first one creates the AuthenticationMethod and the second one tries to, and fails; resulting in the validation error.

This requeries the database and retries the rest of the work.

Would love to have names for methods to pull this out into, rather than copy-pasting the method body but oh well.

@zspencer zspencer requested review from a team October 12, 2023 01:18
@zspencer zspencer changed the title 🐞🔨Authentication Prevent a condition when double-tapping sign-in 🐞🔨Authentication Prevent race condition when double-tapping sign-in Oct 12, 2023
Copy link
Member

@anaulin anaulin left a comment

Choose a reason for hiding this comment

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

Looks good!

This makes me wonder if it might be worth it adding a "disable after submit" thing to some (all?) of our submit buttons. It's a little tricky, though, to make sure that we don't end up with disabled buttons on e.g. a form with errors.

@@ -45,6 +45,16 @@ def save
end

false
rescue ActiveRecord::RecordInvalid
self.authentication_method = nil
if one_time_password.nil?
Copy link
Member

Choose a reason for hiding this comment

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

I suppose you could extract lines 38-44 into a method called, say verify_or_resend_otp, and then this save method would become something like:

def save
  return false if !valid? || !actionable?
  verify_or_resend_otp
rescue ActiveRecord::RecordInvalid
  # Retry in case of race condition
  self.authentication_method = nil
  verify_or_resend_otp
end

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a better name than what I came up with on my own; so I'll do that.

@@ -45,6 +45,16 @@ def save
end

false
Copy link
Member

Choose a reason for hiding this comment

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

I know this is not from this PR, but I think this false never did anything -- the if/else above will always return before this line is executed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh that's a good point!

@anaulin
Copy link
Member

anaulin commented Oct 12, 2023

And for completeness: a different approach, if we think this is due to simultaneous submissions, we could consider using some kind of locking mechanism. Seems overkill for now, though.

@zspencer
Copy link
Member Author

And for completeness: a different approach, if we think this is due to simultaneous submissions, we could consider using some kind of locking mechanism. Seems overkill for now, though.

This is due to simultaneous first-time submissions. I.e. if you attempt to sign in as [email protected] for the first time and double-click the button; the error will occur.

It does not appear to occur with second-times; as the authentication method is already in the database so double-clicking will just double-email.

This makes me wonder if it might be worth it adding a "disable after submit" thing to some (all?) of our submit buttons. It's a little tricky, though, to make sure that we don't end up with disabled buttons on e.g. a form with errors.

I could have sworn there was something like that built into rails, but maybe it was part of ujs and isn't in turbo yet...

@anaulin
Copy link
Member

anaulin commented Oct 12, 2023

I could have sworn there was something like that built into rails, but maybe it was part of ujs and isn't in turbo yet...

Me too, and I googled a bunch and couldn't find anything. Something about "disable with"??? But couldn't find it. 🤷🏼‍♀️

- #1809

OK, so my working assumption is that the bug is caused by two requests
being processed at the same time for a new email address, and the first
one creates the `AuthenticationMethod` and the second one *tries* to,
and fails; resulting in the validation error.

This requeries the database and retries the rest of the work.

Would love to have names for methods to pull this out into, rather than
copy-pasting the method body but oh well.
@zspencer zspencer force-pushed the authentication/fix-the-other-weird-sign-in-bug branch from f931f7d to 8586db7 Compare October 14, 2023 03:10
@zspencer zspencer merged commit 8c6c880 into main Oct 14, 2023
4 checks passed
@zspencer zspencer deleted the authentication/fix-the-other-weird-sign-in-bug branch October 14, 2023 03:16
rosschapman pushed a commit that referenced this pull request Oct 23, 2023
…#1892)

* 🐞🔨`Authentication` Prevent a condition when double-tapping sign-in

- #1809

OK, so my working assumption is that the bug is caused by two requests
being processed at the same time for a new email address, and the first
one creates the `AuthenticationMethod` and the second one *tries* to,
and fails; resulting in the validation error.

This requeries the database and retries the rest of the work.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants