signalapp / Signal-iOS

A private messenger for iOS.
https://signal.org
GNU Affero General Public License v3.0
10.75k stars 3k forks source link

"Something went wrong" after captcha #5846

Open lillian-b opened 1 month ago

lillian-b commented 1 month ago

Bug description

I am presented with a captcha on registration. After I complete the captcha, I get a "something went wrong" popup, in the logs I can see the Signal server returning a 403 to the captcha.

I am not using a VPN, but I have tried using my cell connection to register and my home internet.

-> This might be an issue specific to my phone number, I tried emailing support@signal.org last week but did not hear back.

Actual result: "Something went wrong" popup.

Expected result: it sends me a SMS code to complete registration.

Screenshots

image

Device info

Device: iPhone SE 3rd generation

iOS version: 17.5.1

Signal version: 7.22

Link to debug logs

https://debuglogs.org/ios/7.22.0/2c14f6d1deb45ab90a1157b7379da48bfb962fa3f0e81401410cd1364b8a2a2a.zip

Notably the below:

2024/08/02 22:44:37:422  ๐Ÿ’› [RegistrationCoordinatorImpl.swift:2464 submit(challengeFulfillment:for:retriesLeft:)]: Submitting CAPTCHA challenge fulfillment
2024/08/02 22:44:37:423  ๐Ÿ’› [RegistrationNavigationController.swift:57 pushNextController(_:loadingMode:)]: Pushing loading controller
2024/08/02 22:44:38:185  ๐Ÿงก [OWSUrlSession.swift:423 baseCompletionPromise(requestConfig:responseData:monitorId:)]: Request failed: HTTP 403; <OWSHttpHeaders: [content-length; content-type; date; vary; x-signal-
timestamp: 1722638678102]>; https://chat.signal.org/v1/verification/session/l_t7o75VSi2_fswVPY2NAw==; nil
2024/08/02 22:44:38:186  ๐Ÿงก [OWSUrlSession.swift:568 promiseForTSRequest(_:)]: Failure: { PATCH: v1/verification/session/[REDACTED] }, error: HTTP 403; <OWSHttpHeaders: [content-length; content-type; date; vary;
 x-signal-timestamp: 1722638678102]>; https://chat.signal.org/v1/verification/session/l_t7o75VSi2_fswVPY2NAw==; nil
2024/08/02 22:44:38:209  ๐Ÿ’› [RegistrationNavigationController.swift:71 _pushNextController(_:)]: Pushing registration step: showErrorSheet
g1a55er commented 2 weeks ago

I spent some more time digging into this bug today, and I have a theory of the case: it seems like the captcha verification codes are getting truncated on iOS.

Here is the unreacted/unmodified contents of the body of the failing PATCH request to the /verification/session endpoint on iOS:

{"captcha":"signal-hcaptcha.5fad97ac-7d06-4e44-b18a-b950b20148ff.registration.P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQQUIHOoLVgGBdGvskX4bzgMqMaU7xNMQuerke9XJ2bTyDRJkEm907B9GAM-_60L5P20FNv2WYDjjlI0bzDGZnu1dIahLTxM-g5y14yOIzAIAEowc188NhWTga-1umVHDL0NHaeL_qTLlixXHtjLm64n6Nylyokr0Yt4_hlyp_7tjzf1x39w2-5ZgJU1g0YesiueNfK7WPN5ve76oDicoVIGbHbcz6c9SXWgKGNJdkxVKJyFBtm6lJMU-SvUEBHcuhLbtxkhQYnPMNzE5xVD4EzaTz8yZSrrLiVEmjOrDdlTY6g0uwhWyfcjW0qECdUZNFH5xIzDAUb_TwVsEBvrVh9IyVRt-g_uLOlEHnLdamId4osIaWf5aolkkWKeRQEO-uiVYTXGilNNRdKV7_l0ymC5OhW6j_avOLw_gt8AjANwv4PaKOXA2y-F0x6JWAcRWX2g6WSJP1GzwT_Bm2kYWCZRD3YGRPthiCY8e22TQsLsSj2FK_YH5Z0rvhoedM-op3Uy-T4u6hE_KVJAO-ldYfvl-QN9Yuqm-nyT7kDSMFKCClzvePwHRXlCKs5ZL8d7Cp8xrBjJvXJIlpb_zGG4WZtWfcYb6EFgn9OF3bAZULXFRhqpy2abREyy_xq2_NohP689P53FTxkWyBIfetfcAnzZpwGyXLcYEkCYrrGEryOXr9JgqWaJXCFs_DY8FtfSGK5XLb3OlH9XJ7CvRkmdVft7xLbe_7Dvt77iJKeb_dbOwgkOmo-rk0o4GKSyCb9OBKP2LaCUWwRfY2skIf1lzwH963rl6NK1JlAt196jAj_rJJAkWopBQJ4jXcwIRKStSr9bND-l0YRNO5llMbdtC_O2hyelPg2GUD05ErKJNqRLWitIMDRAeSKZARYkxSS3RIUaowLc9sPI2yveQ5Dz3c2gih_E1ZC3Zez6BeeCwW6dr2BmyigH2hyEydySFxBFhNuG8926GCFjNnvpZ_82t_2EDWS_kPP3M_HtPXauUpIPHLENALiyP3TgYSrs9Q03Lsum1vRgFm3aDfBNvHhFChMFpxK4KwZFgIB3Dwl27ynVL2XcheSYILi1pe5A3rE_SwgAUch4zlfMIFgCNbmkU64VgWu9nzmVGCkW2FCs8Pygxp1O2p8BbesHZu-I-cV00Hkgo6QnCDvxFypvsPUbYZpdRMa_gPsAgFuuAkvLTOAWHP0f7QM1J23bheXL3RLlryeCxay4JpoemyV3jpz-pdM3qRCyNtPa-HvVvcckf_D4X7jphzs6fwbiB-c2pgtf_SgHoq5k6JVhjad4AkFvj9O54ITo7yIY3_ABE2uKwB-3oOzF-H74cmb_uNU3hdd1Yedj60JTo4-lOqMK_PlNuq8uyQ2plQMnuFbjVM93FhYesWsGC7ezo2V4cM5m2KCfqHNoYXJkX2lkzjGtTIGia3KoMzgyNzE0NjKicGQA.CUOpiRXiGtbtTT7DKq6rPvSurre-XzkHeZDnXEmgz6E"}

Here is the unredacted/unmodified contents of the same PATCH request on Android:

{"captcha":"signal-hcaptcha.5fad97ac-7d06-4e44-b18a-b950b20148ff.registration.P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQVMdPZYP9KBjb3qqV32C93Ip-nQm5CitUKzw_SEdJwxAYkNT6-AHnKjotujA5h8Zo4L0Aasb4zcK-CLHaAgyybEkUS0RP1xFrF_jFmKDDixOBNU4YXrThc8_M1bhyA3h-qOQkRUntcAFJk8uXmWUd8mUlTLPnYfy6nULq0yxfuFWuALr3uImhcaXXPWiCibzUqR5aZSEP9S_cSBemaHJnBxG8DXkJpscF0Tvi-gTN16yMws-wv6e-vEpuh5OIV7ydNVJHcYJztdkSAOWK6s8D9puDPMGuRYtXy8EamJtWXAwH8bZCltyt2ErJL7XR9mNNDnQf4SSiBzSm70i7-xIi-yaw0Yv0x45_q_2R-FY1PQUq2Ccmspfv1X2xaTmENgf9m_AsANdSspQvh11EHq4uFqiQnknNb7nLkNY5E_h9pvFjl7E5CNWdGSJgJOv7nn1yRxXXKAdIoT-mpg4IOH8C1SkDVOLiHHkcNNsohDgyJmeMow-U6ttNp7orijewNnDALisSoAlpZyGkVVfrBX4PTuA-35nYPx3mT8daBXQYg7oAqEgoGuTXylGietGroL_fmr2-QKJ0p7F58g3k6MO8rqZe9Duxp3Xkucdi2dK7MjknRyG6snoKYxvTGd1lx-jBGwYCWlRitUHeGENB_TLEL1cSIxPL4_VL_8i6OE7WuCV6EwkHNeF6JGCPsWK55QOVJT3tKurg_1FZyyoHelnMFMRb1Xk1fjk_LtrG3hm-6w_ki0tVAY4iWgV7KGRIbRANFgR25YgGuloUG-SJoq9gteJrTwzYFLbMt6TsCWkptWG-LP9JmirL2KiV3PKWwlWuVLgeXJsa2lvCccbtRorjsZi4RMjztf78j8I59Xs70lOW4yFztansAnlOjAfY0vzSLjfJpx8oW1i1KXgFJLFK2DV-yBOaDJM21mKOSU6y1eAud37oPsOdDef0QHes6Qiq-IZcKRScvoVm_RhFVTdqMJ8Fe8y7905MSEW0-mY5zc-Xcx10Qx9qWEgWOokMj5oKhn9lD9fRVdHJpgBSa9UahH-pV1p4xVuZlstFmqZ22dPZ3iliaGOXu4rn-fLVD0_DJiHVREy_Uiq3mNQ-t_1oliz50vL4rB6yKEEotGKAoKxG2OuR5sn6WqaUyzjDZh_yUPNLT7peZYuC5oleGKefuu3ASR2YANZ1iKOKa0pYDq3QpstBUjnvUiKBqrJqk6bI899lI5-f7l46kIei6-fDVKfVO2s6iwKQL8hVFgfjcAhpIoPfhn9WQymTh_0JTlQQ8PIUT-voD0IH7H2diAZunYwU5Jg4o2SErcuDwOAk6MaDnngqBnGY8FBDh9Kwu4L0VVPF-wjPmgaK1d4YlyjBgZXYYTQBrRjuwTyC1sfNbOFjQwTpFcjQ2pEBikWX1gsZ1hWn7vNZkcGTAm8eJf8i9iPj-XsTYGUBu8ed1Qgego0P9uAeMZwgIw5qa8SboPoXKa38uUt8qrc83rlU_7eUwdKriaECGgAG7qvPHTy37NYXmF3taKV4D2C0LuAx6FDyvHGXNZU0bqR-wmPpoqPKHrvEHl8gJgCAHX8UFLoSMyHTp1Vt3DHKVNMEq3qgOx357YXbqylcUuxlvQ4C_Jyo2aUK5ZjqMVgyPtZ7b9xPNX9AHHPpf6_DrUJ_CUskD0zvxCmXR7y5SzsGU6uSWdvUNOShxzVlH_Quz67IEEMXqjzqTqg9NASvhGxRJNrVLiEbaLoS0lpFAGO3WDP7NhfWCij29VUOE59zozNLQNHhIXSGLQSR5mkBpflAdSNl7fXsWT3eGtoa2s-mBVe7gso2V4cM5m2KWoqHNoYXJkX2lkzjGtTIGia3KoMmYyYmIwOWSicGQA.JD1k9MIr7sw0CC8lDRKLO2MzmSWWxt-q9QJvmkNVfDo"}

The iOS request body is 1624 bytes long, the Android one is 2040 bytes long. The difference in the length comes from the "captcha" field containing the captcha verification token getting seemingly truncated by the iOS app.

The flow for getting this token in both apps goes like this:

  1. The app loads the URL https://signalcaptchas.org/registration/generate in a web view.
  2. If the user completes the CAPTCHA successfully, the page redirects the web view to a URL with format signalcaptcha://XXXXX, where XXXX is the captcha verification token to send to the server to pass the registration challenge response. The code for this lives in CaptchaView.swift:121 for iOS and CaptchaFragment.kt:43 for Android.
  3. The app sees this navigation in the web view, intercepts it, parses out the token from URL, and then sends the token to the the /verification/session endpoint as a PATCH request to proceed with the rest of the registration flow.

When I try this flow in Chrome, the URL I am redirected to looks like this:

