Skip to content

fix: update auth endpoint + stale lock file cleanup#486

Open
ricky0603 wants to merge 3 commits into
majd:mainfrom
ricky0603:fix/apple-auth-endpoint-hotfix24
Open

fix: update auth endpoint + stale lock file cleanup#486
ricky0603 wants to merge 3 commits into
majd:mainfrom
ricky0603:fix/apple-auth-endpoint-hotfix24

Conversation

@ricky0603

@ricky0603 ricky0603 commented Jun 6, 2026

Copy link
Copy Markdown

Problem

Apple's 26HOTFIX24 (June 2026) broke ipatool login for all accounts, and the obvious "switch to the appstored User-Agent" workaround silently breaks purchase afterward.

Two things changed:

  1. The authenticateAccount key moved to the Bag root (it used to live under urlBag).
  2. The native auth endpoint requires a trailing slash: https://auth.itunes.apple.com/auth/v1/native/fast/. Without it Apple returns 301 + an HTML redirect page, which surfaces as something went wrong / unexpected hex digit 'h'. The Bag now advertises …/auth/v1/native (no /fast at all), so the client must append /fast/.

The trailing slash is the load-bearing fix: with it, the default Configurator/2.17 UA logs in and mints a commerce-grade passwordToken that buyProduct accepts. (Dodging the 301 by switching to com.apple.appstored/1.0 makes login look fixed but yields a download-grade token that buyProduct rejects with failureType 2034.)

Changes

  • pkg/appstore/appstore_bag.go: read authenticateAccount from the Bag root and urlBag, and normalize the resolved endpoint to always end with /fast/.
  • pkg/appstore/constants.go: PrivateAuthPathNative fallback gains the trailing slash; add the AMD-Action::SP customer-message constant.
  • pkg/appstore/appstore_login.go: surface AMD-Action::SP as a clear "account requires browser sign-in" error.
  • cmd/common.go: remove a stale zero-byte cookie lock file on startup (independent bug).

Validation

Verified end-to-end (login + purchase + download) across many accounts with the stock Configurator UA — no anisette / kbsync / device signature needed. See #485 for the detailed write-up.

wl added 2 commits June 7, 2026 06:15
Apple's authentication service moved the endpoint from
buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/authenticate
to auth.itunes.apple.com/auth/v1/native/fast, and simultaneously
moved the `authenticateAccount` key in the Bag XML from inside the
`urlBag` dict to the root level.

Changes:
- bagResult: add root-level `authenticateAccount` plist field so the
  Bag() function reads it before falling back to urlBag (backward compat)
- Bag(): append /fast suffix when the resolved endpoint uses the new
  auth.itunes.apple.com domain, matching what the Bag XML signals via
  `auth/v1/native: ["fast"]`
- constants: add PrivateAuthDomain / PrivateAuthPathNative for the new
  endpoint
- loginRequest: use the new auth endpoint as the hardcoded fallback
  (replaces the implicit empty-string which caused "something went wrong"
  when Bag lookup returned nothing)

Without this fix every login attempt returns HTTP 200 with an empty body
in ~1 ms, which the code surfaces as "something went wrong".
The juju/persistent-cookiejar library (via juju/go4/lock) creates a
lock file at <cookies>.lock, writing the owner PID as JSON. If a
process is killed between file creation (O_TRUNC) and the PID write,
a 0-byte file remains. On the next startup the library skips PID-based
stale detection (only runs when fi.Size() > 0) and falls back to
os.OpenFile with O_EXCL, which fails because the file already exists.
The result is "cannot load cookies: file locked for too long; giving up"
on every subsequent invocation until the file is manually removed.

Fix: in newCookieJar(), stat the lock path before opening the jar and
remove the file if it is zero bytes. Zero-byte lock files are always
stale because a live process always writes its PID immediately after
creating the file.
@void-eth

void-eth commented Jun 7, 2026

Copy link
Copy Markdown

pulled these changes into a local clone and tested against my Apple ID. The auth endpoint fix is clearly working now, the request actually reaches Apple's auth server instead of returning the old empty-body "something went wrong" error.

I did hit a rate limit on the 2FA step though:

6:25PM INF enter 2FA code: 828232
6:25PM ERR error="request failed: rate limited by Apple (HTTP 429): Rate limit has been exceeded for: mzauth|global|all" success=false

To be clear, this 429 is coming from Apple's side (mzauth|global|all), not from anything in the patch. Before these changes the login never got far enough to even talk to the new endpoint, so reaching the point where Apple rate-limits us is actually a good sign that the new auth.itunes.apple.com/auth/v1/native/fast path is being used correctly. I'd been retrying logins a fair bit while testing, which probably tripped the limit. I'll wait it out and retry to confirm a clean end-to-end login.

Thanks for putting this together.

@BeauGiles

Copy link
Copy Markdown

also getting the "Rate limit has been exceeded" error, even on a fresh account that hasn't been logged into for... weeks.

@umonaca

umonaca commented Jun 7, 2026

Copy link
Copy Markdown

I did hit a rate limit on the 2FA step though:

With a residential proxy IP or my real residential IP, I have successfully logged in and downloaded IPA. No 429 error.

With the following command you can test if your IP is being restricted or rate limited by Apple:

curl -H "Configurator/2.17 (Macintosh; OS X 15.3.1; 24D70) AppleWebKit/0620.1.16.11.6" -v "https://auth.itunes.apple.com/auth/v1/native/fast"

If you get the following response and a 429 error, your IP is rate limited. Otherwise the response body will be empty (with 404 status code).

Rate limit has been exceeded for: mzauth|global|all

@FimastGDx

Copy link
Copy Markdown

thx u bro

umonaca added a commit to umonaca/ipatool that referenced this pull request Jun 7, 2026
@tux-mind

tux-mind commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Got weird results.
Sometimes the login endpoint responds with:

<html>\r\n<head><title>503 Service Temporarily Unavailable</title></head>\r\n<body>\r\n<center><h1>503 Service Temporarily Unavailable</h1></center>\r\n<hr><center>Apple</center>\r\n</body>\r\n</html>\r\n

Other times with this:

>>> HTTP 500 | headers: map[Content-Length:[170] Content-Type:[text/html] Date:[Mon, 08 Jun 2026 20:15:46 GMT] Server:[Apple] Strict-Transport-Security:[max-age=31536000; includeSubdomains] X-Content-Type-Options:[nosniff] X-Frame-Options:[SAMEORIGIN] X-Xss-Protection:[1; mode=block]] | body: "<html>\r\n<head><title>500 Internal Server Error</title></head>\r\n<body>\r\n<center><h1>500 Internal Server Error</h1></center>\r\n<hr><center>Apple</center>\r\n</body>\r\n</html>\r\n"

And others times results in an empty body with 204, causing this:

>>> HTTP 204 | headers: map[Date:[Mon, 08 Jun 2026 20:17:49 GMT] Server:[Apple] Strict-Transport-Security:[max-age=31536000; includeSubdomains] X-Content-Type-Options:[nosniff] X-Frame-Options:[SAMEORIGIN] X-Xss-Protection:[1; mode=block]] | body: ""
{"level":"debug","error":"something went wrong","metadata":{"StatusCode":204,"Headers":{"Date":"Mon, 08 Jun 2026 20:17:49 GMT","Server":"Apple","Strict-Transport-Security":"max-age=31536000; includeSubdomains","X-Content-Type-Options":"nosniff","X-Frame-Options":"SAMEORIGIN","X-Xss-Protection":"1; mode=block"},"Data":{"FailureType":"","CustomerMessage":"","Account":{"Email":"","Address":{"FirstName":"","LastName":""}},"DirectoryServicesID":"","PasswordToken":""}},"time":"2026-06-08T20:17:49Z"}
{"level":"error","error":"something went wrong","success":false,"time":"2026-06-08T20:17:49Z"}

That 204 looks like a success but it doesn't provide a password token or anything to use the API...

@feiyehua

feiyehua commented Jun 9, 2026

Copy link
Copy Markdown

Got weird results. Sometimes the login endpoint responds with:

<html>\r\n<head><title>503 Service Temporarily Unavailable</title></head>\r\n<body>\r\n<center><h1>503 Service Temporarily Unavailable</h1></center>\r\n<hr><center>Apple</center>\r\n</body>\r\n</html>\r\n

Other times with this:

>>> HTTP 500 | headers: map[Content-Length:[170] Content-Type:[text/html] Date:[Mon, 08 Jun 2026 20:15:46 GMT] Server:[Apple] Strict-Transport-Security:[max-age=31536000; includeSubdomains] X-Content-Type-Options:[nosniff] X-Frame-Options:[SAMEORIGIN] X-Xss-Protection:[1; mode=block]] | body: "<html>\r\n<head><title>500 Internal Server Error</title></head>\r\n<body>\r\n<center><h1>500 Internal Server Error</h1></center>\r\n<hr><center>Apple</center>\r\n</body>\r\n</html>\r\n"

And others times results in an empty body with 204, causing this:

>>> HTTP 204 | headers: map[Date:[Mon, 08 Jun 2026 20:17:49 GMT] Server:[Apple] Strict-Transport-Security:[max-age=31536000; includeSubdomains] X-Content-Type-Options:[nosniff] X-Frame-Options:[SAMEORIGIN] X-Xss-Protection:[1; mode=block]] | body: ""
{"level":"debug","error":"something went wrong","metadata":{"StatusCode":204,"Headers":{"Date":"Mon, 08 Jun 2026 20:17:49 GMT","Server":"Apple","Strict-Transport-Security":"max-age=31536000; includeSubdomains","X-Content-Type-Options":"nosniff","X-Frame-Options":"SAMEORIGIN","X-Xss-Protection":"1; mode=block"},"Data":{"FailureType":"","CustomerMessage":"","Account":{"Email":"","Address":{"FirstName":"","LastName":""}},"DirectoryServicesID":"","PasswordToken":""}},"time":"2026-06-08T20:17:49Z"}
{"level":"error","error":"something went wrong","success":false,"time":"2026-06-08T20:17:49Z"}

That 204 looks like a success but it doesn't provide a password token or anything to use the API...

Same 500 and 204 error for me:

request failed: failed to unmarshal xml from endpoint https://auth.itunes.apple.com/auth/v1/native/fast (status 503, content-type \"text/html\", response \"<html>\\r\\n<head><title>503 Service Temporarily Unavailable</title></head>\\r\\n<body>\\r\\n<center><h1>503 Service Temporarily Unavailable</h1></center>\\r\\n<hr><center>Apple</center>\\r\\n</body>\\r\\n</html>\"): plist: error parsing text property list: unexpected hex digit `h' at line 0 character 2

Also 404 and 403:

12:54PM DBG error="request failed: failed to unmarshal xml from endpoint https://auth.itunes.apple.com/auth/v1/native/fast (status 403, content-type \"text/html\", response \"<html>\\r\\n<head><title>403 Forbidden</title></head>\\r\\n<body>\\r\\n<center><h1>403 Forbidden</h1></center>\\r\\n<hr><center>Apple</center>\\r\\n</body>\\r\\n</html>\"): plist: error parsing text property list: unexpected hex digit `h' at line 0 character 2"
12:55PM DBG error="request failed: failed to unmarshal xml from endpoint https://auth.itunes.apple.com/auth/v1/native/fast (status 403, content-type \"text/html\", response \"<html>\\r\\n<head><title>403 Forbidden</title></head>\\r\\n<body>\\r\\n<center><h1>403 Forbidden</h1></center>\\r\\n<hr><center>Apple</center>\\r\\n</body>\\r\\n</html>\"): plist: error parsing text property list: unexpected hex digit `h' at line 0 character 2"

And 301:

"request failed: failed to unmarshal xml from endpoint https://auth.itunes.apple.com/auth/v1/native/fast (status 301, content-type \"text/html\", response \"<html>\\r\\n<head><title>301 Moved Permanently</title></head>\\r\\n<body>\\r\\n<center><h1>301 Moved Permanently</h1></center>\\r\\n<hr><center>Apple</center>\\r\\n</body>\\r\\n</html>\"): plist: error parsing text property list: unexpected hex digit `h' at line 0 character 2"

@umonaca

umonaca commented Jun 9, 2026

Copy link
Copy Markdown

Bad news: it looks like Apple changed their endpoint again. I'm getting this error for new login sessions. It doesn't matter which IP address or account I'm using.

10:00AM DBG error="request failed: failed to unmarshal xml: plist: error parsing text property list: unexpected hex digit `h' at line 0 character 2"
10:00AM ERR error="request failed: failed to unmarshal xml: plist: error parsing text property list: unexpected hex digit `h' at line 0 character 2" success=false

Existing login sessions aren't affected.

@b-nnett

b-nnett commented Jun 10, 2026

Copy link
Copy Markdown

I opened #490 with a smaller auth-only follow-up.

It keeps the Bag root / urlBag handling from this PR, but also normalizes native auth URLs to /auth/v1/native/fast/ and keeps XML decode metadata so login can retry if Apple returns a non-plist response that contains a native auth URL.

One detail from testing: https://auth.itunes.apple.com/auth/v1/native/fast returned an HTML redirect for me, while ...native/fast/ (with a trailing slash) reached MZAuth and completed login.

Validated with:

  • go generate ./...
  • go test ./...
  • live ipatool auth login

…st/)

Without the trailing slash Apple returns 301 + an HTML redirect page, so the
Configurator UA appears "blocked" at login and the plist parser fails. With
the slash, the default Configurator/2.17 UA logs in and mints a commerce-grade
passwordToken that buyProduct accepts end-to-end (purchase + download) with no
anisette / kbsync / X-Apple-ActionSignature / device signature.

- normalize the Bag-resolved auth endpoint to always end with /fast/
- PrivateAuthPathNative fallback gains the trailing slash
- surface AMD-Action::SP as a clear "account requires browser sign-in" error
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.

8 participants