This is also reported in reCAPTCHA module: #2219993: Enable cacheable captcha support (once 2449209 is committed)
Summary:
reCAPTCHA has "ajax API", which can be used to re-enable caching on Form pages with reCAPTCHA. The problem is that it is currently incompatible with the current captcha API and the "captcha session".
How Captcha works:
- With rendering of the form "captcha session" is initialized, the captcha is generated and the correct "solution" is inserted in the record for "captcha session".
- When submitting the form user provides "captcha response", and it is being checked if it is identical with the "solution". If it is, then captcha validation is successful, and the user is not a bot.
How reCAPTCHA ajax API works.
- With javascript the reCAPTCHA is generated on a cached page.
- The reCAPTCHA is different despite the page being cached.
- When user submits the reCAPTCHA the "recaptcha response", along with information that identifies the "recaptcha challenge" is posted to Drupal.
- Drupal will call the recaptcha service with that information and service will respond with success or failure, and the service will make sure that it will only succeed once for the same challenge.
There is a POC for this in comment #4. What is left is to create a patch that will allow existing CAPTCHA functionality to work, and to still have the option for working cacheable and secure reCAPTCHA challenges.
| Comment | File | Size | Author |
|---|---|---|---|
| #33 | double_message-2449209-33.patch | 563 bytes | miroslavbanov |
| #32 | Capture.PNG | 9.54 KB | miroslavbanov |
| #27 | 2449209-27.patch | 2.12 KB | vijaycs85 |
| #19 | add-support-for-cacheable-captcha-2449209-19.patch | 3.4 KB | fabianx |
| #19 | interdiff.txt | 2.14 KB | fabianx |
Comments
Comment #1
miroslavbanov commentedHere is a first draft of the patch. It will allow for reCAPTCHA with Ajax API to be used with caching enabled. So we can have caching of forms with captcha. And don't forget that reCAPTCHA is accessible. Unfortunately with this patch only reCAPTCHA will work. Captcha modules that use the normal captcha session handling will not work (captcha validation will fail), because the session handling is completely gutted.
I am thinking that there should the option to have custom session handling built into the captcha module, with the option to manage it externally - in a lightweight PHP script, or maybe a nodejs. But I am not yet sure how to implement it in a very elegant way, while keeping compatibility.
Comment #2
nicrodgersPerhaps this is a good case for using the Session API module?
Comment #3
miroslavbanov commentedI seem to have broken the patch with a last-minute change. I will add a working patch soon.
@nicrodgers
My goal is to keep the so-called "Captcha session" managed separately from Drupal, so it wouldn't need a Drupal bootstrap in order to generate or use it, and Session API module doesn't look like it will help in this scenario.
Comment #4
miroslavbanov commentedHere is a fixed patch. I have removed the disabling of cache under all conditions, and have made changes so only reCAPTCHA will validate correctly, and other CAPTCHAs currently will just be always correct. This is how I will be using it for a project in which performance is a high concern.
Here is the CAPTCHA part of my build:
Comment #5
wundo commentedWrong project, moving to ReCAPTCHA
Comment #6
miroslavbanov commented@wundo
I intentionally created this issue in CAPTCHA module. It's not a mistake. Some adjustments to the CAPTCHA API are needed to support reCAPTCHA+caching. There already is an issue in reCAPTCHA about this.
Comment #7
miroslavbanov commentedComment #8
nwom commentedHas anyone had any success with #4? Would love to use it, since we occasionally have the "CAPTCHA session reuse attack detected" error message. Thanks in advanced.
Comment #9
s_leu commented#4 is workig for me
Comment #10
koppie commentedI can confirm that upgrading to the latest dev version solves the problem.
We haven't had a stable release of this module since 2015, so hopefully we'll get one soon. In the mean time, I'm marking this issue as fixed.
Comment #11
miroslavbanov commented@koppie
I guess you are not getting the annoying 'CAPTCHA session reuse attack detected' error. That's good.
The problem is that the pages with captcha are still not cacheable. It doesn't matter if you use recaptcha ajax API, and if you use latest dev version of captcha. If you think otherwise, can you direct me to a web page which is cached and uses recaptcha? It is easy to determine if it is cached by looking at the response headers.
Comment #12
miroslavbanov commentedComment #13
miroslavbanov commentedLet's have correct status. Issue is not fixed because pages are not cacheable.
Comment #14
koppie commented@MiroslavBanov actually I did get it working with a cached page, with the new Google recaptcha checkbox functionality - see https://www.google.com/recaptcha/intro/index.html. Maybe that's the difference - I don't know if it works with the older "type in the word" recaptcha. Anyway you can see it in action here: http://www.starthub.org/eform/submit/submit-event
I hope that helps.
Comment #15
miroslavbanov commented@koppie
I'm referring to full page cache, which you can cache in Varnish, and directly serve for different HTTP requests. Looking at the headers, I am think you always hit the backend. I've attached a screenshot to show.
Comment #16
koppie commented@MiroslavBanov funny - it was caching yesterday. I swear! But of course I didn't take a screenshot.
FWIW, do you really need to cache the submission page? If you cache the other 99% of your site, and move forms to separate pages (no embedded/modal), you'll still see huge performance gains from caching, even on a heavily trafficked site. I know this is all moot since you've already closed the ticket - just trying to help.
Comment #17
miroslavbanov commentedI was just wondering (doubting) if it really is solved.
I created the patch in the past because of reasons that are now irrelevant. But I am still interested in the topic, and how far the modules have progressed, what has changed.
Probably with Drupal 8 the whole problem should be approached from different angle.
Comment #18
fabianx commentedRe-opening as I got this to work for a client.
Comment #19
fabianx commentedThis includes the fix for https://www.drupal.org/project/captcha/issues/2465113#comment-12370804, but an interdiff.txt is provided for easier review.
To explain a little bit:
recaptcha can just set:
in the 'generate' callback.
As recaptcha does not depend on any sid or solution it can be displayed on cached pages and therefore the page cache does not need to be disabled.
The only thing happening then is:
- A session re-use error is generated on the second usage of the cached form (for obvious reasons).
However this session re-use error is not a problem as the form still will validate correctly (as recaptcha uses its own $_POST values to check), therefore the error message can be just skipped.
A new sid and token are generated and the sid is (if the captcha passes validation) immediately set to solved. If the captcha does not pass validation, the captcha is displayed as normal.
To ensure that the message can be skipped, a new hidden element called 'captcha_cacheable' is introduced. As this only affects display logic (drupal_set_message()), there is no security problem.
Side effects
In case that someone would set a captcha to cacheable, which is not cacheable the only thing happening would be that the challenge would be deemed wrong and the user would need to enter it again.
However custom logic could be applied to hide the captcha until the form is actually submitted (e.g. display the captcha only on POST). This leads to a validation error, but for some sites that might be acceptable.
Therefore while this improves recaptcha in general, this would also allow more complex workflows (e.g. ajax based, 2nd page captcha) for all types of captcha's, so is also generally useful.
Comment #20
plachLooks good and works well in combination with #2465113-2: Improve cache handling for non-displayed captcha's.
Comment #21
plach.
Comment #22
miroslavbanov commented#19
+1
Doing a basic test, this appears to work well with recaptcha 7.x-2.2 + the recaptcha patch. Tested with Contact module.
Comment #23
vijaycs85+1 to RTBC. We'd need it to commit #2130615: Enable page caching
Comment #24
gomez_in_the_south commented+1 to get this committed.
We're using the patch from this issue alongside that of #2130615 to allow our pages using Recaptcha to be cacheable.
Comment #25
wundo commentedComment #26
wundo commentedCould you please re-roll?
Comment #27
vijaycs85Here is a re-roll.
Comment #28
vijaycs85Looks like some environment issue with branch test @wundo, could you re-test it please?
Comment #29
fabianx commentedRe-roll looks great to me!
Back to RTBC
Comment #31
wundo commentedComment #32
miroslavbanov commentedI think the reroll overlooked something and a message is shown in cases where it shouldn't be shown, and it is shown twice in cases where it should be shown once.
Comment #33
miroslavbanov commentedFixes issue from my previous comment.
Comment #34
fabianx commentedUgh, yes.
Good catch.
Back to RTBC for follow-up
Comment #35
vijaycs85Sorry about that. I can see the bug on rerolled patch. +1 to RTBC
Comment #36
reinvented commentedWith the end-of-life for Mollom coming in just three weeks, rolling this up sooner than later would be very helpful.
Comment #38
miroslavbanov commentedMoved the patch from #33 to a follow-up #2956916: Follow-up to #2449209, fix double message. Closing this issue as it is done.
Comment #39
hass commentedWhy are we not committing the bugfix here?
Comment #40
miroslavbanov commented@hass
I don't mind if it's committed in this issue instead of the follow-up issue, but it's now been two months since the patch and it's unfortunately not committed yet. I was contacted by a member of the community to ask for help because he was confused. I created the follow-up issue because I thought it was more clear, and less confusing this way.
Comment #41
hass commentedIt's more a regression of the previously committed patch. How about committing the follow up and create a new release?
Comment #42
wundo commentedI agree with @hass, I'm going to commit it in this issue.