Skip to content

LG-8860: Add reCAPTCHA fallback error screen#7826

Merged
aduth merged 5 commits intomainfrom
aduth-lg-8860-recaptcha-errors
Feb 24, 2023
Merged

LG-8860: Add reCAPTCHA fallback error screen#7826
aduth merged 5 commits intomainfrom
aduth-lg-8860-recaptcha-errors

Conversation

@aduth
Copy link
Contributor

@aduth aduth commented Feb 14, 2023

🎫 Ticket

LG-8860

🛠 Summary of changes

Adds fallback error screen handling for reCAPTCHA failure scenario.

📜 Testing Plan

  1. Generate reCAPTCHA credentials for use in your local environment: https://www.google.com/recaptcha/admin/create (Note you will need two sets of credentials, one for v2 and another for v3)
  2. In config/application.yml:
    1. Assign credentials as recaptcha_site_key_v2, recaptcha_site_key_v3, recaptcha_secret_key_v2, and recaptcha_secret_key_v3
    2. Set phone_setup_recaptcha_score_threshold to 1.0
  3. Sign in
  4. Add a phone
  5. Submit a number (e.g. 5135550100 for U.S., 3065550100 for international)
  6. Observe error screen with reCAPTCHA checkbox if entering international number on Step 5, otherwise observe OTP confirmation screen
  7. If presented with error screen with reCAPTCHA checkbox, confirm that clicking checkbox and successfully validating reCAPTCHA proceeds to OTP confirmation screen

👀 Screenshots

Screen Shot 2023-02-14 at 10 48 43 AM

Comment on lines 8 to 10
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we could consider being more restrictive in this logic, specifically in checking that the reason for failure was due to a score falling outside the acceptable range (i.e. disallow failures due to blank or otherwise invalid tokens). One of the challenges with this is that if the user refreshes the page and resubmits the form contents, we'll likely get a timeout-or-duplicate error from the reCAPTCHA service. From the user's perspective, I think they should still have the chance to retry at this point. It has me wondering if should cache the token verification result in Redis for a short time, so we don't have to call out to the external service, and so that we would be able to validate it based on the initial service response.

That being said, it's probably best to save that work for a follow-on ticket.

@aduth aduth force-pushed the aduth-lg-8860-recaptcha-errors branch from bf29ab2 to daac5b0 Compare February 14, 2023 20:38
Copy link
Contributor

Choose a reason for hiding this comment

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

is this fallback page always version 2? is there a way to set this fro a controller or local variable from the form? just to minimize the number of places we hardcode things?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes it is. Although interestingly, Google enforces that the reCAPTCHA keys matches the configured version for the frontend display of the checkbox, but it appears that any reCAPTCHA key can be used for the verification endpoint.

There might be some option to configure this in the controller. One interesting thing is that all of these values will carry over from the previous submission, including recaptcha_version: 3 from the initial challenge. We'd want to make sure that we set that at the right point to make sure that we'd not be populating the wrong version in the form input.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that alternative ends up looking like adding a line before this:

https://github.com/18F/identity-idp/blob/38e3643026574229cda5b230543e927954c3a9c4/app/controllers/users/phones_controller.rb#L23

...as:

@new_phone_form.recaptcha_version = 2

...but it feels a little awkward / unpredictable to modify the form like that ahead of rendering the view? I guess contrasted with how it's implemented here, I'm a bit more comfortable with forcefully overriding the value in the view.

Copy link
Contributor

Choose a reason for hiding this comment

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

just thinking out loud, if this new template is so different from existing stuff, should we add a new controller for it? so we redirect to users/phone_setup/spam_production#index or something?

counterpoint, would we be able to easily link back to the phone setup from that new controller if we did?

Copy link
Contributor Author

@aduth aduth Feb 14, 2023

Choose a reason for hiding this comment

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

Yeah, I noodled on a few different approaches here. One key thing that is hard to do with other approaches is maintaining form values between the initial submission and the subsequent checkbox submission. As implemented here without a redirect, those form values carry over automatically. With a redirect, we'd have to find some other way to save those values (e.g. storing them in session).

@aduth aduth force-pushed the aduth-lg-8860-recaptcha-errors branch from dd43564 to 38e3643 Compare February 15, 2023 20:02
@aduth aduth marked this pull request as ready for review February 15, 2023 20:24
@aduth aduth requested a review from a team February 15, 2023 20:34
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a reason we have to hardcode it like this and not let recaptcha version be passed 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.

The main idea was to limit the set of potential values we'd allow for constructing the RecaptchaValidator class, since we wouldn't want to allow invalid versions, e.g. 4, etc (related spec). Perhaps that should be handled a bit more strictly within the validator class itself, though.

Copy link
Contributor Author

@aduth aduth Feb 23, 2023

Choose a reason for hiding this comment

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

I think I'd like to keep this in the controller, but I also added some extra checks to the validator class in e4f0e1ac6 to add extra assurances that it's initialized correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I refactored this a bit in a7018b44a to extract a few methods for readability, based on team review discussion yesterday that the implied nil score handling from a reCAPTCHA v2 result was not very obvious.

changelog: Upcoming Features, Fraud Mitigation, Implement spam protection for phone registration
Previously it was implied that the nil check for score was associated with recaptcha v2, but this wasn't very obvious. Extract some named methods for clarity
@aduth aduth force-pushed the aduth-lg-8860-recaptcha-errors branch from e4f0e1a to 7a67be7 Compare February 23, 2023 20:48
@aduth aduth merged commit c12b787 into main Feb 24, 2023
@aduth aduth deleted the aduth-lg-8860-recaptcha-errors branch February 24, 2023 14:03
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.

3 participants