I have a website that has a form with a recaptcha. The form has a lot of server-side validation that can't be moved to the client-side and so it's often for users to submit several forms with the same recaptcha token. The problem is that recaptcha is not very well suited for multiple validations.
According to google's recaptcha documentation:
Each reCAPTCHA user response token can only be verified once.
If one attempts to validate the same token more than once, google's api returns timeout-or-duplicate
.
So, in order for the form to have a smooth user experience and not request to fill the captcha another time every time a user files a form that fails server-side validation I either need to postpone captcha token validation to the end of the server-side validation (which slows the server down) or I need to whitelist captcha tokens for, say, 3 minutes. However, whitelisting a captcha for 3 minutes means someone can make a robot that attacks my website for 3 minutes...
I feel that the above solution might be a comprimise in security so I wanted to know what is the common practice or if you guys have better solutions. Thanks!
I believe that the standard practice is to set a cookie or session variable when a user passes reCAPTCHA the first time, and use that indicator to decide whether to display/check reCAPTCHA or not. You can then set a period of validity for that indicator, or keep it indefinitely.
Now on to the security question. The purpose of reCAPTCHA and other humanity-validation mechanisms isn't necessarily to prevent bots from using your service entirely, but instead to reduce the volume of bots using your service, and the rate at which an attacker can attempt new attacks. You are adding a step to any attack that requires either manual intervention or an immense dedication of resources; either way, you are increasing the time it takes an attacker to attempt one attack, and limit the absolute number of simultaneous attacks they can attempt. An attacker can't spin up 50 clients and launch 50 attacks instantaneously if they need to solve 50 distinct reCAPTCHAs first. This idea, making attacks more difficult and slower rather than outright impossible, is the basic concept behind most security systems and patterns.
With that in mind, forcing your users to solve a reCAPTCHA on every request gives you little advantage compared to having them solve a single reCAPTCHA at the start of their session; I'd argue that the user experience concerns outweigh the security gains. Let the initial reCAPTCHA do it's job of making it difficult for an attacker to start multiple simultaneous attacking sessions, and use some simple user-activity heuristics (i.e. making 20 form submissions in as many seconds) to find and kick out the attacking sessions they do create.