Skip to main content

Proxy & CORS

This page explains why pattern B (a same-origin GraphQL proxy) avoids CORS for the widget, and when pattern A (direct GraphQL + getHeaders) requires CORS to be configured. See Authentication for the full integration guidance.

The widget itself has no auth logic.

CORS is a browser rule

CORS limits JavaScript on one origin from reading responses from another origin unless the remote server explicitly allows it. It does not apply to server-to-server HTTP.

Pattern A — Direct GraphQL (CORS required)

Pagehttps://customer-portal.example.com
Widget apiUrlhttps://api.kraken.example.com/graphql

The widget runs fetch() in the browser toward the API. That is cross-origin, so the API (or your gateway) must respond with CORS headers (Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers) for your site's origin, or the browser blocks the response.

You also supply auth via getHeaders (e.g. Authorization: Bearer …).

Pattern B — Same-origin proxy (no CORS for the widget)

Pagehttps://customer-portal.example.com
Widget apiUrlhttps://customer-portal.example.com/api/graphql

The widget only talks to your app — same protocol, host, and port → same origin → no cross-origin restriction on that request.

Your server then calls the upstream API:

Your server → https://api.kraken.example.com/graphql

That hop is server-to-server, so CORS does not apply. Your proxy attaches Authorization (from the session, cookies, or a server-side token store) before calling upstream.

Takeaway: with a proxy, the widget never crosses origins to reach the API. Only your server does.

End-to-end flow (pattern B)

┌─────────────┐ POST /api/graphql ┌──────────────┐ POST + Authorization ┌────────┐
│ Widget │ ─────────────────────────► │ Your proxy │ ────────────────────────► │ Kraken │
│ (browser) │ cookies (optional) │ (your app) │ Bearer from server │ GraphQL│
└─────────────┘ no Authorization header └──────────────┘ └────────┘

The widget does not add Authorization. Your proxy reads the session server-side and builds a new authenticated request to the upstream API.

Summary

QuestionPattern A (direct)Pattern B (proxy)
Browser CORS needed?YesNo (same origin)
Who adds Authorization?getHeaders in widget configYour proxy route
Where is the token?Client (your app manages)Server / httpOnly cookies (your app manages)