Skip to content

Cookie domain mismatch in @expo/apple-utils pagination (developer-mdn.apple.com vs developer.apple.com) #3392

@christopherwxyz

Description

@christopherwxyz

Summary

The Cookie not in this host's domain. Cookie:developer-mdn.apple.com Request:developer.apple.com error continues to occur in eas-cli 16.32.0 with @expo/apple-utils v2.1.13. This is the same bug reported in #1672, #2224, and #2881 — all closed without a root-cause fix.

Root Cause Analysis

The bug is in ConnectResponse.fetchNextPageAsync() inside @expo/apple-utils.

How requests normally work:

  1. ConnectClientAPI.requestAsync() sets baseURL: await this.getHostnameAsync(u) which resolves to https://developer-mdn.apple.com
  2. Cookies are stored for the developer-mdn.apple.com domain
  3. Relative URL paths (e.g., devices, profiles) are resolved against this baseURL — works fine

How pagination breaks:

  1. Apple's JSON:API responses include links.next with absolute URLs like https://developer.apple.com/services-account/v1/...
  2. ConnectResponse.getNextUrl() returns this raw absolute URL from this.data.links.next
  3. fetchNextPageAsync() passes this absolute URL to this.getRequestAsync(this.context, {method:"get", url: e})
  4. Inside requestAsync, axios sees the URL is already absolute and ignores the baseURL (developer-mdn.apple.com)
  5. The request goes to developer.apple.com instead of developer-mdn.apple.com
  6. tough-cookie rejects the developer-mdn.apple.com cookies for the developer.apple.com domain
  7. Build fails with Cookie not in this host's domain

Relevant code path (from minified build):

// ConnectResponse class
getNextUrl() {
  return this.data?.links?.next ?? null;  // Returns absolute Apple URL
}

async fetchNextPageAsync() {
  const url = this.getNextUrl();
  return url ? this.getRequestAsync(this.context, { method: "get", url }) : null;
  // ^ Passes absolute URL directly — baseURL is ignored by axios
}

// ConnectClientAPI
async requestAsync(context, options, retryOptions) {
  return await this.requestFromAPIAsync(context, {
    baseURL: await this.getHostnameAsync(context),  // developer-mdn.apple.com
    ...options,  // options.url is absolute, so baseURL is ignored
  }, retryOptions);
}

Proposed Fix

In getNextUrl(), convert the absolute pagination URL to a relative path so baseURL handles domain resolution:

getNextUrl() {
  const next = this.data?.links?.next ?? null;
  if (!next) return null;
  try {
    const parsed = new URL(next);
    return parsed.pathname + parsed.search;  // Strip the domain, keep the path
  } catch {
    return next;
  }
}

This ensures pagination requests go through the same domain (developer-mdn.apple.com) as all other requests, respecting the baseURL set in requestAsync.

Environment

eas-cli/16.32.0 darwin-arm64 node-v25.2.1
@expo/apple-utils v2.1.13
macOS 15.4 (Darwin 25.2.0)

Error Output

✔ Logged in New session
Authentication with Apple Developer Portal failed!
Cookie not in this host's domain. Cookie:developer-mdn.apple.com Request:developer.apple.com
    Error: build command failed.

This occurs during Handling Apple ad hoc provisioning profiles — authentication succeeds, but the subsequent paginated API call to list devices/profiles fails.

Steps to Reproduce

eas build --platform ios --profile development

Using Apple ID login (not ASC API key). The error occurs when EAS CLI successfully authenticates but then paginates through devices or provisioning profiles.

Why This Keeps Recurring

The underlying bug in ConnectResponse.fetchNextPageAsync() has never been fixed. Previous issues were resolved by:

  • Apple temporarily changing their API to not redirect
  • Users switching to ASC API keys as a workaround
  • Stale bot closing issues

The @expo/apple-utils pagination code needs to normalize URLs to the working domain before making follow-up requests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions