{
    "componentChunkName": "component---src-pages-blog-markdown-remark-fields-slug-js",
    "path": "/blog/cors-errors",
    "result": {"data":{"markdownRemark":{"html":"<h2 id=\"what-is-a-cors-error-and-why-does-it-happen\" style=\"position:relative;\"><a href=\"#what-is-a-cors-error-and-why-does-it-happen\" aria-label=\"what is a cors error and why does it happen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What Is a CORS Error and Why Does It Happen?</h2>\n<h3 id=\"what-is-cors\" style=\"position:relative;\"><a href=\"#what-is-cors\" aria-label=\"what is cors permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What Is CORS?</h3>\n<p>Cross-Origin Resource Sharing (CORS) is a browser security mechanism that controls whether JavaScript running on one website can access resources from another. It extends the <strong>Same-Origin Policy (SOP)</strong> — the browser’s fundamental security boundary that prevents one site from reading data belonging to another.</p>\n<p>An <strong>origin</strong> is defined by three components:</p>\n<ul>\n<li><strong>Protocol</strong> — <code class=\"language-text\">http://</code> vs. <code class=\"language-text\">https://</code></li>\n<li><strong>Domain</strong> — <code class=\"language-text\">example.com</code> vs. <code class=\"language-text\">api.example.com</code></li>\n<li><strong>Port</strong> — <code class=\"language-text\">:3000</code> vs. <code class=\"language-text\">:8080</code></li>\n</ul>\n<p>Any difference in these components makes a request <em>cross-origin</em>, which requires explicit permission from the target server.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"86887697425451780000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Same-origin requests (no CORS needed)\nfetch('/api/users')                        // Relative URL\nfetch('https://myapp.com/api/data')        // Matches protocol, domain, and port\n\n// Cross-origin requests (CORS required)\nfetch('https://api.myapp.com/users')       // Different subdomain\nfetch('http://myapp.com/api/users')        // Different protocol\nfetch('https://myapp.com:8080/api/users')  // Different port`, `86887697425451780000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Same-origin requests (no CORS needed)</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/users'</span><span class=\"token punctuation\">)</span>                        <span class=\"token comment\">// Relative URL</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://myapp.com/api/data'</span><span class=\"token punctuation\">)</span>        <span class=\"token comment\">// Matches protocol, domain, and port</span>\n\n<span class=\"token comment\">// Cross-origin requests (CORS required)</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.myapp.com/users'</span><span class=\"token punctuation\">)</span>       <span class=\"token comment\">// Different subdomain</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://myapp.com/api/users'</span><span class=\"token punctuation\">)</span>        <span class=\"token comment\">// Different protocol</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://myapp.com:8080/api/users'</span><span class=\"token punctuation\">)</span>  <span class=\"token comment\">// Different port</span></code></pre></div>\n<p>The Same-Origin Policy exists to prevent malicious websites from silently reading your data from other sites — like your email, banking details, or session tokens.</p>\n<h3 id=\"what-triggers-a-cors-error\" style=\"position:relative;\"><a href=\"#what-triggers-a-cors-error\" aria-label=\"what triggers a cors error permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What Triggers a CORS Error?</h3>\n<p>A CORS error occurs when your browser blocks a response because the server didn’t include the required permission headers. Here’s what typically happens:</p>\n<ol>\n<li>Your frontend at <code class=\"language-text\">http://localhost:3000</code> makes a request to <code class=\"language-text\">https://api.yourservice.com</code></li>\n<li>The browser detects a cross-origin request</li>\n<li>The request is sent to the server</li>\n<li>The server responds <strong>without</strong> CORS headers</li>\n<li>The browser blocks JavaScript from reading the response</li>\n<li>A CORS error appears in the console</li>\n</ol>\n<blockquote>\n<p><strong>Critical insight:</strong> The request often completes successfully on the server. CORS doesn’t prevent requests — it prevents your JavaScript from <em>reading</em> the response. This distinction matters when debugging issues like duplicate database records despite seeing a console error.</p>\n</blockquote>\n<h3 id=\"cors-preflight-and-simple-requests\" style=\"position:relative;\"><a href=\"#cors-preflight-and-simple-requests\" aria-label=\"cors preflight and simple requests permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS Preflight and Simple Requests</h3>\n<p>The browser categorizes HTTP requests into two types for CORS purposes.</p>\n<p><strong>Simple requests</strong> proceed without a preflight check:</p>\n<ul>\n<li>Methods: <code class=\"language-text\">GET</code>, <code class=\"language-text\">HEAD</code>, or <code class=\"language-text\">POST</code></li>\n<li>No custom headers</li>\n<li><code class=\"language-text\">Content-Type</code> limited to <code class=\"language-text\">application/x-www-form-urlencoded</code>, <code class=\"language-text\">multipart/form-data</code>, or <code class=\"language-text\">text/plain</code></li>\n</ul>\n<blockquote>\n<p><strong>Terminology note:</strong> The term “simple requests” comes from the older CORS spec. The current <a href=\"https://fetch.spec.whatwg.org/\" target=\"_blank\" rel=\"nofollow\">Fetch Standard</a> doesn’t use this term, but browser behavior remains the same: these requests are sent directly, and the browser checks the <code class=\"language-text\">Access-Control-Allow-Origin</code> response header afterward.</p>\n</blockquote>\n<p><strong>Preflighted requests</strong> require an <code class=\"language-text\">OPTIONS</code> check first:</p>\n<ul>\n<li>Any method other than <code class=\"language-text\">GET</code>, <code class=\"language-text\">HEAD</code>, or <code class=\"language-text\">POST</code></li>\n<li>Custom headers like <code class=\"language-text\">Authorization</code> or <code class=\"language-text\">X-API-Key</code></li>\n<li><code class=\"language-text\">POST</code> with <code class=\"language-text\">Content-Type: application/json</code></li>\n</ul>\n<p>Here’s the full preflight flow:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"51539049104586880000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# 1. Browser sends preflight (OPTIONS)\nOPTIONS /api/users HTTP/1.1\nOrigin: http://localhost:3000\nAccess-Control-Request-Method: POST\nAccess-Control-Request-Headers: Content-Type, Authorization\n\n# 2. Server grants permission\nHTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: http://localhost:3000\nAccess-Control-Allow-Methods: POST, GET, OPTIONS\nAccess-Control-Allow-Headers: Content-Type, Authorization\nVary: Origin\n\n# 3. Browser sends actual request\nPOST /api/users HTTP/1.1\nOrigin: http://localhost:3000\nContent-Type: application/json\n\n{&quot;name&quot;: &quot;New User&quot;}\n\n# 4. Server responds (must include CORS headers again)\nHTTP/1.1 201 Created\nAccess-Control-Allow-Origin: http://localhost:3000\n\n{&quot;id&quot;: 123, &quot;name&quot;: &quot;New User&quot;}`, `51539049104586880000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"http\"><pre class=\"language-http\"><code class=\"language-http\"># 1. Browser sends preflight (OPTIONS)\n<span class=\"token request-line\"><span class=\"token method property\">OPTIONS</span> <span class=\"token request-target url\">/api/users</span> <span class=\"token http-version property\">HTTP/1.1</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Origin</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">http://localhost:3000</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Access-Control-Request-Method</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">POST</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Access-Control-Request-Headers</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">Content-Type, Authorization</span></span>\n\n# 2. Server grants permission\n<span class=\"token response-status\"><span class=\"token http-version property\">HTTP/1.1</span> <span class=\"token status-code number\">204</span> <span class=\"token reason-phrase string\">No Content</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Access-Control-Allow-Origin</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">http://localhost:3000</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Access-Control-Allow-Methods</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">POST, GET, OPTIONS</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Access-Control-Allow-Headers</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">Content-Type, Authorization</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Vary</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">Origin</span></span>\n\n# 3. Browser sends actual request\n<span class=\"token request-line\"><span class=\"token method property\">POST</span> <span class=\"token request-target url\">/api/users</span> <span class=\"token http-version property\">HTTP/1.1</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Origin</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">http://localhost:3000</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Content-Type</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">application/json</span></span>\n<span class=\"token application-json\">\n<span class=\"token punctuation\">{</span><span class=\"token property\">\"name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"New User\"</span><span class=\"token punctuation\">}</span>\n\n# <span class=\"token number\">4</span>. Server responds (must include CORS headers again)\n</span><span class=\"token response-status\"><span class=\"token http-version property\">HTTP/1.1</span> <span class=\"token status-code number\">201</span> <span class=\"token reason-phrase string\">Created</span></span>\n<span class=\"token header\"><span class=\"token header-name keyword\">Access-Control-Allow-Origin</span><span class=\"token punctuation\">:</span> <span class=\"token header-value\">http://localhost:3000</span></span>\n\n{\"id\": 123, \"name\": \"New User\"}</code></pre></div>\n<p>This two-step process explains why JSON API calls appear slower in browsers than in Postman — browsers complete the preflight first, while tools like Postman bypass CORS entirely.</p>\n<hr>\n<h2 id=\"common-cors-errors-and-what-they-mean\" style=\"position:relative;\"><a href=\"#common-cors-errors-and-what-they-mean\" aria-label=\"common cors errors and what they mean permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Common CORS Errors and What They Mean</h2>\n<h3 id=\"no-access-control-allow-origin-header-is-present\" style=\"position:relative;\"><a href=\"#no-access-control-allow-origin-header-is-present\" aria-label=\"no access control allow origin header is present permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>“No ‘Access-Control-Allow-Origin’ header is present”</h3>\n<p>The most common CORS error. The server processed the request but didn’t include the header that authorizes your origin to read the response.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"72266088641204430000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`fetch('https://api.coolservice.com/data')\n  .then(res => res.json())\n  .then(data => console.log(data))\n\n// Error:\n// Access to fetch at 'https://api.coolservice.com/data' from origin\n// 'http://localhost:3000' has been blocked by CORS policy:\n// No 'Access-Control-Allow-Origin' header is present on the requested resource.`, `72266088641204430000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.coolservice.com/data'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">res</span> <span class=\"token operator\">=></span> res<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">data</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">// Error:</span>\n<span class=\"token comment\">// Access to fetch at 'https://api.coolservice.com/data' from origin</span>\n<span class=\"token comment\">// 'http://localhost:3000' has been blocked by CORS policy:</span>\n<span class=\"token comment\">// No 'Access-Control-Allow-Origin' header is present on the requested resource.</span></code></pre></div>\n<p>For servers you control:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"10035409184683375000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`app.use((req, res, next) => {\n  res.header('Access-Control-Allow-Origin', 'http://localhost:3000');\n  next();\n});`, `10035409184683375000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'http://localhost:3000'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>For third-party APIs, you’ll need a <strong>proxy server</strong> or the API must natively support CORS.</p>\n<h3 id=\"method-not-allowed-by-access-control-allow-methods\" style=\"position:relative;\"><a href=\"#method-not-allowed-by-access-control-allow-methods\" aria-label=\"method not allowed by access control allow methods permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>“Method not allowed by Access-Control-Allow-Methods”</h3>\n<p>The server accepts cross-origin requests, but not the HTTP method you’re using.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"19855088852074897000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`fetch('https://api.example.com/users/123', {\n  method: 'DELETE',\n  headers: { 'Authorization': 'Bearer token' }\n})\n\n// Error:\n// Method DELETE is not allowed by Access-Control-Allow-Methods in preflight response.`, `19855088852074897000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/users/123'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">'DELETE'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">'Authorization'</span><span class=\"token operator\">:</span> <span class=\"token string\">'Bearer token'</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">// Error:</span>\n<span class=\"token comment\">// Method DELETE is not allowed by Access-Control-Allow-Methods in preflight response.</span></code></pre></div>\n<p>Common causes: missing <code class=\"language-text\">OPTIONS</code> endpoint handler, or incomplete method list in the CORS configuration.</p>\n<h3 id=\"credentialed-requests-not-supported-wildcard--credentials-conflict\" style=\"position:relative;\"><a href=\"#credentialed-requests-not-supported-wildcard--credentials-conflict\" aria-label=\"credentialed requests not supported wildcard  credentials conflict permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>“Credentialed requests not supported” (wildcard + credentials conflict)</h3>\n<p>This error appears when you send cookies or auth headers cross-origin but the server uses a wildcard origin.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"73178906002868850000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`fetch('https://api.example.com/profile', {\n  credentials: 'include'\n})\n\n// Error:\n// The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*'\n// when the request's credentials mode is 'include'.`, `73178906002868850000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/profile'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">credentials</span><span class=\"token operator\">:</span> <span class=\"token string\">'include'</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token comment\">// Error:</span>\n<span class=\"token comment\">// The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*'</span>\n<span class=\"token comment\">// when the request's credentials mode is 'include'.</span></code></pre></div>\n<p>When credentials are involved, the server must:</p>\n<ul>\n<li>Specify an <strong>exact origin</strong> (not <code class=\"language-text\">*</code>)</li>\n<li>Include <code class=\"language-text\">Access-Control-Allow-Credentials: true</code></li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"41534219859958310000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`res.header('Access-Control-Allow-Origin', 'http://localhost:3000');\nres.header('Access-Control-Allow-Credentials', 'true');`, `41534219859958310000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'http://localhost:3000'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'true'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>This is a hard browser rule: <code class=\"language-text\">Access-Control-Allow-Origin: *</code> combined with <code class=\"language-text\">Access-Control-Allow-Credentials: true</code> will always be rejected. Any server misconfigured this way exposes sensitive user data.</p>\n<h3 id=\"cors-errors-in-fetch-vs-axios\" style=\"position:relative;\"><a href=\"#cors-errors-in-fetch-vs-axios\" aria-label=\"cors errors in fetch vs axios permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS Errors in Fetch vs. Axios</h3>\n<p>Fetch and Axios handle CORS failures differently:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"63995867353769570000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Fetch — generic, unhelpful error message\nfetch('https://api.example.com/data')\n  .catch(error => {\n    console.log(error.message); // &quot;Failed to fetch&quot; (no detail)\n  });\n\n// Axios — structured error information\naxios.get('https://api.example.com/data')\n  .catch(error => {\n    if (error.response) {\n      console.log('Server error:', error.response.status);\n    } else if (error.request) {\n      console.log('No response received:', error.message);\n    }\n  });`, `63995867353769570000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Fetch — generic, unhelpful error message</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/data'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">catch</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">.</span>message<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// \"Failed to fetch\" (no detail)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Axios — structured error information</span>\naxios<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/data'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">catch</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">.</span>response<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Server error:'</span><span class=\"token punctuation\">,</span> error<span class=\"token punctuation\">.</span>response<span class=\"token punctuation\">.</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'No response received:'</span><span class=\"token punctuation\">,</span> error<span class=\"token punctuation\">.</span>message<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Also note: Axios automatically sets <code class=\"language-text\">Content-Type: application/json</code> on requests with a body, which triggers a preflight. Any interceptors that add custom headers will also trigger preflight. Check your Axios configuration if requests fail even on seemingly “simple” endpoints.</p>\n<hr>\n<h2 id=\"how-to-fix-cors-errors-backend-configuration\" style=\"position:relative;\"><a href=\"#how-to-fix-cors-errors-backend-configuration\" aria-label=\"how to fix cors errors backend configuration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to Fix CORS Errors: Backend Configuration</h2>\n<p>CORS is fundamentally a <strong>server-side configuration problem</strong>. Frontend workarounds can help during development, but production requires proper backend setup.</p>\n<h3 id=\"setting-cors-headers-manually\" style=\"position:relative;\"><a href=\"#setting-cors-headers-manually\" aria-label=\"setting cors headers manually permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting CORS Headers Manually</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"59504834647483600000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Exact origin (required for credentialed requests)\nres.header('Access-Control-Allow-Origin', 'https://app.example.com');\n\n// Allowed methods\nres.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n\n// Allowed request headers\nres.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key');\n\n// Allow cookies and auth headers\nres.header('Access-Control-Allow-Credentials', 'true');\n\n// Cache preflight for 24 hours (reduces OPTIONS round-trips)\nres.header('Access-Control-Max-Age', '86400');\n\n// IMPORTANT: Tell caches that responses vary by origin\nres.header('Vary', 'Origin');`, `59504834647483600000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Exact origin (required for credentialed requests)</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'https://app.example.com'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Allowed methods</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Methods'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'GET, POST, PUT, DELETE, OPTIONS'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Allowed request headers</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Headers'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Content-Type, Authorization, X-API-Key'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Allow cookies and auth headers</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'true'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Cache preflight for 24 hours (reduces OPTIONS round-trips)</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Max-Age'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'86400'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// IMPORTANT: Tell caches that responses vary by origin</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Vary'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Origin'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<blockquote>\n<p><strong>Why <code class=\"language-text\">Vary: Origin</code> matters:</strong> When your server dynamically reflects the requesting origin (rather than using <code class=\"language-text\">*</code>), you must include <code class=\"language-text\">Vary: Origin</code> in your responses. Without it, CDNs and shared caches may serve a response with one origin’s <code class=\"language-text\">Access-Control-Allow-Origin</code> to a different origin — which either breaks CORS or creates a security hole.</p>\n</blockquote>\n<h3 id=\"nodejs--express-with-the-cors-package\" style=\"position:relative;\"><a href=\"#nodejs--express-with-the-cors-package\" aria-label=\"nodejs  express with the cors package permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Node.js / Express with the <code class=\"language-text\">cors</code> Package</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"43053487954392030000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const cors = require('cors');\n\nconst corsOptions = {\n  origin: function (origin, callback) {\n    const allowedOrigins = [\n      'https://app.example.com',\n      'https://admin.example.com',\n      'http://localhost:3000'\n    ];\n\n    // Allow server-to-server requests (no origin header)\n    if (!origin) return callback(null, true);\n\n    if (allowedOrigins.includes(origin)) {\n      callback(null, true);\n    } else {\n      callback(new Error('Not allowed by CORS'));\n    }\n  },\n  credentials: true,\n  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n  allowedHeaders: ['Content-Type', 'Authorization'],\n  maxAge: 86400\n};\n\napp.use(cors(corsOptions));\n\n// Explicitly handle preflight for all routes\napp.options('*', cors(corsOptions));`, `43053487954392030000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> cors <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'cors'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> corsOptions <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function-variable function\">origin</span><span class=\"token operator\">:</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">origin<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> allowedOrigins <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token string\">'https://app.example.com'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'https://admin.example.com'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'http://localhost:3000'</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Allow server-to-server requests (no origin header)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>origin<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>allowedOrigins<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span>origin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Not allowed by CORS'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">credentials</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">methods</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'GET'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'POST'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'PUT'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'DELETE'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'OPTIONS'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">allowedHeaders</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'Content-Type'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Authorization'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">maxAge</span><span class=\"token operator\">:</span> <span class=\"token number\">86400</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token function\">cors</span><span class=\"token punctuation\">(</span>corsOptions<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Explicitly handle preflight for all routes</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">options</span><span class=\"token punctuation\">(</span><span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span> <span class=\"token function\">cors</span><span class=\"token punctuation\">(</span>corsOptions<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"flask-python\" style=\"position:relative;\"><a href=\"#flask-python\" aria-label=\"flask python permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Flask (Python)</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"60769181603124855000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`from flask import Flask, jsonify, request\nfrom flask_cors import CORS\n\napp = Flask(__name__)\nCORS(app, origins=[&quot;https://app.example.com&quot;], supports_credentials=True)\n\n@app.after_request\ndef after_request(response):\n    origin = request.headers.get('Origin')\n    if origin in ['https://app.example.com', 'http://localhost:3000']:\n        response.headers['Access-Control-Allow-Origin'] = origin\n        response.headers['Access-Control-Allow-Credentials'] = 'true'\n        response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'\n        response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'\n        response.headers['Vary'] = 'Origin'\n    return response`, `60769181603124855000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> flask <span class=\"token keyword\">import</span> Flask<span class=\"token punctuation\">,</span> jsonify<span class=\"token punctuation\">,</span> request\n<span class=\"token keyword\">from</span> flask_cors <span class=\"token keyword\">import</span> CORS\n\napp <span class=\"token operator\">=</span> Flask<span class=\"token punctuation\">(</span>__name__<span class=\"token punctuation\">)</span>\nCORS<span class=\"token punctuation\">(</span>app<span class=\"token punctuation\">,</span> origins<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"https://app.example.com\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> supports_credentials<span class=\"token operator\">=</span><span class=\"token boolean\">True</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token decorator annotation punctuation\">@app<span class=\"token punctuation\">.</span>after_request</span>\n<span class=\"token keyword\">def</span> <span class=\"token function\">after_request</span><span class=\"token punctuation\">(</span>response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    origin <span class=\"token operator\">=</span> request<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">'Origin'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> origin <span class=\"token keyword\">in</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'https://app.example.com'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'http://localhost:3000'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>\n        response<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> origin\n        response<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'true'</span>\n        response<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'Access-Control-Allow-Methods'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'GET, POST, PUT, DELETE, OPTIONS'</span>\n        response<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'Access-Control-Allow-Headers'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'Content-Type, Authorization'</span>\n        response<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'Vary'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'Origin'</span>\n    <span class=\"token keyword\">return</span> response</code></pre></div>\n<h3 id=\"django-python\" style=\"position:relative;\"><a href=\"#django-python\" aria-label=\"django python permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Django (Python)</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"41593308740418224000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# settings.py\nINSTALLED_APPS = [\n    'corsheaders',\n    # ...\n]\n\nMIDDLEWARE = [\n    'corsheaders.middleware.CorsMiddleware',  # Must be before CommonMiddleware\n    'django.middleware.common.CommonMiddleware',\n    # ...\n]\n\nCORS_ALLOWED_ORIGINS = [\n    &quot;http://localhost:3000&quot;,\n    &quot;https://app.example.com&quot;,\n]\n\nCORS_ALLOW_CREDENTIALS = True\n\nCORS_ALLOW_HEADERS = [\n    'accept',\n    'authorization',\n    'content-type',\n    'x-csrftoken',\n]`, `41593308740418224000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token comment\"># settings.py</span>\nINSTALLED_APPS <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">'corsheaders'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\"># ...</span>\n<span class=\"token punctuation\">]</span>\n\nMIDDLEWARE <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">'corsheaders.middleware.CorsMiddleware'</span><span class=\"token punctuation\">,</span>  <span class=\"token comment\"># Must be before CommonMiddleware</span>\n    <span class=\"token string\">'django.middleware.common.CommonMiddleware'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\"># ...</span>\n<span class=\"token punctuation\">]</span>\n\nCORS_ALLOWED_ORIGINS <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">\"http://localhost:3000\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"https://app.example.com\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span>\n\nCORS_ALLOW_CREDENTIALS <span class=\"token operator\">=</span> <span class=\"token boolean\">True</span>\n\nCORS_ALLOW_HEADERS <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">'accept'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'authorization'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'content-type'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'x-csrftoken'</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span></code></pre></div>\n<h3 id=\"spring-boot-java\" style=\"position:relative;\"><a href=\"#spring-boot-java\" aria-label=\"spring boot java permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Spring Boot (Java)</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"29664322459496240000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`@Configuration\n@EnableWebMvc\npublic class WebConfig implements WebMvcConfigurer {\n\n    @Override\n    public void addCorsMappings(CorsRegistry registry) {\n        registry.addMapping(&quot;/api/**&quot;)\n            .allowedOrigins(&quot;https://app.example.com&quot;, &quot;http://localhost:3000&quot;)\n            .allowedMethods(&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;DELETE&quot;, &quot;OPTIONS&quot;)\n            .allowedHeaders(&quot;Content-Type&quot;, &quot;Authorization&quot;)\n            .allowCredentials(true)\n            .maxAge(3600);\n    }\n}`, `29664322459496240000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Configuration</span>\n<span class=\"token annotation punctuation\">@EnableWebMvc</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">WebConfig</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">WebMvcConfigurer</span> <span class=\"token punctuation\">{</span>\n\n    <span class=\"token annotation punctuation\">@Override</span>\n    <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">addCorsMappings</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">CorsRegistry</span> registry<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        registry<span class=\"token punctuation\">.</span><span class=\"token function\">addMapping</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/api/**\"</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">.</span><span class=\"token function\">allowedOrigins</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"https://app.example.com\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"http://localhost:3000\"</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">.</span><span class=\"token function\">allowedMethods</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"GET\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"POST\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"PUT\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"DELETE\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"OPTIONS\"</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">.</span><span class=\"token function\">allowedHeaders</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Content-Type\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Authorization\"</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">.</span><span class=\"token function\">allowCredentials</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">.</span><span class=\"token function\">maxAge</span><span class=\"token punctuation\">(</span><span class=\"token number\">3600</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<hr>\n<h2 id=\"frontend-considerations\" style=\"position:relative;\"><a href=\"#frontend-considerations\" aria-label=\"frontend considerations permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Frontend Considerations</h2>\n<h3 id=\"what-doesnt-work\" style=\"position:relative;\"><a href=\"#what-doesnt-work\" aria-label=\"what doesnt work permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What Doesn’t Work</h3>\n<p><strong>Adding CORS headers on the frontend has no effect.</strong> CORS headers are server responses — the browser ignores them if you try to set them in a <code class=\"language-text\">fetch()</code> call:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"94110033725470440000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// This does nothing — CORS headers belong on the server\nfetch('https://api.example.com/data', {\n  headers: {\n    'Access-Control-Allow-Origin': '*',\n  }\n})`, `94110033725470440000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// This does nothing — CORS headers belong on the server</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/data'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string-property property\">'Access-Control-Allow-Origin'</span><span class=\"token operator\">:</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p><strong><code class=\"language-text\">no-cors</code> mode makes responses unreadable.</strong> You can send the request, but JavaScript cannot access the response body:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"49092373564472000000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`fetch('https://api.example.com/data', { mode: 'no-cors' })\n  .then(response => response.json()) // Throws — response is &quot;opaque&quot;`, `49092373564472000000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/data'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">mode</span><span class=\"token operator\">:</span> <span class=\"token string\">'no-cors'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">response</span> <span class=\"token operator\">=></span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// Throws — response is \"opaque\"</span></code></pre></div>\n<h3 id=\"what-actually-works-dev-proxy\" style=\"position:relative;\"><a href=\"#what-actually-works-dev-proxy\" aria-label=\"what actually works dev proxy permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What Actually Works: Dev Proxy</h3>\n<p>Route your frontend through a local proxy during development so requests appear same-origin:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"52749908450043750000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// vite.config.js\nexport default {\n  server: {\n    proxy: {\n      '/api': {\n        target: 'https://api.example.com',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, '')\n      }\n    }\n  }\n}`, `52749908450043750000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// vite.config.js</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">server</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">proxy</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">'/api'</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">target</span><span class=\"token operator\">:</span> <span class=\"token string\">'https://api.example.com'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">changeOrigin</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function-variable function\">rewrite</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">path</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> path<span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^\\/api</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"16275379948869274000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// next.config.js\nmodule.exports = {\n  async rewrites() {\n    return [\n      {\n        source: '/api/:path*',\n        destination: 'https://api.example.com/:path*'\n      }\n    ];\n  }\n};`, `16275379948869274000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// next.config.js</span>\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">async</span> <span class=\"token function\">rewrites</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">source</span><span class=\"token operator\">:</span> <span class=\"token string\">'/api/:path*'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">destination</span><span class=\"token operator\">:</span> <span class=\"token string\">'https://api.example.com/:path*'</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<hr>\n<h2 id=\"cors-and-authentication\" style=\"position:relative;\"><a href=\"#cors-and-authentication\" aria-label=\"cors and authentication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS and Authentication</h2>\n<p>Authentication adds extra complexity to CORS because credentials require stricter rules.</p>\n<h3 id=\"why-credentials-change-everything\" style=\"position:relative;\"><a href=\"#why-credentials-change-everything\" aria-label=\"why credentials change everything permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Credentials Change Everything</h3>\n<p>When you send cookies or HTTP auth headers cross-origin (using <code class=\"language-text\">credentials: 'include'</code>), the browser enforces two additional rules:</p>\n<ol>\n<li><code class=\"language-text\">Access-Control-Allow-Origin</code> must be an <strong>exact origin</strong>, never <code class=\"language-text\">*</code></li>\n<li>The server must return <code class=\"language-text\">Access-Control-Allow-Credentials: true</code></li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"61291196303419700000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Frontend\nfetch('https://api.example.com/profile', {\n  credentials: 'include',\n  headers: { 'Content-Type': 'application/json' }\n});`, `61291196303419700000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Frontend</span>\n<span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://api.example.com/profile'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">credentials</span><span class=\"token operator\">:</span> <span class=\"token string\">'include'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">'Content-Type'</span><span class=\"token operator\">:</span> <span class=\"token string\">'application/json'</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"36343859521709420000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Backend\nres.header('Access-Control-Allow-Origin', 'https://app.example.com'); // Exact origin\nres.header('Access-Control-Allow-Credentials', 'true');`, `36343859521709420000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Backend</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'https://app.example.com'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Exact origin</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'true'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"cookie-configuration-for-cross-origin-auth\" style=\"position:relative;\"><a href=\"#cookie-configuration-for-cross-origin-auth\" aria-label=\"cookie configuration for cross origin auth permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cookie Configuration for Cross-Origin Auth</h3>\n<p>For cross-origin cookies to work at all, they must be set with <code class=\"language-text\">SameSite=None</code> and <code class=\"language-text\">Secure</code>:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"18594097274069930000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`res.cookie('session', token, {\n  httpOnly: true,\n  secure: true,        // HTTPS required\n  sameSite: 'none'     // Required for cross-origin\n});`, `18594097274069930000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">res<span class=\"token punctuation\">.</span><span class=\"token function\">cookie</span><span class=\"token punctuation\">(</span><span class=\"token string\">'session'</span><span class=\"token punctuation\">,</span> token<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">httpOnly</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">secure</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>        <span class=\"token comment\">// HTTPS required</span>\n  <span class=\"token literal-property property\">sameSite</span><span class=\"token operator\">:</span> <span class=\"token string\">'none'</span>     <span class=\"token comment\">// Required for cross-origin</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<blockquote>\n<p><strong>Browser note:</strong> Safari is notably stricter about cross-origin cookies than Chrome or Firefox. If your auth flows work in Chrome but fail in Safari, this is usually the cause. Third-party cookie restrictions in Safari’s ITP (Intelligent Tracking Prevention) can block credentialed CORS requests even with correct headers.</p>\n</blockquote>\n<p>Getting this cookie configuration right by hand is error-prone, which is one reason many teams reach for a dedicated session-management layer. <a href=\"https://supertokens.com\" target=\"_blank\" rel=\"nofollow\">SuperTokens</a> sets these <code class=\"language-text\">SameSite=None; Secure; HttpOnly</code> cookie flags and the matching CORS headers for you, so cross-origin authenticated requests work consistently across browsers. If you’re weighing cookies against other storage options, see <a href=\"https://supertokens.com/blog/cookies-vs-localstorage-for-sessions-everything-you-need-to-know\" target=\"_blank\" rel=\"nofollow\">Cookies vs. <code class=\"language-text\">localStorage</code> for sessions</a> and <a href=\"https://supertokens.com/blog/session-based-authentication\" target=\"_blank\" rel=\"nofollow\">how session-based authentication works</a>.</p>\n<hr>\n<h2 id=\"security-best-practices\" style=\"position:relative;\"><a href=\"#security-best-practices\" aria-label=\"security best practices permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Security Best Practices</h2>\n<h3 id=\"1-never-use-wildcard-origins-in-production\" style=\"position:relative;\"><a href=\"#1-never-use-wildcard-origins-in-production\" aria-label=\"1 never use wildcard origins in production permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. Never Use Wildcard Origins in Production</h3>\n<p><code class=\"language-text\">Access-Control-Allow-Origin: *</code> disables all the security benefits of CORS for that endpoint. Any website can read responses from your API.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"18477050860880650000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Environment-aware origin whitelist\nconst allowedOrigins = {\n  production: ['https://app.yourcompany.com', 'https://www.yourcompany.com'],\n  staging:    ['https://staging.yourcompany.com'],\n  development: ['http://localhost:3000', 'http://localhost:3001']\n};\n\napp.use(cors({\n  origin: (origin, callback) => {\n    const env = process.env.NODE_ENV || 'development';\n    const allowed = allowedOrigins[env];\n\n    if (!origin || allowed.includes(origin)) {\n      callback(null, true);\n    } else {\n      console.error(\\`CORS rejected: \\${origin}\\`);\n      callback(new Error('CORS policy violation'));\n    }\n  }\n}));`, `18477050860880650000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Environment-aware origin whitelist</span>\n<span class=\"token keyword\">const</span> allowedOrigins <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">production</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'https://app.yourcompany.com'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'https://www.yourcompany.com'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">staging</span><span class=\"token operator\">:</span>    <span class=\"token punctuation\">[</span><span class=\"token string\">'https://staging.yourcompany.com'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">development</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'http://localhost:3000'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'http://localhost:3001'</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token function\">cors</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token function-variable function\">origin</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">origin<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> env <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">NODE_ENV</span> <span class=\"token operator\">||</span> <span class=\"token string\">'development'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> allowed <span class=\"token operator\">=</span> allowedOrigins<span class=\"token punctuation\">[</span>env<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>origin <span class=\"token operator\">||</span> allowed<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span>origin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">CORS rejected: </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>origin<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'CORS policy violation'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><strong>Exception:</strong> Public, read-only APIs with no user data or authentication can safely use <code class=\"language-text\">*</code>.</p>\n<h3 id=\"2-limit-methods-and-headers-to-what-you-need\" style=\"position:relative;\"><a href=\"#2-limit-methods-and-headers-to-what-you-need\" aria-label=\"2 limit methods and headers to what you need permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Limit Methods and Headers to What You Need</h3>\n<p>Only allow the HTTP methods and headers your application actually uses. Every additional method or header is additional attack surface.</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"4052567972969045500\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// Too permissive — avoid in production\nres.header('Access-Control-Allow-Methods', '*');\n\n// Better — list only what's needed\nres.header('Access-Control-Allow-Methods', 'GET, POST');\nres.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');`, `4052567972969045500`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// Too permissive — avoid in production</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Methods'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Better — list only what's needed</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Methods'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'GET, POST'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nres<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Headers'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Content-Type, Authorization'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>If <code class=\"language-text\">DELETE</code> is allowed but not needed, an attacker could potentially trigger deletion via a CSRF attack.</p>\n<h3 id=\"3-always-set-vary-origin\" style=\"position:relative;\"><a href=\"#3-always-set-vary-origin\" aria-label=\"3 always set vary origin permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. Always Set <code class=\"language-text\">Vary: Origin</code></h3>\n<p>When dynamically reflecting the requesting origin (the most common production pattern), include <code class=\"language-text\">Vary: Origin</code> to prevent cache poisoning:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"67557234031965544000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// When reflecting origin dynamically, always add Vary\nif (allowedOrigins.includes(req.headers.origin)) {\n  res.header('Access-Control-Allow-Origin', req.headers.origin);\n  res.header('Vary', 'Origin');\n}`, `67557234031965544000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// When reflecting origin dynamically, always add Vary</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>allowedOrigins<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">,</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Vary'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Origin'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Without this, a CDN may cache a response with <code class=\"language-text\">Access-Control-Allow-Origin: https://app.example.com</code> and serve it to a request from a different origin.</p>\n<h3 id=\"4-log-and-monitor-cors-rejections\" style=\"position:relative;\"><a href=\"#4-log-and-monitor-cors-rejections\" aria-label=\"4 log and monitor cors rejections permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. Log and Monitor CORS Rejections</h3>\n<p>Blocked requests may indicate misconfiguration or active probing:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"10284241893914014000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`app.use((req, res, next) => {\n  if (req.method === 'OPTIONS' || req.headers.origin) {\n    const allowed = isAllowedOrigin(req.headers.origin);\n    if (!allowed) {\n      console.warn('[CORS Rejected]', {\n        origin: req.headers.origin,\n        method: req.method,\n        path: req.path,\n        timestamp: new Date().toISOString()\n      });\n    }\n  }\n  next();\n});`, `10284241893914014000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>method <span class=\"token operator\">===</span> <span class=\"token string\">'OPTIONS'</span> <span class=\"token operator\">||</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> allowed <span class=\"token operator\">=</span> <span class=\"token function\">isAllowedOrigin</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>allowed<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      console<span class=\"token punctuation\">.</span><span class=\"token function\">warn</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[CORS Rejected]'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">origin</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>method<span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">path</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">timestamp</span><span class=\"token operator\">:</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toISOString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"5-consider-sec-fetch--headers-as-a-defense-layer\" style=\"position:relative;\"><a href=\"#5-consider-sec-fetch--headers-as-a-defense-layer\" aria-label=\"5 consider sec fetch  headers as a defense layer permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>5. Consider <code class=\"language-text\">Sec-Fetch-*</code> Headers as a Defense Layer</h3>\n<p>Modern browsers send <code class=\"language-text\">Sec-Fetch-Site</code>, <code class=\"language-text\">Sec-Fetch-Mode</code>, and <code class=\"language-text\">Sec-Fetch-Dest</code> headers with every request. These headers are set by the browser and cannot be forged by JavaScript, making them a useful complement to CORS for server-side request validation:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"68466140045357110000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`app.use((req, res, next) => {\n  const fetchSite = req.headers['sec-fetch-site'];\n  // 'same-origin', 'same-site', 'cross-site', or 'none' (direct navigation)\n  if (fetchSite === 'cross-site' && req.method !== 'GET') {\n    // Consider additional validation for cross-site non-GET requests\n  }\n  next();\n});`, `68466140045357110000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> fetchSite <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'sec-fetch-site'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// 'same-origin', 'same-site', 'cross-site', or 'none' (direct navigation)</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fetchSite <span class=\"token operator\">===</span> <span class=\"token string\">'cross-site'</span> <span class=\"token operator\">&amp;&amp;</span> req<span class=\"token punctuation\">.</span>method <span class=\"token operator\">!==</span> <span class=\"token string\">'GET'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Consider additional validation for cross-site non-GET requests</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>This isn’t a CORS replacement, but a complementary layer alongside CSRF tokens and Content Security Policy.</p>\n<hr>\n<h2 id=\"debugging-cors-issues\" style=\"position:relative;\"><a href=\"#debugging-cors-issues\" aria-label=\"debugging cors issues permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Debugging CORS Issues</h2>\n<h3 id=\"browser-developer-tools\" style=\"position:relative;\"><a href=\"#browser-developer-tools\" aria-label=\"browser developer tools permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Browser Developer Tools</h3>\n<p>Open the <strong>Network tab</strong> and look for:</p>\n<ul>\n<li><code class=\"language-text\">OPTIONS</code> requests before your main request (preflight)</li>\n<li>The response headers on the OPTIONS request — these show what the server actually allows</li>\n<li>The presence or absence of <code class=\"language-text\">Access-Control-Allow-Origin</code> on the actual response</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"># Healthy flow\nOPTIONS /api/users   204   2ms    (preflight approved)\nPOST    /api/users   201   45ms   (request succeeded)\n\n# CORS failure\nPOST    /api/users   ---   0ms    (blocked before preflight even sent)</code></pre></div>\n<blockquote>\n<p><strong>Note:</strong> CORS errors in the browser console don’t show the specific cause for security reasons. The Network tab is the only reliable place to see the actual headers exchanged.</p>\n</blockquote>\n<h3 id=\"testing-with-curl\" style=\"position:relative;\"><a href=\"#testing-with-curl\" aria-label=\"testing with curl permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Testing with <code class=\"language-text\">curl</code></h3>\n<p>Simulate a preflight request without a browser:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"61481585001969360000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`curl -X OPTIONS https://api.production.com/users \\\n  -H &quot;Origin: https://app.production.com&quot; \\\n  -H &quot;Access-Control-Request-Method: POST&quot; \\\n  -H &quot;Access-Control-Request-Headers: Content-Type, Authorization&quot; \\\n  -v 2>&1 | grep -i &quot;access-control&quot;`, `61481585001969360000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">curl</span> -X OPTIONS https://api.production.com/users <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Origin: https://app.production.com\"</span> <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Access-Control-Request-Method: POST\"</span> <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Access-Control-Request-Headers: Content-Type, Authorization\"</span> <span class=\"token punctuation\">\\</span>\n  -v <span class=\"token operator\"><span class=\"token file-descriptor important\">2</span>></span><span class=\"token file-descriptor important\">&amp;1</span> <span class=\"token operator\">|</span> <span class=\"token function\">grep</span> -i <span class=\"token string\">\"access-control\"</span></code></pre></div>\n<p>Expected output:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">access-control-allow-origin: https://app.production.com\naccess-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS\naccess-control-allow-headers: content-type, authorization</code></pre></div>\n<h3 id=\"infrastructure-checklist\" style=\"position:relative;\"><a href=\"#infrastructure-checklist\" aria-label=\"infrastructure checklist permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Infrastructure Checklist</h3>\n<p>Production CORS failures are often caused by infrastructure, not application code:</p>\n<ul>\n<li><strong>CDNs</strong> may strip or cache CORS headers incorrectly (Cloudflare, CloudFront, etc.)</li>\n<li><strong>Load balancers</strong> may block <code class=\"language-text\">OPTIONS</code> requests</li>\n<li><strong>Reverse proxies</strong> (nginx, Apache) may need explicit pass-through configuration</li>\n<li><strong>Missing environment variables</strong> may cause the server to fall back to a wrong origin list</li>\n</ul>\n<p>Always test with <code class=\"language-text\">curl</code> directly against your origin server and then again through your CDN to isolate where headers are being dropped.</p>\n<h3 id=\"enhanced-debug-logging\" style=\"position:relative;\"><a href=\"#enhanced-debug-logging\" aria-label=\"enhanced debug logging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Enhanced Debug Logging</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"49295667376119770000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`app.use((req, res, next) => {\n  if (req.method === 'OPTIONS' || req.headers.origin) {\n    console.log('[CORS Debug]', {\n      timestamp: new Date().toISOString(),\n      method: req.method,\n      path: req.path,\n      origin: req.headers.origin,\n      requestedMethod: req.headers['access-control-request-method'],\n      requestedHeaders: req.headers['access-control-request-headers'],\n    });\n  }\n  next();\n});`, `49295667376119770000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>method <span class=\"token operator\">===</span> <span class=\"token string\">'OPTIONS'</span> <span class=\"token operator\">||</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[CORS Debug]'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">timestamp</span><span class=\"token operator\">:</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toISOString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>method<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">path</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">origin</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">requestedMethod</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'access-control-request-method'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">requestedHeaders</span><span class=\"token operator\">:</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'access-control-request-headers'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<hr>\n<h2 id=\"emergency-fix-and-production-verification\" style=\"position:relative;\"><a href=\"#emergency-fix-and-production-verification\" aria-label=\"emergency fix and production verification permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Emergency Fix and Production Verification</h2>\n<h3 id=\"emergency-fix-temporary-only\" style=\"position:relative;\"><a href=\"#emergency-fix-temporary-only\" aria-label=\"emergency fix temporary only permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Emergency Fix (Temporary Only)</h3>\n<p>If production is broken and you need to buy time:</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"43314475459209500000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`app.use((req, res, next) => {\n  console.warn('EMERGENCY CORS MODE — REMOVE BEFORE NEXT DEPLOY');\n\n  res.header('Access-Control-Allow-Origin', req.headers.origin || '*');\n  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n  res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers'] || 'Content-Type, Authorization');\n  res.header('Access-Control-Allow-Credentials', 'true');\n  res.header('Vary', 'Origin');\n\n  if (req.method === 'OPTIONS') return res.sendStatus(204);\n  next();\n});`, `43314475459209500000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">warn</span><span class=\"token punctuation\">(</span><span class=\"token string\">'EMERGENCY CORS MODE — REMOVE BEFORE NEXT DEPLOY'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">,</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin <span class=\"token operator\">||</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Methods'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'GET, POST, PUT, DELETE, OPTIONS'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Headers'</span><span class=\"token punctuation\">,</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'access-control-request-headers'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> <span class=\"token string\">'Content-Type, Authorization'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'true'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">header</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Vary'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Origin'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">.</span>method <span class=\"token operator\">===</span> <span class=\"token string\">'OPTIONS'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">sendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">204</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Tighten this immediately once the immediate incident is resolved.</p>\n<h3 id=\"production-deployment-verification-script\" style=\"position:relative;\"><a href=\"#production-deployment-verification-script\" aria-label=\"production deployment verification script permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Production Deployment Verification Script</h3>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"11350048234213196000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`#!/bin/bash\nAPI_DOMAIN=&quot;https://api.example.com&quot;\nFRONTEND_DOMAIN=&quot;https://app.example.com&quot;\n\necho &quot;=== Testing preflight ===&quot;\ncurl -s -X OPTIONS &quot;\\$API_DOMAIN/api/test&quot; \\\n  -H &quot;Origin: \\$FRONTEND_DOMAIN&quot; \\\n  -H &quot;Access-Control-Request-Method: POST&quot; \\\n  -H &quot;Access-Control-Request-Headers: Content-Type, Authorization&quot; \\\n  -I | grep -i &quot;access-control\\|vary&quot;\n\necho &quot;&quot;\necho &quot;=== Testing actual request ===&quot;\ncurl -s -X GET &quot;\\$API_DOMAIN/api/health&quot; \\\n  -H &quot;Origin: \\$FRONTEND_DOMAIN&quot; \\\n  -I | grep -i &quot;access-control\\|vary&quot;`, `11350048234213196000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token shebang important\">#!/bin/bash</span>\n<span class=\"token assign-left variable\">API_DOMAIN</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://api.example.com\"</span>\n<span class=\"token assign-left variable\">FRONTEND_DOMAIN</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://app.example.com\"</span>\n\n<span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"=== Testing preflight ===\"</span>\n<span class=\"token function\">curl</span> -s -X OPTIONS <span class=\"token string\">\"<span class=\"token variable\">$API_DOMAIN</span>/api/test\"</span> <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Origin: <span class=\"token variable\">$FRONTEND_DOMAIN</span>\"</span> <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Access-Control-Request-Method: POST\"</span> <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Access-Control-Request-Headers: Content-Type, Authorization\"</span> <span class=\"token punctuation\">\\</span>\n  -I <span class=\"token operator\">|</span> <span class=\"token function\">grep</span> -i <span class=\"token string\">\"access-control\\|vary\"</span>\n\n<span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"\"</span>\n<span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"=== Testing actual request ===\"</span>\n<span class=\"token function\">curl</span> -s -X GET <span class=\"token string\">\"<span class=\"token variable\">$API_DOMAIN</span>/api/health\"</span> <span class=\"token punctuation\">\\</span>\n  -H <span class=\"token string\">\"Origin: <span class=\"token variable\">$FRONTEND_DOMAIN</span>\"</span> <span class=\"token punctuation\">\\</span>\n  -I <span class=\"token operator\">|</span> <span class=\"token function\">grep</span> -i <span class=\"token string\">\"access-control\\|vary\"</span></code></pre></div>\n<hr>\n<h2 id=\"cors-quick-reference\" style=\"position:relative;\"><a href=\"#cors-quick-reference\" aria-label=\"cors quick reference permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS Quick Reference</h2>\n<h3 id=\"all-cors-response-headers\" style=\"position:relative;\"><a href=\"#all-cors-response-headers\" aria-label=\"all cors response headers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>All CORS Response Headers</h3>\n<table>\n<thead>\n<tr>\n<th>Header</th>\n<th>Purpose</th>\n<th>Required?</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"language-text\">Access-Control-Allow-Origin</code></td>\n<td>Which origins can access the response</td>\n<td>Always</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">Access-Control-Allow-Methods</code></td>\n<td>Allowed HTTP methods (preflight response)</td>\n<td>For preflighted requests</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">Access-Control-Allow-Headers</code></td>\n<td>Allowed request headers (preflight response)</td>\n<td>For custom headers</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">Access-Control-Allow-Credentials</code></td>\n<td>Whether cookies/auth are allowed</td>\n<td>For credentialed requests</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">Access-Control-Max-Age</code></td>\n<td>How long to cache the preflight result (seconds)</td>\n<td>Optional but recommended</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">Access-Control-Expose-Headers</code></td>\n<td>Which response headers JS can read</td>\n<td>When using non-standard headers</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">Vary: Origin</code></td>\n<td>Signals that responses differ by origin</td>\n<td>When reflecting dynamic origins</td>\n</tr>\n</tbody>\n</table>\n<h3 id=\"developer-checklist\" style=\"position:relative;\"><a href=\"#developer-checklist\" aria-label=\"developer checklist permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Developer Checklist</h3>\n<p><strong>Before shipping to production:</strong></p>\n<ul class=\"contains-task-list\">\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> No wildcard <code class=\"language-text\">*</code> origins on authenticated or credentialed endpoints</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> <code class=\"language-text\">Vary: Origin</code> header set on all responses that reflect a dynamic origin</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> <code class=\"language-text\">OPTIONS</code> preflight handled correctly for all relevant routes</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> <code class=\"language-text\">Access-Control-Allow-Credentials: true</code> only where cookies/auth are needed</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> Allowed methods and headers scoped to only what your app uses</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> CORS rejection events are logged</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> Configuration tested against your CDN or reverse proxy, not just the app server</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> Cookie <code class=\"language-text\">SameSite=None; Secure</code> set if using cross-origin session cookies</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" disabled> Cross-browser tested (especially Safari for credentialed flows)</li>\n</ul>\n<hr>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>CORS is not a bug to bypass — it’s a browser security mechanism working exactly as designed. Every CORS error is telling you that a server hasn’t explicitly authorized the cross-origin access being requested.</p>\n<p>The key principles:</p>\n<ul>\n<li><strong>CORS is server-configured.</strong> No frontend workaround substitutes for proper server headers.</li>\n<li><strong>Credentials change the rules.</strong> Wildcard origins are forbidden when cookies or auth headers are involved.</li>\n<li><strong>Reflect origins dynamically, then <code class=\"language-text\">Vary</code>.</strong> Don’t echo <code class=\"language-text\">req.headers.origin</code> back without also setting <code class=\"language-text\">Vary: Origin</code>.</li>\n<li><strong>Infrastructure matters.</strong> CDNs, load balancers, and proxies can silently strip or cache CORS headers.</li>\n<li><strong>Preflight must succeed.</strong> <code class=\"language-text\">OPTIONS</code> requests must be handled for any non-simple cross-origin request.</li>\n</ul>\n<p>With correct configuration, CORS becomes an ally rather than an obstacle — enforcing the right trust boundaries while letting your legitimate cross-origin traffic flow freely.</p>\n<h2 id=\"related-reading\" style=\"position:relative;\"><a href=\"#related-reading\" aria-label=\"related reading permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Related reading</h2>\n<ul>\n<li><a href=\"https://supertokens.com/blog/http-error-codes-401-vs-403\" target=\"_blank\" rel=\"nofollow\">HTTP Error Codes: 401 vs. 403</a></li>\n<li><a href=\"https://supertokens.com/blog/what-is-502-bad-gateway-error\" target=\"_blank\" rel=\"nofollow\">What Is a 502 Bad Gateway Error and How to Fix It</a></li>\n<li><a href=\"https://supertokens.com/blog/cookies-vs-localstorage-for-sessions-everything-you-need-to-know\" target=\"_blank\" rel=\"nofollow\">Cookies vs. <code class=\"language-text\">localStorage</code> for Sessions</a></li>\n</ul>","frontmatter":{"date":"July 20, 2025","title":"Fixing CORS Errors: What They Are and How to Resolve Them (2026)","cover":"cors_errors.png","author":"Maurice Saldivar","description":"Learn what causes CORS errors, how they impact your web app, and how to fix them securely with proper headers and backend configurations."},"fields":{"slug":"/cors-errors/"}},"site":{"siteMetadata":{"title":"SuperTokens Blog"}}},"pageContext":{"id":"e824c4bd-208d-51b4-8695-0b6468a50765","fields__slug":"/cors-errors/","__params":{"fields__slug":"cors-errors"}}},
    "staticQueryHashes": []}