Improve race condition handling for slow reCAPTCHA load#11451
Conversation
There was a problem hiding this comment.
Does this mean we wait an additional 5 seconds? That seems like a very long time
There was a problem hiding this comment.
The logic here is meant to be a race: Either reCAPTCHA finishes loading in the next 5 seconds (and we cancel this timeout), or the form submits (without the reCAPTCHA token). From a user's perspective, the form will submit as soon as reCAPTCHA is finished its assessment.
We could also just remove this logic, but then it risks reCAPTCHA failing to load altogether and the submission appearing to hang indefinitely. They'll be unsuccessful if they submit without a reCAPTCHA token, but at least it gives them a path forward.
There was a problem hiding this comment.
I think it's important to keep things moving, but my guess is that if the page is responsive enough for the user to submit, but the reCAPTCHA hasn't loaded yet, it probably won't? I would have added like a 1 second delay
There was a problem hiding this comment.
I've got a few other optimizations in the pipeline to drive the load time down further that we could be more aggressive, but I'm hoping this is exceedingly unlikely as it is to not worry too much about it.
changelog: Internal, reCAPTCHA, Improve race condition handling for slow reCAPTCHA load
7271f15 to
69fb875
Compare
|
I did an extra test locally to double-check that it works as expected with a real-world scenario of reCAPTCHA being slow, but eventually loading: Diff, for posterity: diff --git a/app/components/captcha_submit_button_component.html.erb b/app/components/captcha_submit_button_component.html.erb
index 88e7033c4a..f8f10909da 100644
--- a/app/components/captcha_submit_button_component.html.erb
+++ b/app/components/captcha_submit_button_component.html.erb
@@ -36,4 +36,8 @@
).with_content(content) %>
- <% if recaptcha_script_src.present? %>
- <%= content_tag(:script, '', src: recaptcha_script_src, async: true) %>
+ <%= javascript_tag(nonce: true) do %>
+ setTimeout(() => {
+ const script = document.createElement('script');
+ script.src = "<%= recaptcha_script_src %>";
+ document.body.appendChild(script);
+ }, 3000);
<% end %> |
🛠 Summary of changes
Updates
CaptchaSubmitButtonto better handle a scenario where reCAPTCHA is slow to load.Currently, if reCAPTCHA is not loaded by the time the user submits the form, the form will submit immediately, which may produce a failing result from the backend if reCAPTCHA is being enforced.
This is rather unlikely to happen, since the initial reCAPTCHA script is small (roughly 2kb in size), but still technically possible, particularly if someone is using browser extensions or system features to autofill the sign-in form.
The proposed changes here take advantage of documented reCAPTCHA features to "queue" callbacks prior to reCAPTCHA being loaded†, with an additional fallback to submit the form if reCAPTCHA fails to load within a reasonable timeframe (currently 5 seconds).
†: While this feature is not explicitly documented in the reCAPTCHA Enterprise documentation, I've manually confirmed the presence of this queue behavior in the
enterprise.jsscript.📜 Testing Plan
Verify that reCAPTCHA validation is not impacted by these changes:
Configure reCAPTCHA for local development. You can use any credentials, they don't need to be valid.
Verify that the reCAPTCHA script failing to load doesn't prevent form submission:
You can simulate this by removing the reCAPTCHA script from
CaptchaSubmitButtonComponent's markup: