Happy holidays everyone. We’ve had three sites in the last two weeks that have reported reCAPTCHA problems. A captcha is the funny little thing at the end of forms that tries to prove you’re not a robot by having you spell out letters, or pick pictures with traffic lights. They’re annoying, but without them, many “contact us” forms and user registration forms can be hit with a crippling amount of spam submissions.

One of our clients even recently called in for holiday support on this bug, so we’re pretty sure there are others dealing with this situation as well. They all have the same JS error and/or symptom:

CAPTCHA validation error: unknown CAPTCHA session ID. Contact the site administrator if the problem persists.

Diagnosing the session validation error

The root of this error, at least for one of our sites using simple_reCAPTCHA, is pretty straightforward (but took us days to diagnose initially). There are two parts to the issue. A typical contact us page has 2-3 forms on the page: Search, Email Sign Up, and the contact form. The submit button for each one has the same HTML ID. That's not valid HTML; IDs have to be unique. There's code in the reCAPTCHA, captcha, and simple_reCAPTCHA modules that get tripped up because of caching.

Each part (block) on the page is cached separately, so when someone visits the homepage and that gets cached, Drupal also just pulls the search form from its cache for other pages instead of rendering it from scratch.

If rendering the whole page from scratch, Drupal uses unique IDs in every form. One's submit button has the id #edit-submit, another gets #edit-submit--2, the other #edit-submit--3. But due to the caching behaviour with reusing existing blocks, we end up with:

  1. If you visit the homepage, which just has the search form, its button gets #edit-submit.
  2. When you visit the contact page, which has 2 forms that need to be rendered, the Sign-Up and contact form, Drupal uses ids #edit-submit and #edit-submit--2. But the cached search form also ends up in the header with an id of #edit-submit too.

The simple_recaptcha module does something quirky. When you click the submit button it runs some javascript to get a token from the reCAPTCHA service, which is fine, but then it has to re-click the submit button, and it does that by looking up the button by ID again. Looking up by ID gives the first element with that ID, the search form's submit button.

Similarly, the captcha and reCAPTCHA module loads the token, but it gets stored in the cache and it causes the same or similar error that simple_recaptcha does.

Helping reCAPTCHA modules deal with Drupal caching

The real bug is challenging and not fixable within our support scope of practice. More on the accessibility concerns and other issues below.

  • The fix for the simple_captcha module is to modify the javascript as described in this bug write up.
  • If you’re using the captcha module, we recommend reviewing the discussion and various patches in #3089263.
  • For the reCAPTCHA module, perhaps consider using one of the other two modules instead.

Accessibility concerns

Even if you’re not using the reCAPTCHA module, your site may still have an adverse effect on accessibility as well as confusing any Javascript that is written. Here’s a quote from the linked accessibility issue:

“It may sound minor, but it's a major issue, as it is associating the search autocomplete functionality in the header with the views filters elements in the content. The end result is that JAWS thinks a regular select element in the views filters, is a combobox, which it is not, so it's pretty confusing to users.”

So it’s not just captcha related and is definitely going to need some real consideration from the caching experts that work on that piece of Drupal. Let us know on Twitter if you’re having the same issues and how you fixed them.