Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
  • Privacy Policy
Ajax

Ajax: Fix a Cross-Origin Request That Silently Drops Cookies Because credentials Was Never Set to include

- 04.10.26 - ErcanOPAK

🔄 The Cross-Origin Request That Forgot to Bring Its Cookies

A fetch call defaults to not sending cookies on a cross-origin request at all unless you explicitly opt in on the client, and the server on the other end has to agree with a matching header pair naming the exact calling origin rather than a wildcard. Miss either half of that handshake and the request often still succeeds with a normal success status, just without the session cookie attached, so the API quietly treats a logged-in caller as logged out instead of returning anything that looks like an authentication error.

🔎 The Problem

// Frontend served from app.example.com calling api.example.com -
// a cross-origin request by definition, even though both are "yours."
fetch('https://api.example.com/account', {
    method: 'GET'
    // no credentials option set - defaults to same-origin, which
    // means NO cookies are sent to a different origin at all.
})
.then(res => res.json())
.then(data => console.log(data)); // { loggedIn: false } every time,
// even for a user who is very much logged in on api.example.com.

// Fixed: explicitly opt in on the client...
fetch('https://api.example.com/account', {
    method: 'GET',
    credentials: 'include'
});

// ...and the server has to agree, with the exact origin, never a
// wildcard, plus an explicit allow-credentials header set to true.

✅ Fix: Opt In on Both the Client and the Server

  • Add the credentials option set to include on every fetch call that needs to carry the session cookie across origins – the browser’s same-origin default silently drops cookies on a cross-origin request rather than raising any error you would notice in the client code itself.
  • On the server, respond with the exact calling origin in the allow-origin header, never a wildcard, together with an explicit allow-credentials header set to true – a wildcard origin is specifically disallowed by browsers the moment credentials are involved, and the request fails differently if you try it anyway.
  • Treat a cross-origin response that succeeds but shows a logged-out state as a credentials configuration problem first, before assuming the session itself expired – check the actual request headers for a cookie header before debugging anything server-side.

⚠️ Why This Is Easy to Miss

  • The request still returns a normal success status with a valid-looking response body, so nothing about the failure looks like a networking or cross-origin error – it looks exactly like the user really is logged out, which sends debugging in the wrong direction first.
  • A same-origin development setup, where a local proxy makes the frontend and API appear as one origin, never exhibits this at all, so the bug only appears after deploying to an environment where the frontend and API are genuinely on different domains or subdomains.

A cross-origin request that forgets its cookies does not fail loudly – it just quietly agrees with the server to pretend nobody is logged in.

— Frontend Engineer

Related posts:

Ajax: Use Query Strings to Pass Data in GET Requests

Ajax: Why Axios is Better Than Fetch for HTTP Requests

Ajax: Use Server-Sent Events (SSE) for Real-Time Updates Without WebSockets

Post Views: 3

Post navigation

CSS: Fix a Cascade Layer That Silently Overrides Styles You Thought Had Higher Specificity
Photoshop: Fix the History Panel Running Out of Undo States Mid-Edit Because of One Setting Buried in Preferences

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

October 2026
M T W T F S S
 1234
567891011
12131415161718
19202122232425
262728293031  
« Sep    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (973)
  • How to make theater mode the default for Youtube (948)
  • How to add default value for Entity Framework migrations for DateTime and Bool (938)
  • Get the First and Last Word from a String or Sentence in SQL (847)
  • How to select distinct rows in a datatable in C# (836)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (624)
  • Add Constraint to SQL Table to ensure email contains @ (590)
  • Average of all values in a column that are not zero in SQL (553)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (526)
  • Find numbers with more than two decimal places in SQL (468)

Recent Posts

  • CSS: Fix a prefers-color-scheme Media Query That Gets Silently Overridden by a Browser Extension’s Forced Dark Mode
  • Git: Fix a Merge Commit That Silently Drops a File Because Both Branches Deleted It Differently
  • HTML5: Fix a Native Lazy-Loading Image That Never Loads Because It Sits Inside a Hidden Tab Until the User Clicks It
  • The AI Prompt That Traces a Null Reference Exception Back to the Exact Line That First Produced the Null
  • The AI Prompt That Turns a Gym Membership Contract’s Fine Print Into a Plain-English List of Cancellation Steps
  • Photoshop: Fix a Color Profile Mismatch That Makes Printed Output Look Nothing Like What You Saw On Screen
  • WordPress: Fix Search Results That Return Pages From a Theme You Deactivated Months Ago
  • Visual Studio: Fix a Test Project That Builds Fine Alone but Fails to Discover Any Tests After a NuGet Restore
  • ASP.NET Core: Fix a File Upload That Times Out on Slow Connections Only Because Kestrel’s Minimum Data Rate Feature Kicked In
  • JavaScript: Fix an Array Destructuring Default Value That Silently Never Applies Because null Was Passed Instead of Undefined

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (973)
  • How to make theater mode the default for Youtube (948)
  • How to add default value for Entity Framework migrations for DateTime and Bool (938)
  • Get the First and Last Word from a String or Sentence in SQL (847)
  • How to select distinct rows in a datatable in C# (836)

Recent Posts

  • CSS: Fix a prefers-color-scheme Media Query That Gets Silently Overridden by a Browser Extension’s Forced Dark Mode
  • Git: Fix a Merge Commit That Silently Drops a File Because Both Branches Deleted It Differently
  • HTML5: Fix a Native Lazy-Loading Image That Never Loads Because It Sits Inside a Hidden Tab Until the User Clicks It
  • The AI Prompt That Traces a Null Reference Exception Back to the Exact Line That First Produced the Null
  • The AI Prompt That Turns a Gym Membership Contract’s Fine Print Into a Plain-English List of Cancellation Steps

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com