aryehraber / statamic-captcha

Statamic Addon that protects your Statamic forms using a Captcha service.
MIT License
11 stars 8 forks source link

Usage with half method caching and nocache #49

Closed bfaulkner-champions closed 1 year ago

bfaulkner-champions commented 1 year ago

release: dev-dev (also tried on latest) statamic: v3.4.9

I have a form that I need to use a captcha on, and the client has asked for reCaptcha. The form HTML currently looks like this:

{{ nocache }}
    {{ form:set in="get_in_touch" }}
        {{ if form:errors }}
                {{ form:errors }}
                    {{ value }}<br>
                {{ /form:errors }}
        {{ /if }}
        {{ form:create  js="alpine" id="contactForm" redirect="/thank-you" }}  
            <div>
                {{ fields }}
                    <template x-if="{{ show_field }}">
                        <div>
                            <label for="form_{{ handle }}">{{ display }}</label>
                            {{ field }}
                        </div>
                    </template>
                {{ /fields }}
            </div>

            <input type="text" class="hidden" name="{{ honeypot ?? 'honeypot' }}">
            <div>
                <div class="captcha">
                    {{ if config:captcha:enabled }}
                        {{ captcha }}
                    {{ /if }}
                </div>
            </div>
            <button form="contactForm" type="submit">
                <i class="fa fa-spinner fa-spin hidden" id="loading-icon"></i>
                <span class="btn-text" id="btn-text">Submit Message</span>
            </button>
        {{ /form:create }}
    {{ /form:set }}
{{ /nocache }}

As you can see during debugging I've updated the config slightly to look like the one below, this was so I could easily check it was the captcha plugin causing the issue.

return [
    'enabled' => env('CAPTCHA_ENABLED', false), // true/false
    'service' => env('CAPTCHA_PROVIDER', 'Recaptcha'), // options: Recaptcha / Hcaptcha
    'sitekey' => env('CAPTCHA_SITEKEY', ''),
    'secret' => env('CAPTCHA_SECRET', ''),
    //'collections' => [],
    'forms' => env('CAPTCHA_ENABLED', false) == false ? [] : 'all',
    'user_login' => false,
    'user_registration' => false,
    'disclaimer' => '',
    'invisible' => false,
    'hide_badge' => false,
    'enable_api_routes' => false,
];

I've also updated the replacer to have the one mentioned in https://github.com/aryehraber/statamic-captcha/issues/45

    'replacers' => [
        Statamic\StaticCaching\Replacers\CsrfTokenReplacer::class,
        Statamic\StaticCaching\Replacers\NoCacheReplacer::class,
        \AryehRaber\Captcha\CaptchaReplacer::class
    ]

The response I get is simply "Captcha failed" and it reloads the page with the form.

aryehraber commented 1 year ago

Hi @bfaulkner-champions, thanks for the info!

Firstly, I didn't know there was a {{ config:... }} tag that you could use like that, neat!

I don't see it here so just want to make sure you also have the {{ captcha:head }} tag in the <head> section of your main layout?

Also, are you submitting the form using default form submission behaviour or are you submitting via JS?

bfaulkner-champions commented 1 year ago

Hi @aryehraber and thanks for getting back to me so quickly,

Yes we have the captcha:head tag inside of head, without the half measure, the form submits correctly.

We're using conventional submission on this form - we have an identical one which we use JS on though as it's in a modal, so both are valid!

aryehraber commented 1 year ago

Hmm ok, interesting that it works as expected without caching enabled.

Can you check the rendered HTML when half measure caching is enabled -- does the captcha tag in the form look correct?

bfaulkner-champions commented 1 year ago

To me it looks about right:

<div class="captcha"><div class="g-recaptcha" data-sitekey="......"><div style="width: 304px; height: 78px;"><div><iframe title="reCAPTCHA" src="https://www.google.com/recaptcha/api2/anchor?ar=1&amp;k=...&amp;co=aHR0cHM6Ly9pbmZsdWVuY2VybWF0Y2htYWtlci50ZXN0OjQ0Mw..&amp;hl=en&amp;v=1h-hbVSJRMOQsmO_2qL9cO0z&amp;size=normal&amp;cb=730j9lfzdrp0" width="304" height="78" role="presentation" name="a-270y3wlnoqri" frameborder="0" scrolling="no" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation allow-modals allow-popups-to-escape-sandbox"></iframe></div><textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 40px; border: 1px solid rgb(193, 193, 193); margin: 10px 25px; padding: 0px; resize: none; display: none;"></textarea></div><iframe style="display: none;"></iframe></div> </div>
aryehraber commented 1 year ago

I just tested this myself locally and also hit an issue (potentially the same as you?).

I turned half measure on and refreshed the browser a few times, my reCAPTCHA field disappeared from the page and as a result the form failed to submit every time.

I have the latest Captcha installed and still had the Replacer configured too. After removing the Replacer and clearing Statamic's cache it started working again.

Would you mind trying removing the CaptchaReplacer from config/statamic/static_caching.php, clearing Statamic's application cache using php please cache:clear, and refreshing the browser to try again?

bfaulkner-champions commented 1 year ago

No change for me - sorry!

aryehraber commented 1 year ago

Hmm I'm not sure in that case, hard to debug without being able to fiddle with the code myself. If you are able and open to give me temporary access to the codebase I'd be happy to take a closer look, otherwise I'm not sure what else to suggest at this time.

bfaulkner-champions commented 1 year ago

Hmm I'm not sure in that case, hard to debug without being able to fiddle with the code myself. If you are able and open to give me temporary access to the codebase I'd be happy to take a closer look, otherwise I'm not sure what else to suggest at this time.

Can do - it's on bitbucket if you have an account there?

bfaulkner-champions commented 1 year ago

Also, this is the object when returning invalid, if that helps?

^ AryehRaber\Captcha\Recaptcha {#6360 ▼
  #client: GuzzleHttp\Client {#5799 ▼
    -config: array:8 [▼
      "http_errors" => false
      "handler" => GuzzleHttp\HandlerStack {#6310 ▼
        -handler: Closure(RequestInterface $request, array $options): PromiseInterface {#6359 ▼
          returnType: "GuzzleHttp\Promise\PromiseInterface"
          class: "GuzzleHttp\Handler\Proxy"
          use: {▶}
        }
        -stack: array:4 [▶]
        -cached: Closure($request, array $options) {#5718 ▼
          class: "GuzzleHttp\Middleware"
          use: {▶}
        }
      }
      "allow_redirects" => array:5 [▼
        "max" => 5
        "protocols" => array:2 [▼
          0 => "http"
          1 => "https"
        ]
        "strict" => false
        "referer" => false
        "track_redirects" => false
      ]
      "decode_content" => true
      "verify" => true
      "cookies" => false
      "idn_conversion" => false
      "headers" => array:1 [▶]
    ]
  }
  #data: Illuminate\Support\Collection {#5713 ▼
    #items: array:2 [▼
      "success" => false
      "error-codes" => array:1 [▼
        0 => "timeout-or-duplicate"
      ]
    ]
    #escapeWhenCastingToString: false
  }
}
aryehraber commented 1 year ago

I think I have a Bitbucket account, will share if we can't get any further.

Looking at the object you just shared, it does help I think: at the bottom is the error that the reCAPTCHA service returns, meaning the addon is working as expected but something is going wrong with the response.

Just to double check, are you using reCAPTCHA V2? This addon doesn't currently support V3.

bfaulkner-champions commented 1 year ago

timeout-or-duplicate

I am yeah! I saw that and did some digging, v3 kept popping up which is strange, I regenerated the keys as v2 this morning just to be sure.

aryehraber commented 1 year ago

Ok good, that eliminates another potential issue then!

Perhaps the g-recaptcha-response is getting cached too and then gets resubmitted instead of it fetching a fresh response each time? I've never come across this before though...

My Bitbucket account should be under this email: aryeh.raber@gmail.com -- can try and have a look later this afternoon if you'd like.

bfaulkner-champions commented 1 year ago

Potentially! I've sent you an invite and created a new branch called wip-nocache, thanks for helping with this, it's driving me somewhat mad! 😃

aryehraber commented 1 year ago

Ok cool, I've just cloned the repo. I'm busy until the afternoon but will try and have a look later and get back to you asap!

aryehraber commented 1 year ago

@bfaulkner-champions where should I email you with some feedback? I don't want to share anything here incase it's sensitive to your company. Alternatively, shoot me an email at the email address I provided above and we can pick it up from there.

bfaulkner-champions commented 1 year ago

@bfaulkner-champions where should I email you with some feedback? I don't want to share anything here incase it's sensitive to your company. Alternatively, shoot me an email at the email address I provided above and we can pick it up from there.

Emailed 😃

bfaulkner-champions commented 1 year ago

Hi Aryeh,

I got it resolved, you'll never believe this, but this:

{{ form:create  js="alpine" id="contactForm" redirect="/thank-you" }}  

needed to be this instead:

{{ if {form:success} }}
    {{ redirect to="/thank-you" }}
{{ /if }}
aryehraber commented 1 year ago

Great to hear, good stuff! 💪