[iOS · Registration] Sign-up fails with 'The CAPTCHA verification has failed' #31
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happens
Creating an account on the iOS app can end in the alert "The CAPTCHA verification has failed", and every further tap on Register gives the same text, while the same server (another.im) registers other libtacky clients fine.
Cause
It is not the proof of work itself. ejabberd 26.09 (
mod_registerwithcaptcha_protected+ top-levelcaptcha_pow) checks the XEP-0158 challenge before anything else and deletes it whatever the verdict (ejabberd_captcha:check_captcha_pow/2,src/ejabberd_captcha.erl:716-733, reached frommod_register.erl:222-238). So once a submit is refused for any other reason — "User already exists", "Users are not allowed to register accounts so quickly" (another.im allows one registration per IP per 600 s,REGISTRATION_TIMEOUT), a malformed user name — the form's challenge is spent.The app then keeps using that spent form:
AnotherIM/Screens/Registration/RegistrationScreen.swift:529-544shows the error with Retry and OK.dismissError()(AnotherIM/Screens/Registration/RegistrationViewModel.swift:203-206), which puts the phase back to.readyon the same form.submit(),:167-183) sends that form again. libtacky solves a new proof of work for a challenge id the server no longer has →not_found→ "The CAPTCHA verification has failed". From then on every attempt shows this text instead of the real reason.(The view model's own comment on
retry(),:155-158, already says "a rejected submit can have spent the one behind it", but only the alert's Retry acted on it.)Reproduced on libtacky's ejabberd 26.09 rig (captcha_pow only, as production), driving the
registermodule exactly asRegistrationViewModeldoes (connect -host+ token,form,submitwith every visible non-fixed field):<Success>;User already exists, then the same form submitted with a free name:The CAPTCHA verification has failed;connect(Retry) before the second submit:<Success>;<Success>(libtacky dials again for an expired stream).The embedded libtacky (submodule pin
276241b1= v1.1.15) is not at fault: itsregister.tclis wire-identical to libtacky develop for registration, and the app sends exactly what anotherim-js sends (ui/src/state/registration.tssubmission(): every non-hidden, non-fixed field; libtacky fills the hiddenFORM_TYPE/from/challenge/sidand theSHA-256answer).How anotherim-js does it
Same flow (
connect→<Form>→form→submit→<Success>/<Error>,ui/src/state/registration.ts). Its Refresh form button callsretry()with the typed answers. Note: after an<Error>the js sign-in card also keeps the form, and Create account would resubmit it, so the js app can hit the same text after a refused first submit. That is not fixed here; it is a possible follow-up.Fix
PR from
fix/registration-captcha: a submit's<Error>marks the form spent, and dismissing the error (OK) fetches a fresh form — same token, typed answers kept — just as Retry does. The server's real reason ("User already exists", "…so quickly") is then what the user sees on the next attempt.SHA-256among them: libtacky hands the … #34Fixed in master by #34 (merged with feat/ui-redesign in #36). On feat/ui-redesign the cause was another one than master's:
RegistrationModel.submitsent every hidden field,SHA-256among them, and libtacky solves the proof of work only when that key is not among the values, so on another.im (captcha_pow) every submit failed with this text. The submit now sends only what the person answers. Not yet checked by a live sign-up on another.im.