umbraco / Umbraco.Forms.Issues

Public issue tracker for Umbraco Forms
29 stars 0 forks source link

Recaptcha throws an error when submitting form via the headless api. #1154

Closed jaandrews closed 5 months ago

jaandrews commented 5 months ago

A brief description of the issue goes here.

Reproduction

If you're filing a bug, please describe how to reproduce it. Include as much relevant information as possible, such as:

Bug summary

I upgraded umbraco forms from 11.1.3 to 13.0.1 and have been working on cleaning up the issues caused by breaking changes. There does appear to be an issue with the recaptcha validation that I'm not able to resolve though.

Specifics

When I submit the form via the ajax api, the recaptcha code is submitted, just like any other form field. I've worked out most of the kinks, but the api throws the following error and I'm not sure why.

Could not retrieve the reCAPTCHA v2 respoinse from the non-field form values stored on the HttpContext

This is strange, as the form is not using recaptcha v2. It uses recaptcha v3. The data is also directly submitted along with the other fields and so would not be in the httpContext. I peeked at the Recaptcha2 and Recaptcha3 classes and confirmed that particular error message isn't in either of them, so I'm not sure where it's coming from.

Any idea where this error is coming from and why it's happening?

For reference, I'm running this in umbraco 13.0.3.

Steps to reproduce

  1. Add a recaptcha v3 form field to a form.
  2. Submit the form via the ajax api.
  3. View the response from the api.

Expected result

The form submits successfully.

Actual result

I get the error

Could not retrieve the reCAPTCHA v2 respoinse from the non-field form values stored on the HttpContext
AndyButland commented 5 months ago

So the error message is coming from a base class that both Recaptcha2 and Recaptcha3 use. Clearly we should update the message here so it doesn't mention "v2".

What's going on here is that when you post a form submission, the "non-field" entries - i.e. any form fields that don't correspond to an entry field defined on the form - get saved into the HttpContext.Items collection. They are then read from there in reCAPTCHA processing to find the g-recaptcha-response field.

Please could you share an example payload that you are posting to the API to submit a form, and I'll see from that if I can investigate what isn't working as expected?

jaandrews commented 5 months ago

@AndyButland That's the thing though. The recaptcha is a form field added to each of the umbraco forms in my current installation, so it shouldn't end up on in the HttpContext based on how you explained it. form-with-recaptcha

Here is one example of the data I currently send to the api ("/umbraco/forms/api/v1/entries/{id}").

{
    "values": {
        "name": "Test",
        "zip": "32436",
        "telephone": "43634643",
        "message": "Test",
        "preferredLanguage": "english",
        "recaptcha": "03AFcWeA4JCWFYmSS3yA4pzFJJmybhxE3dv0gA1BGh2DeoflDSqFmoaeYiwaj3uD3uBOBtyoMMutwdOfieFnVHJFWoBkyvsl5213qHV6DHyEEXhOk7YDMNKU3ipn6HmgsWLT30UXcmB6EF1x9k3x4FLJCCh8qpWVx2nbXrvgT4W7t7409znhc23w1n8z_LjhqdcuZelUC8g8n8GbwKEdjREBMg449o0MtgEtt1yylAmx7d2iBUE5302haqJUC409gvTvTaf4mivR68pKlU0wAVot2X016k6UCNvbppmVVxjfq5OPxCguDZlBDz..."
    },
    "contentId": "60ee7557-049d-42d5-b7f6-1ec44e72f4c9"
}

The "recaptcha" value is the token generated by the recaptcha api.

AndyButland commented 5 months ago

I think it should work if you pass the reCAPTCHA response in g-recaptcha-response.

Maybe it would have been better how you have it, but I've looked to mimic the Razor post, and there we don't submit and store the value of the response. Rather we optionally store a score, and use a separate hidden field for the response that needs to be validated server-side.

I've got a gist here that uses vanilla JS to render and submit and form with various field types including reCAPTCHA.

jaandrews commented 5 months ago

I'll give that a whirl and post an update once I've tested it.

jaandrews commented 5 months ago

I replaced the "recaptcha" key with "g-recaptcha-response" and the form now submits successfully. A little counter intuitive, since it differs from the behavior of the other form fields, though I agree that it should be kept consistent with the non ajax behavior. It does make sense if the recaptcha control is added globally instead of adding it to each form via the field control.

AndyButland commented 5 months ago

Thanks for the update. I'll close this issue now then.