signalcaptcha://signal-hcaptcha.5fad97ac-7d06-4e44-b18a-b950b20148ff.registration.P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQUiy3-z6J9sDwF3uZz4uiKkfI24DGFPCUc1eW47YV4QRAQU2rf5qTHniuKTsDHsjaXDQkfCxwiPoge5ogvJ7xLawz8tKnZqbt43N37HT6dYZ6POazML1NLWnNgtgXZuCM3PO6mMcO_djXLmBGKRwwad56MqPsu035OvZlAml8ELg8096U6J0mlGd-zCOc073ZaVBD96dCH-fEMop2wXXrSqFlGX6cpkjJwbBQKOrsJWgG600v-_yD_UXw851eXi7GcrsLE-72QaSlvwbiRF1HHJ7EmrYLrg4UQ8Df46DgOs1gjQWJRolWqRC9gz-7GxZyfLyX_U9CfLDBQZ_jlZLcaZY9K9Q7-g9BpFQBVYKbQvkpPRkdzOtfXoKqnWwWhJshnIBwgkartA1WLIacfZekadwTAPYmPerR_2WNShMKQVQBvSqMrGGPUPFplP49wZCRLV09-E75xcDnbUj1AC9K-uRXIAUyJPOjaeYuzc0KzBRJe5FofJQ2qlfWRAQQC3P8MlfB0zhHbNSCvR1f-sEoyXIshBs_2-7SquH1QNUXZKOw1LSkIkdmPPBnNguQCwAduieQqP3zRZxXr_CnHuS0ZHx7asSZMxHbZQkMti4IuaQP23XuD8heoxAPUSI6I7W8p1ePz2_ue-H86faA2-oIP0Kazfiw0CrFIuoM0vrrrb78IVnZ7bfJ832RCGceTa3n0MnMm4McAjqhKBcZncCxBlw8oseNfbGT7xrTeRdX4DULHv9WRW16XGicx6Du-khQf2rFnr_qr-2EiL5Y1PK2eXmrQXcfslFZrqoa-rbDQEuOy0f1S6USFGA6ziQPlWno9YVA3eX4HPRC4ygRDQIc3b0XIIS9KMnwKMnWLRweEgliYO6q9xizvL-kUDace1Wt5AMPGk0C8IDIGhpe11rDuIaGrviXXY4yTTxBNfdKff1fRULcVHSuEcTylDOmtcoqBYBGNQMawglFZNDCs3B4dxd1du19VjPzt98rejx_wqvf7DKBHIVYzFXzfl6FuthzaV2ku_cAJ7r_MVipUWODwdnAp4cs6ofsXU8CJ0zAyl-rZhQ8DDPFOb0RTIXBTblhdtf7sqeT_K6USVe-Cp-gw7KMnarwpXX8fiBH311S8ZDJMOB8t7osVnh69lK1fS5qKy9Az_2P7QLZ2L8o7XlDQP7_HhLD3iSR_CC5imKxRsIGYevGgLhuxW6UYazlazoIaRmYnBglmxNQ2GhF2-HdMUVvlufKu1xtYxsuPUkhKZx4PT-qIMpT5sbHsVRjTFHHoR8uNKTYLMp9PwoO3TQdT6Dhk92cJ68j8Ub32z2ZvcuRdJTkIy1okIpv5pFrBRK8POJ5ReHvC9Q_bcVfs74b_kQoZSFHMrAQd8OWl_KnoCg4pC46mKE9D6H0j3UAxgrjdI_NqpuIFvkKf0ywJPvC4k-VyvV7JGWePCO2Iv1tSW8UklZngzKevL8aKa9kCL9Rwt0endNqSh5ip0ubf8fqO54USRjwZlncB0s4wq2hWevcfxkbTauhjWYCDmVyyI6CbUr8FFM6LTs9uuIdVQO_N-0VZTHGZGzgrtzzNBu6waI_fxnJu1voLTXtO93ayH9_5hKpxIpz4IDWX0oJcncJKFmg7IvojYbECucdSAI1KcWJJksEHdmj9GkS-4EuXnQdfJd8qYCJ3CLB7Mcux1m6Xnukwj5moG4W_WTsg5j8DROpRgpzdtg8ShpYxTc45YAVTdK9Z5KBR7XM0j89XR6hVp2xHGo2V4cM5m2LOQqHNoYXJkX2lkzjGtTIGia3KoMzQzYmE5MzWicGQA.1VDWeLrPSK3ZWS0Uhvs3uTEXMFr8lkkgUG51EmwWMSQ

This is also about 2k characters long, so it seems to me like the proper full token should be about that length.

I tried to Google around and see if the maximum length of format of a custom URL scheme for iOS is defined anywhere, but all I could really find is that around 2K characters for the base URL (i.e. hostname component) length start to get into the "there be dragons" territory.

My next steps would be to try and modify the URL scheme slightly to see if a scheme where the token lives in the path of the URL instead of the host works better.

g1a55er commented 2 weeks ago

It turns out this all comes down to the custom user agent string used in the CaptchaView on iOS. hCaptcha seems to not like it for some reason, and to return invalid captcha responses when it is used. I have a fix out here: https://github.com/signalapp/Signal-iOS/pull/5865

(Although if Signal has a contact at hCaptcha, might be worth reaching out to them to figure out why they don't like the custom user agent string.)