Skip to content

Strip locale keywords from X-Apple-Locale - fixes 2FA codes never arriving (HTTP 500) - #58

Open
IgoSzaFIIT wants to merge 1 commit into
rileytestut:notarizedfrom
IgoSzaFIIT:fix/2fa-locale-keywords
Open

IgoSzaFIIT wants to merge 1 commit into
rileytestut:notarizedfrom
IgoSzaFIIT:fix/2fa-locale-keywords

Conversation

@IgoSzaFIIT

@IgoSzaFIIT IgoSzaFIIT commented Sep 19, 2026

Copy link
Copy Markdown

Apple's 2FA endpoints return HTTP 500 with an empty body whenever X-Apple-Locale carries a locale keyword, e.g. en_US@rg=skzzzz. That's what macOS and iOS report when the language's region differs from the device region (English with Slovakia as the region, in my case), and AltSign sends Locale.current.identifier as-is. Sign-in itself still succeeds, so the user gets the code prompt, but GET /auth/verify/trusteddevice (and the SMS variant) fails and no code is ever sent. I'm fairly sure this is what #1804 and #1810 are hitting, and why 1.8.1 only fixed 2FA "for some users".

How I narrowed it down: FindMy.py v0.10.2 completes 2FA fine for the same account, from the same Mac, while AltServer 1.8.1 and AltStore 2.3 (remote mode) both get the 500. Before landing on the locale I made AltSign's 2FA request header-identical to SideSign's (App-Info, Accept/Content-Type, serial, Connection: close, fresh OTP, User-Agents) and it still failed, so I went the other way - started from FindMy.py's working flow and changed one thing per run, each with a fresh, never-trusted anisette machine so Apple always asks for 2FA:

Run Change vs. FindMy.py's working flow Result
A skip GET /auth before requesting the code (AltSign never calls it) code arrived
B no cookies carried between requests (AltSign uses an ephemeral session per request) code arrived
C X-Apple-Locale / loc = en_US@rg=skzzzz (AltSign's value on my Mac) HTTP 500
D X-Apple-I-TimeZone = GMT+2 (AltSign's value on my Mac) code arrived

In run C the 500 already comes from GET /auth, so it's the 2FA endpoints in general rejecting that locale, while GrandSlam sign-in accepts it.

The fix normalizes the locale once in ALTAnisetteData (initializer and setter) to language, script and region only, and makes the sign-in cpd use anisetteData.locale instead of reading Locale.current directly. That covers the 2FA requests and every developer-services request, for AltServer (both anisette paths) and for AltStore on the device, without touching the call sites. en_US@rg=skzzzz becomes en_US, de_DE@calendar=japanese becomes de_DE, and plain identifiers (sk_SK, en_SK, sr-Latn_RS) pass through unchanged. There's a small standalone check for this that compiles against the patched ALTAnisetteData.m (localecheck.m, all cases pass).

Verified end to end: I built AltServer from classic @ fafd76ee with AltSign notarized @ 468313b plus only this patch (and the Xcode 27 project tweaks needed to compile, nothing behavioral), and signed in with a local anisette machine that had never completed 2FA. Every request came back 200 - the trusted-device code request that returns 500 on stock 1.8.1 went through, the code arrived, and sign-in finished. The iOS side is inferred from FetchAnisetteDataOperation passing .current as well, since I didn't capture the exact locale string my iPhone reports.

@IgoSzaFIIT
IgoSzaFIIT force-pushed the fix/2fa-locale-keywords branch from 0a7329f to af620c9 Compare September 19, 2026 09:31
…ng sent

Apple's 2FA endpoints (gsa.apple.com/auth, /auth/verify/*) answer HTTP 500 with an empty body when
X-Apple-Locale carries locale keywords, e.g. "en_US@rg=skzzzz" - what macOS/iOS report when the
language's region differs from the device region. Sign-in still succeeds, so the code prompt appears
but no code is ever sent.

ALTAnisetteData now keeps only language, script and region (initializer and setter), and the sign-in
cpd uses anisetteData.locale instead of reading Locale.current directly.
@vinczemarton

Copy link
Copy Markdown

Thank you for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants