Hello everyone,
I’m developing a Checkout UI Extension that needs to fetch a json configurations from my backend server through a Shopify app
proxy. However, I’m encountering a persistent CORS error that I cannot resolve. I’ve read that this can be caused by a password protection issue, but I’m unsure how that would be fair to people who do not have access to a Live Shopify Plus subscription and or Paid Partner Plus sandbox site. Im using a Partner Development site with correct config.
(ive changed variables to obfuscate so might be wrong here)
The Error:
Access to fetch at
'https://store-worki1.myshopify.com/apps/app-dev-proxy/endpoint?foo=quick&operation=GET_SOMETHING' from
origin 'https://extensions.shopifycdn.com' has been blocked by CORS policy: Response to preflight request doesn't pass access
control check: Redirect is not allowed for a preflight request.
My Setup:
Checkout Extension Code (Checkout.tsx):
const { shop } = useApi();
const sessionToken = useSessionToken();
const checkoutToken = useCheckoutToken();
const shopDomain = shop.myshopifyDomain!;
const PROXY_BASE_URL = useMemo(() =>
`${shop.storefrontUrl}/apps/app-dev-proxy`,
[]
);
...
const currentSessionToken = await sessionToken.get();
const currentCheckoutToken = checkoutToken;
// Making the request
const [quickResponse, enhancedResponse] = await Promise.all([
fetch(`${PROXY_BASE_URL}/endpoint?foo=quick&operation=GET_SOMETHING`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${currentSessionToken}`,
}
}),
fetch(`${PROXY_BASE_URL}/endpoint?foo=enhanced&operation=GET_SOMETHING`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${currentSessionToken}`,
}
})
]);
App Proxy Configuration:
shopify.app.dev-1.toml:
[app_proxy]
url = "https://ngrok-ngrok-wombat.ngrok-free.app/api/proxy"
subpath = "app-dev-proxy"
prefix = "apps"
shopify.extension.toml:
[extensions.capabilities]
api_access = true
network_access = true
Backend Route (api.proxy.endpoint.tsx):
export const loader = async ({ request }: LoaderFunctionArgs) => {
logRequestContext(request, { handler: 'loader' });
const { admin } = await authenticate.public.appProxy(request);
const { sessionToken, cors } = await authenticate.public.checkout(request);
// Handle CORS preflight OPTIONS request
if (request.method === 'OPTIONS') {
return cors(new Response(null, { status: 200 }));
}
....
return cors(Response.json(
{
success: true,
data: foo,
operation: 'GET_FOO',
source: configSource,
fooType: finalfooType,
shopDomain: shopDomain
},
{ status: 200 }
));
What I’ve Tried:
- Proper CORS headers in OPTIONS preflight handling
- Using absolute URLs instead of relative paths
- Both authenticate.public.appProxy() and authenticate.public.checkout() authentication
- Verified app proxy configuration in Shopify admin
- Added cors() wrapper to all responses
The Issue:
The error specifically mentions “Redirect is not allowed for a preflight request”, which suggests that somewhere in the request
chain, there’s a redirect happening during the OPTIONS preflight request that browsers don’t allow. I have logging in my remix file but it cant even reach it.
Questions:
- I seen a thread about
possibility that the error may appear if your shop is password protected on the frontend
, if this is the case how would I be able to bypass this when using a Partner Development store with Shopify Plus? I need the shopify plus features for the purpose of my extension. - Is there a known issue with app proxies and Checkout UI Extensions causing redirects during CORS preflight?
- Should I be using a different URL structure for checkout extensions vs regular storefront requests?
- Is there a specific way to configure Remix routes to handle app proxy requests from checkout extensions without redirects?
Working Alternative:
When I bypass the app proxy and use a direct external URL (which I don’t want to expose), the requests work perfectly. This
confirms the issue is specifically with the app proxy handling of checkout extension requests.
Any guidance would be greatly appreciated! This seems to be a common issue but I haven’t found a definitive solution.
Environment:
- Shopify CLI: Latest
- App:
Checkout and account UI extensions are enabled
- Store:
Checkout and Customer Accounts Extensibility
feature enabled. But password protected since not a sandbox. - Remix: Latest
- Checkout UI Extensions: 2025-07