[18.0][FIX] auth_signup_verify_email: verify captcha on signup - #1007
szalatyzuzanna wants to merge 1 commit into
Conversation
passwordless_signup() creates the user without going through web_auth_signup() from auth_signup, which is where the captcha token is verified, so the signup form is left open to automated posts even when a captcha is configured. Call the ir.http hook defined in base, so that an installed captcha module (google_recaptcha, website_cf_turnstile) is enforced here too. No new dependency is needed: the hook returns True when none is installed. Those modules also pop their token from request.params, which keeps the captcha field from reaching res.users.signup() and raising an invalid field error there. Co-authored-by: szalatyzuzanna <szalaty.susana@gmail.com>
jelenapoblet
left a comment
There was a problem hiding this comment.
The issue and the proposed fix make sense to me.
|
@pedrobaeza I think this is a good fix, If you're ok with it, I would merge it |
pedrobaeza
left a comment
There was a problem hiding this comment.
OK, but the problem may be using the new method passwordless_signup that replaces the whole logic of web_auth_signup instead of reusing it and only injecting the needed bits. Isn't possible to inject the verification inside the existing method and calling super afterwards for doing the rest of the standard setup?
And about the test, being so synthetic that is mocking the direct method, I don't think it's adding value.
|
@pedrobaeza Thanks for the review. I tried it: reusing On the test, fair point. It's only a regression guard so the call can't be dropped again. Happy to remove it if you think it's not worth it. |
pedrobaeza
left a comment
There was a problem hiding this comment.
OK, I was talking about the method web_auth_signup, if you see it not possible, I don't insist. About the regression test, I think it's not adding value in this case. A real regression tests would be a complete signup flow and only mocking the captcha failure.
Port of #933 (17.0) to 18.0, with a stronger test. Original fix by @Cl0ut1eR, kept as the commit author.
Problem
auth_signupverifies the captcha token inweb_auth_signup(), beforedo_signup()creates anything. This module overrides that route and, when a login arrives with no password, answers it withpasswordless_signup()without callingsuper(), so that verification is never reached.The result is that with
google_recaptchaorwebsite_cf_turnstileinstalled and configured, the widget is rendered on the signup page but the token is never checked on the server for this flow. We are getting automated signups in production because of it, and they are not harmless: each one triggers an activation email from our server to an address the bot chose, which is what damages the sending reputation of the domain.There is a second effect, reported in #878: the captcha token stays in
request.paramsand reachesres.users.signup(), where it raises an invalid field error for legitimate users.Fix
Call
ir.http._verify_request_recaptcha_token("signup")at the start of the passwordless flow, so the existing error handling renders the message.No new dependency is added. This answers the question raised in #783 ("Isn't reCaptcha an extra module?"), which was never followed up:
_verify_request_recaptcha_tokenis defined inbase(ir.http) and returnsTruewhen no captcha module is installed, so a database without one behaves exactly as it does today.google_recaptchaandwebsite_cf_turnstileoverride it, and both pop their own token fromrequest.params— which is also what fixes #878.About the test
test_failed_recaptchapatches the method on the registry class (type(self.env["ir.http"])) rather than onbase'sIrHttp. This matters: when a captcha module is installed, its own override sits in front of the one inbase, so patchingbaseleaves the real implementation running and the test does not exercise the rejection at all. Patchingbasewas verified to fail on a database withwebsite_cf_turnstileinstalled — precisely the setup the fix is meant to protect.The test also asserts that no user is created, which is the property that actually matters here, rather than only that an error is rendered.
Related
#774, #783, #878, #901, #933