How IPATool Manages App Store Sessions: SAP Authentication and Session Flow

IPATool authenticates to the Apple App Store using Apple's SAP (Store-Apple-Protocol) and creates a short-lived purchase-history session (mlid) that it reuses for all subsequent API calls during a single CLI execution.

The majd/ipatool repository implements a sophisticated session management system for interacting with Apple's servers without requiring persistent browser cookies. By leveraging the Store-Apple-Protocol (SAP), IPATool establishes temporary credentials that grant access to purchase history and app downloading capabilities while maintaining a strict ephemeral security model.

SAP Authentication and Session Initialization

IPATool begins the session lifecycle by configuring the machine identity and establishing a secure channel with Apple's servers. In pkg/appstore/appstore_login.go, the tool obtains the machine's MAC address and builds a GUID before fetching the current bag—Apple's configuration bundle containing cryptographic parameters.

The authentication flow in appstore_login.go:38-62 creates an ActionSigner from the bag's SAPConfig, which cryptographically signs all subsequent requests. When a user provides their Apple ID credentials, IPATool sends a POST request to the SAP authentication endpoint with the email, password, and optional two-factor code, all signed by the ActionSigner (lines 58-78).

// SAP login establishes the foundation for session creation
loginInput := appstore.LoginInput{
    Email:    "user@apple.com",
    Password: "secret",
}
loginOut, err := store.Login(loginInput) // Returns Account with tokens
if err != nil {
    log.Fatal(err)
}

Extracting the Session ID (mlid) from Login Responses

Upon successful authentication, Apple's servers return a response containing the mlid field (machine ID session identifier). IPATool extracts this value in pkg/appstore/appstore_owned_apps.go:138-144 using the firstDMAPUint helper function.

The implementation validates that the mlid fits within a 32-bit unsigned integer before accepting it as the official session identifier. If the field is missing or fails validation, the operation returns an error immediately, preventing unauthorized requests.

Propagating the Session Across API Calls

Once extracted, the session ID is stored in the appstore struct's sessionID field (t.sessionID) and injected into every subsequent request body targeting the purchase-history service. As implemented in appstore_owned_apps.go:209-224, this ensures continuity across multiple API interactions without re-authenticating.

Each request body follows URL-encoded form format, beginning with session-id=<mlid>. The helper functions ownedAppsUpdateRequest and ownedAppsItemsRequest (lines 210-235) automatically embed this identifier:

// Extracting and using the session ID for owned apps requests
sessionID, ok, err := firstDMAPUint(loginResult.Data, "mlid")
if err != nil || !ok {
    log.Fatal("no session id")
}
req := store.ownedAppsUpdateRequest(acc, guid, uint32(sessionID), query, signer)
// Generates request.Body => "session-id=42&revision-number=(null)&query=..."
resp, err := store.ownedAppsClient.Send(req)

Session Lifetime and Ephemeral Security Model

IPATool implements a strict ephemeral session policy. The mlid session is valid only for the duration of the current command execution and exists solely in memory within the appstore instance. After the command completes, the appstore object is discarded, forcing the next CLI invocation to establish a fresh session.

No long-term cookies or session tokens are stored on disk. The only persistent authentication data is the Account record saved in the system keychain (containing login tokens), while the short-lived mlid session must be regenerated for every operation. This design ensures that compromising the local file system does not grant access to active App Store sessions.

Implementation Files and Code Structure

File Role in Session Management
pkg/appstore/appstore_login.go Implements SAP login flow, creates the ActionSigner, and handles the initial authentication handshake with Apple servers.
pkg/appstore/appstore_owned_apps.go Extracts the mlid (session-id) from login responses and constructs request bodies with embedded session identifiers.
pkg/appstore/appstore.go Defines the appstore struct that carries the sessionID between method calls within a single CLI execution.
pkg/http/request.go Provides the HTTP request infrastructure for sending signed SAP payloads including the session-id parameter.

Summary

  • IPATool uses SAP (Store-Apple-Protocol) for initial authentication, creating an ActionSigner from Apple's configuration bag.
  • The mlid (machine ID) serves as the temporary session identifier extracted from login responses using firstDMAPUint.
  • Session IDs are validated as 32-bit unsigned integers and stored in memory within the appstore struct.
  • Every API request includes the session ID in a URL-encoded form body starting with session-id=<mlid>.
  • Sessions are ephemeral—they exist only during a single command execution and are never cached between CLI runs.
  • Only the Account credentials are persisted in the system keychain; active sessions must be re-established for each operation.

Frequently Asked Questions

What is the mlid in IPATool's session management?

The mlid (machine ID) is a temporary session identifier returned by Apple's servers after successful SAP authentication. IPATool extracts this value from the login response and uses it as the session-id parameter for all subsequent App Store API calls during a single command execution.

Does IPATool store App Store sessions between commands?

No. IPATool does not persist session cookies or the mlid identifier between CLI invocations. While the Account credentials are stored in the system keychain for convenience, the actual App Store session must be re-established fresh for each command, ensuring no long-lived session tokens remain on disk.

How does IPATool authenticate with Apple servers?

IPATool uses the Store-Apple-Protocol (SAP), an internal Apple authentication protocol. The tool creates an ActionSigner from cryptographic parameters in Apple's configuration bag and sends signed requests containing the user's Apple ID credentials. Upon validation, Apple returns the temporary session identifier (mlid) used for subsequent requests.

Why does IPATool validate the session ID as a 32-bit unsigned integer?

The validation in appstore_owned_apps.go:138-144 ensures data integrity and type safety when extracting the mlid from Apple's response. By confirming the session ID fits within a 32-bit unsigned integer using firstDMAPUint, IPATool prevents malformed responses from causing integer overflow errors and ensures compatibility with the downstream API requirements.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →