How the ipatool Download Command Handles License Requirements: Detection and Acceptance Flow
The ipatool download command detects license requirements by inspecting Apple App Store API responses for specific error codes, then either prompts the user to accept the license interactively or allows explicit acceptance via the --accept-license flag.
The download command in the majd/ipatool repository automates IPA downloads from the Apple App Store while ensuring compliance with mandatory license agreements. When Apple's servers require explicit license acceptance before delivering an application bundle, the command implements a structured three-step flow—detection, user notification, and header-based acceptance—to handle the requirement gracefully without silent failures.
License Detection in the macOS Adapter
The core detection logic resides in pkg/appstore/appstore_download_macos_adapter.go. When the download adapter communicates with Apple's servers, it inspects HTTP responses for status codes and JSON payloads indicating a license requirement.
Identifying License-Required Responses
The doRequest method checks for HTTP 403 (Forbidden) responses and parses the JSON body for an errorCode field. If this field contains LICENSE_REQUIRED, the adapter returns appstore.ErrLicenseRequired to signal that user intervention is necessary before the download can proceed.
// pkg/appstore/appstore_download_macos_adapter.go – licence detection
func (d *macOSDownloader) doRequest(req *http.Request) error {
// …perform HTTP request…
if resp.StatusCode == http.StatusForbidden {
var respBody struct {
ErrorCode string `json:"errorCode"`
}
json.NewDecoder(resp.Body).Decode(&respBody)
if respBody.ErrorCode == "LICENSE_REQUIRED" {
return fmt.Errorf("%w: license agreement needed", appstore.ErrLicenseRequired)
}
}
// …normal processing…
return nil
}
Error Handling in the Command Layer
The cmd/download.go file implements the user-facing logic that catches license errors and provides actionable remediation steps. This ensures users understand why a download failed and how to fix it.
Interactive Prompting and User Instructions
When the RunE handler catches ErrLicenseRequired, it writes a descriptive message to stderr explaining that the application requires license acceptance. The user can then either open the App Store application to accept the agreement interactively, or re-run the command with the --accept-license flag for non-interactive workflows.
// cmd/download.go – simplified flow
func runDownload(cmd *cobra.Command, args []string) error {
// …parse flags, create download options…
opts := []appstore.DownloadOption{
appstore.WithAppID(appID),
}
if acceptLicense {
opts = append(opts, appstore.WithAcceptLicense())
}
err := appstore.Download(ctx, opts...)
if err != nil {
if errors.Is(err, appstore.ErrLicenseRequired) {
fmt.Fprintln(cmd.ErrOrStderr(),
"This app requires you to accept a license agreement. "+
"Run the command again with '--accept-license' or open the App Store UI to accept it.")
return err
}
return err
}
fmt.Fprintln(cmd.OutOrStdout(), "Download completed successfully.")
return nil
}
Explicit License Acceptance Mechanism
When the user provides the --accept-license flag, the command enables the AcceptLicense option in the download configuration. This signals the adapter to include a specific header that satisfies Apple's license acceptance protocol.
The X-Apple-Store-Licence-Accepted Header
According to the implementation in pkg/appstore/appstore_download_macos_adapter.go, setting the AcceptLicense option causes the adapter to add the X-Apple-Store-Licence-Accepted: 1 HTTP header to the request. This header indicates to Apple's servers that the user has explicitly agreed to the license terms, allowing the download to complete successfully without further user interaction.
Key Implementation Files
The license handling flow spans four critical files in the repository:
cmd/download.go: Implements the CLI command, parses the--accept-licenseflag, and handlesErrLicenseRequiredwith user-facing error messages.pkg/appstore/appstore_download.go: Defines the high-levelDownloadfunction and provides theWithAcceptLicenseoption for configuring license acceptance.pkg/appstore/appstore_download_macos_adapter.go: Contains the platform-specific logic for detecting license errors via HTTP response inspection and injecting the acceptance header.pkg/appstore/appstore_download_macos.go: Acts as a wrapper that instantiates the macOS-specific adapter for the download operation.
Summary
- Detection: The macOS adapter in
appstore_download_macos_adapter.goparses HTTP 403 responses and JSONerrorCodefields to identifyLICENSE_REQUIREDerrors. - Notification: The command layer catches these errors and prints explicit instructions to stderr, preventing silent failures.
- Acceptance: Users can accept licenses interactively through the App Store UI or non-interactively using the
--accept-licenseflag, which triggers theX-Apple-Store-Licence-Accepted: 1header. - Architecture: The implementation separates concerns between API interaction (adapter), orchestration (appstore package), and CLI handling (command layer).
Frequently Asked Questions
What happens if I run the download command without the --accept-license flag when a license is required?
The command will detect the requirement via the macOS adapter, print an error message to stderr explaining that you must accept the license agreement, and exit with a non-zero status. The IPA will not download until you either open the App Store application to manually accept the license, or re-run the command with the --accept-license flag.
Does ipatool automatically accept licenses on my behalf?
No. The source code in cmd/download.go explicitly checks for appstore.ErrLicenseRequired and requires explicit user action. The tool never silently accepts licenses; it will always prompt you or require the explicit --accept-license flag to proceed, ensuring you consciously agree to the terms.
Which specific error code triggers the license requirement handler?
The handler triggers when the JSON response body from Apple's servers contains "errorCode": "LICENSE_REQUIRED". This string is checked in the doRequest method of pkg/appstore/appstore_download_macos_adapter.go when processing HTTP 403 responses.
Is the license acceptance flow available on all operating systems?
The license detection and acceptance logic is specific to the macOS implementation found in pkg/appstore/appstore_download_macos_adapter.go. The X-Apple-Store-Licence-Accepted header and the associated error parsing are part of the macOS-specific adapter, as ipatool is designed primarily for interacting with the macOS App Store infrastructure.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →