Skip to content

Send GrandSlam requests with the anisette provider's client identity - #61

Open
kisnner26 wants to merge 4 commits into
rileytestut:notarizedfrom
kisnner26:fix/gsa-windows-anisette
Open

kisnner26 wants to merge 4 commits into
rileytestut:notarizedfrom
kisnner26:fix/gsa-windows-anisette

Conversation

@kisnner26

@kisnner26 kisnner26 commented Oct 15, 2026 •

Copy link
Copy Markdown

Builds on top of #59 (2FA codes that Apple sends on its own), so the diff also includes its commit until #59 is merged. Used by altstoreio/AltStore#1834.

Problem

Since October 12 2026, every sign-in from AltServer, Sideloadly, SideStore and iloader fails on the first GrandSlam request (GsService2, o=init), with -80045 "This action cannot be completed at this time" (altstoreio/AltStore#1828).

  1. October 12–13. Third-party anisette is generated with Android's CoreADI, but the X-MMe-Client-Info sent to Apple described a Mac. Apple started rejecting that mismatch. Declaring a Pixel client fixed it for a day (Handle 2FA codes that Apple sends on its own #59, Fix AltServer sign-in failing with -80045 since October 13 altstoreio/AltStore#1832, xtool 1.22.2).
  2. Since October 14 (~20:50 UTC). gsa.apple.com answers any request that declares an Android client with an HTML page: 503 Service Temporarily Unavailable (Login Error nab138/iloader#920, #921). AltSign then tries to parse that HTML as a property list and fails with NSCocoaErrorDomain 3840 ("Encountered unknown tag html").

Apple now accepts a sign-in only if the User-Agent and X-MMe-Client-Info match the client that generated the anisette data. Today that client is the Windows iTunes identity served by anisette v3 servers such as ani.jkcoxson.com. Its /v3/client_info returns:

{"client_info":"<PC> <Windows;6.2(0,0);9200> <com.apple.AuthKit/1 (com.apple.iTunes/12.12.4.1)>","user_agent":"akd/1.0 CFNetwork/808.1.4"}

That is also the fix nab138/isideload 0.4.6 / iloader 2.3.8 shipped.

Solution

AltSign used a hardcoded Xcode User-Agent. It needs to accept the one from the anisette provider and send the same request shape as clients that sign in successfully today.

Commit Change
fix: send GrandSlam requests with the anisette provider's client identity New optional authenticationUserAgent property. Callers set it to the anisette provider's user_agent; the default is akd's instead of Xcode's, which Apple blocks. GsService2 and 2FA requests send Accept: text/x-xml-plist, X-Xcode-Version, X-Apple-App-Info and Connection: close. cpd is reduced to the fields those clients send, with string values.
fix: report HTTP errors from GrandSlam instead of plist parsing errors GsService2 responses that are not 2xx now throw ALTAppleAPIError.unknown(statusCode:), e.g. "Apple's authentication servers returned an error (HTTP 503)", instead of NSCocoaErrorDomain 3840. GrandSlam requests no longer follow redirects.
feat: resynchronize anisette data once on hsc 434 New optional anisetteDataResyncHandler. On hsc 434, AltSign passes X-Apple-I-MD-DATA to the handler and retries init once with the resynchronized anisette data. Without a handler, the behavior is unchanged.

Request comparison

Before After
User-Agent AuthKit/1 (Macintosh; OS X 26.5.2) (com.apple.dt.Xcode/26.0) authenticationUserAgent, default akd/1.0 CFNetwork/808.1.4
Accept */* text/x-xml-plist
Extra headers none X-Xcode-Version, X-Apple-App-Info, Connection: close
cpd 14 fields, booleans bootstrap, icscrec, pbe, prkgen, svct, loc, X-Apple-I-MD, X-Apple-I-MD-M, X-Mme-Device-Id (strings)

Testing

Tested from AltServer (altstoreio/AltStore#1834) on macOS 27.2 (26B5091g), MacBook Pro M1, with a free Apple ID with 2FA:

Notes

Credits

#59 by @whydr4 (2FA). nab138/isideload (d424b17, 8ca39b6), whose request shape this follows. altstoreio/AltStore#1832 and #1833 for the earlier Android work.

whydr4 and others added 4 commits October 14, 2026 21:16
Since October 13 Apple often pushes the verification code to trusted
devices right after the password step. In that case the complete
response has hsc 409 and no "au" value, so we used to skip 2FA, ask for
app tokens right away and fail with -22411 (This action cannot be
completed at this time).

Now hsc 409 is treated like trustedDeviceSecondaryAuth, except that we
don't request a new code because that would invalidate the one already
sent.

This also adds an optional anisetteDataRefreshHandler so that the code
check, the second sign-in and the app token request can each use a fresh
one-time password instead of reusing the one from the first request.
…tity

Since October 14 2026, gsa.apple.com answers 503 with an HTML page to
sign-in requests that declare an Android client, and rejects mismatched
Mac identities with -80045. Requests are only accepted when the
User-Agent and X-MMe-Client-Info match the client that generated the
anisette data (e.g. the Windows iTunes identity served by anisette v3
servers).

- Add an optional authenticationUserAgent so callers can pass the
  user_agent reported by their anisette provider. The default is akd's
  user agent instead of the Xcode one, which Apple blocks.
- Send the same headers as clients that currently sign in successfully:
  Accept text/x-xml-plist, X-Xcode-Version, X-Apple-App-Info and
  Connection: close, for both GsService2 and 2FA requests.
- Reduce cpd to the fields those clients send, with string values.
When Apple rejects a client, GsService2 returns an HTML error page
(e.g. "503 Service Temporarily Unavailable"). AltSign tried to parse it
as a property list and surfaced NSCocoaErrorDomain 3840 ("unknown tag
html"), which hid the real cause.

Check the HTTP status of GsService2 responses and throw an error with the
status code, and don't follow redirects on GrandSlam requests.
GrandSlam answers hsc 434 with X-Apple-I-MD-DATA when the anisette data
is out of sync with Apple. Add an optional anisetteDataResyncHandler that
receives that value, and retry the init step once with the resynchronized
anisette data, reusing the same SRP context. Without a handler, or on a
second 434, fail with invalidAnisetteData as before.

This mirrors the resync flow used by other anisette v3 clients.
johnbuckman pushed a commit to johnbuckman/SideStep that referenced this pull request Oct 16, 2026
…anisette-v3 servers

- Default to Windows anisette-v3 servers (ani.jkcoxson.com, fallback ani2.stikstore.app);
  reject servers whose client_info isn't Windows
- Send the server's own client_info as X-MMe-Client-Info and its user_agent as User-Agent
  for all GrandSlam requests (incl. 2FA); re-provision when the client info changes
- cpd and headers aligned with clients that currently sign in (rileytestut/AltSign#61)
- Resynchronize anisette on hsc 434 (X-Apple-I-MD-DATA), retry once with fresh anisette on 503
- Fresh anisette for the post-2FA sign-in
- One URLSession per GrandSlam request
- Report non-200 GrandSlam answers as HTTP errors instead of plist parse errors (3840)
- One-line step logging for GrandSlam requests

Based on altstoreio/AltStore 22f766d and rileytestut/AltSign 6b12fdc / 832d9ce (AGPL-3.0).
@whydr4

whydr4 commented Oct 16, 2026

Copy link
Copy Markdown

Small thing, this PR targets master, so GitHub shows over 2000 changed files. Compared to notarized it's just #59 plus your three commits in two files, so retargeting it to notarized should make it a lot easier to review.

@kisnner26
kisnner26 changed the base branch from master to notarized October 16, 2026 19:04
@kisnner26

Copy link
Copy Markdown
Author

Thanks, good catch. I've retargeted it to notarized: it now shows 4 commits in 2 files (#59 plus the three on top).

izaankml pushed a commit to izaankml/AltStore that referenced this pull request Oct 18, 2026
…'s identity

Points AltSign to rileytestut/AltSign#61 (which includes altstoreio#59): configurable authentication User-Agent, anisette data refresh and resync handlers, readable HTTP errors, and handling 2FA codes Apple sends on its own.
liuzhe1117 added a commit to liuzhe1117/AltSign that referenced this pull request Oct 21, 2026
…ntity

Source: rileytestut#61
Preserve the original PR commits and authors.
liuzhe1117 added a commit to liuzhe1117/AltSign that referenced this pull request Oct 21, 2026
Keep the initial User-Agent and reject stable device identity changes before sending GrandSlam requests. Allow refreshed OTP and machine data for the same identity.

Incremental change on top of PR rileytestut#61; no diagnostic capture or HTTP retry policy.
@rileytestut

Copy link
Copy Markdown
Owner

Awesome work, thanks so much for investigating and this fix! Overall looks good to me, so I've merged it in, and will be releasing a update with these changes very soon 🙂

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.

4 participants