docs / runtime behaviour

Talking to a backend: CORS, cookies and sign-in

Your pages run on the origin https://appassets.androidplatform.net. To your API that is a different site from your website — which decides whether requests are allowed, whether cookies are sent, and which sign-in methods work.

8 min read·6 sections·updated Sep 2026
TL;DR

Add https://appassets.androidplatform.net to your API's allowed CORS origins. Authenticate with a token in the Authorization header rather than cookies. Google blocks its OAuth sign-in inside WebViews, so offer email/password, magic links or phone sign-in in the app.

Your app is a new origin

On your website, the page at https://example.com calling https://example.com/api is a same-origin request: no CORS, cookies flow freely. In the app, the same code runs at https://appassets.androidplatform.net/web/, so every request to your API is cross-origin, and the browser enforces three rules on it:

  1. The API must answer with an Access-Control-Allow-Origin header that permits the app's origin, or the response is hidden from your code.
  2. Requests with JSON bodies or custom headers are preceded by an OPTIONS preflight the API must also answer.
  3. Cookies are only sent cross-site if they are marked SameSite=None; Secure and the request opts in with credentials: 'include'.

Public APIs that already send Access-Control-Allow-Origin: * (most weather, maps and open-data APIs; Supabase; Firebase's REST endpoints) work with no changes.

Allowing the origin

app.use(cors({
  origin: ['https://example.com', 'https://appassets.androidplatform.net'],
  allowedHeaders: ['Content-Type', 'Authorization'],
}))
const ALLOWED = new Set(['https://example.com', 'https://appassets.androidplatform.net'])
function cors(req, res) {
  const o = req.headers.get('Origin')
  if (ALLOWED.has(o)) {
    res.headers.set('Access-Control-Allow-Origin', o)
    res.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
    res.headers.set('Vary', 'Origin')
  }
  return res
}
'allowed_origins' => ['https://example.com', 'https://appassets.androidplatform.net'],
if ($http_origin = "https://appassets.androidplatform.net") {
  add_header Access-Control-Allow-Origin $http_origin always;
  add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
}

Every ZIP-built app shares this origin. Allowing it means any such app could call your API from a user's phone — the same as any website could with *. CORS is a browser courtesy, not access control; your API still needs real authentication.

Tokens beat cookies

Session cookies set by your API are third-party cookies from the app's point of view. The app accepts them, but most frameworks issue SameSite=Lax session cookies, which the browser will not send on cross-site fetch. Rather than loosening your cookie policy, authenticate the app with a bearer token:

const token = localStorage.getItem('token')
const res = await fetch('https://api.example.com/orders', {
  headers: { Authorization: `Bearer ${token}` },
})

Store short-lived access tokens with a refresh flow; localStorage in the app is private to it and survives updates.

Sign-in methods that work

MethodIn the app
Email + password, your own backend✓
Magic link / one-time code by email✓ (code entry is smoother than links, which open the mail app's browser)
Phone number + SMS code✓ (invisible reCAPTCHA needs the app's hostname allowed in your provider's settings)
Google sign-in (OAuth popup or redirect)✗ Google rejects OAuth requests from embedded WebViews (disallowed_useragent)
Facebook, Apple, GitHub OAuthUnreliable — providers increasingly block or degrade WebView sign-in

With Firebase Authentication, add appassets.androidplatform.net to Authorized domains and use email/password, email link or phone providers in the app build. If Google sign-in is essential, it needs a native integration rather than a web page.

HTTP, mixed content and certificates

The app is permissive about plain http:// APIs and mixed content, so a test server on your LAN works. Do not ship that way: traffic is readable on any shared Wi-Fi. Self-signed certificates are rejected — use a real certificate (Let's Encrypt, or a tunnel such as Cloudflare Tunnel for testing).

Secrets

Everything in the ZIP can be read by unzipping the APK. Publishable keys are fine. Anything that grants write access, billing or admin rights belongs on a server; the app calls that server with the user's token.

FAQ

What Origin header does my API see from the app?

https://appassets.androidplatform.net — the same for every ZIP-built app, and independent of your package name.

Why does Google sign-in fail with disallowed_useragent?

Google blocks OAuth consent screens inside embedded WebViews to protect users' passwords. The web Google sign-in flow therefore cannot run inside the app; use another sign-in method in the app build.

Can I use Firebase in the app?

Yes — Firestore, Realtime Database, Storage and most Auth providers work from the app's origin. Add appassets.androidplatform.net to Authorized domains and avoid Google popup sign-in.

Tools for this step

Unzip it on a phone today

Upload the ZIP, name the app, pick an icon — and download a signed APK a few minutes later. Free builds, no watermark, no Android Studio.

Convert a ZIP — free site.zip → app-release.apk