BFF in ASP.NET Core #3 - The BFF Pattern Explained

BFF in ASP.NET Core #3 – The BFF Pattern Explained

The BFF pattern eliminates many SPA security risks, but it introduces a new critical component: the session cookie. This cookie becomes the key to your user’s authentication. If it’s not properly secured, you’ve simply moved the vulnerability from JavaScript tokens to HTTP cookies.

This post shows you how to properly secure the session cookie using HTTPS, HttpOnly flags, SameSite protection, and other essential browser security features.

This is a big topic, so I’ve split it into multiple parts. You can jump to the section you need, but for background and context, it’s best to start here:

Part 1 – Introduction
Part 2 – Introducing the Backend-for-Frontend (BFF) pattern
Part 3 – Securing the Cookie Session
Part 4 – Implementing a BFF in ASP.NET Core (coming soon)
Part 5 – Automatic Token Renewal (coming soon)
Part 6 – Securing the BFF using CORS (coming soon)
Part 7 – Introducing the Duende BFF Library (coming soon)

Securing the Communication with the BFF

The session cookie is the cornerstone of BFF security. After a user logs in, this cookie becomes their digital identity, included with every request from the browser to the BFF.

Here’s where the BFF pattern really shines: when you handle OIDC directly in the browser, you can’t leverage most of the browser’s built-in security mechanisms.

With the BFF approach, we can finally use the full arsenal of browser security features. Session cookies unlock HttpOnly protection, SameSite controls, Secure flags, and host prefixes. When properly configured, these create multiple layers of protection that can withstand sophisticated attacks and pass rigorous penetration tests.

But how do we protect this cookie and the communication channel?

Using HTTPS

HTTPS isn’t optional in modern web applications. It’s the foundation that makes everything else possible. Without HTTPS, your BFF implementation will encounter immediate problems: OpenID Connect flows may fail, browsers will block security-critical cookies, and essential security features will not activate.

Securing the Authentication Cookie - HttpOnly

The HttpOnly flag is your first line of defense against JavaScript-based attacks. This simple yet powerful attribute instructs the browser to block JavaScript access to the authentication cookie, preventing malicious scripts from stealing the session cookie.

Set-Cookie: .AspNetCore.cookie=CfDJ8IgPXE...; HttpOnly

This protection is critical because it directly addresses cross-site scripting (XSS), one of the most common attack vectors. Even if an attacker manages to inject malicious JavaScript into your application, they cannot access or steal the session cookie. It’s one simple change, with a big impact!

Important: HttpOnly doesn’t block legitimate functionality. Cookies marked with HttpOnly are still automatically included in same-origin requests made by JavaScript (such as fetch or XMLHttpRequest calls), ensuring your application functions normally while remaining protected.

Adding this flag helps reduce the risk of stolen session cookies through injected scripts.

Securing the Session Cookie – Secure

The Secure attribute adds another essential layer of protection by ensuring your session cookie only travels over encrypted HTTPS connections. This simple flag prevents the cookie from ever being sent over via plain HTTP, even by mistake.

Set-Cookie: .AspNetCore.cookie=CfDJ8IgPXE...; HttpOnly; Secure

This protection is vital for preventing man-in-the-middle attacks. Without the Secure flag, if any part of your application accidentally makes an HTTP request, the session cookie could be transmitted in plain text, potentially exposing it to network eavesdroppers.

Browsers prevent setting Secure cookies on HTTP sites, with one exception: localhost during local development. Since production BFF implementations run on public HTTPS endpoints, this development exception doesn’t affect your security posture.

Securing the Session Cookie – SameSite

Before SameSite protection existed, browsers had a dangerous default behavior where they would send cookies with every request to your domain, regardless of where that request originated. This meant malicious websites could trigger requests to your application and your users’ cookies would be automatically included.

This creates a serious vulnerability. Imagine a user is logged into their banking application in one tab, then clicks a malicious link in an email. That malicious site can send hidden requests to the bank’s website, and because the browser automatically includes the user’s session cookie, the bank sees these requests as legitimate. This is the foundation of Cross-Site Request Forgery (CSRF) attacks.

The SameSite attribute solves this problem by giving you control over when cookies are included in cross-site requests. Modern browsers increasingly require this attribute, and it should be part of every cookie configuration.

The attribute accepts three values:

  • Strict
    The cookie is only sent with requests originating from the same site. This provides maximum protection but can impact user experience. Users clicking links from external sites (emails, social media) will appear logged out and need to sign in again.
  • Lax (default)
    The cookie is sent for “safe” top-level navigation (like clicking a link) but blocked for potentially dangerous requests (like form submissions from other sites). This prevents most CSRF attacks while maintaining good usability.
  • None
    The cookie is sent with all cross-site requests. This requires the Secure flag and should only be used if your application specifically needs cross-site cookie access. Most BFF implementations should avoid this setting. This is how cookies behaved before the SameSite attribute was introduced.

For BFF implementations, use SameSite=Strict if your application can handle users appearing logged out when arriving from external links. Otherwise, SameSite=Lax provides excellent protection with better usability.

Here’s what a secure session cookie might look like:

Set-Cookie: .AspNetCore.cookie=CfDJ8IgPXE...; HttpOnly; Secure; SameSite=Strict

 

Locking the Session Cookie to the Origin

By default, session cookies are included in all same-site requests. But what exactly qualifies as “same-site”? The answer reveals a significant security blind spot that many developers overlook.

Understanding the Same-Site Boundary

In browser security, “same-site” is much broader than most people expect. All of these domains are considered part of the same site:

  • example.com
  • login.example.com
  • api.example.com
  • test.login.example.com

This broad scope applies to all top-level domains, including country-code domains. For example, these are all considered the same site:

  • example.co.uk
  • login.example.co.uk
  • api.example.co.uk
  • test.login.example.co.uk

The Public Suffix List helps browsers decide if two domains belong to the same site or not.

The Subdomain Takeover Risk

This broad cookie scope creates a vulnerability: if an attacker compromises any subdomain (such as test.api.example.com), they can potentially access cookies intended for your main application. This is known as a subdomain takeover attack

The Solution: __Host- Prefixed Cookie Names

Fortunately, modern browsers provide a powerful solution: prefixed cookie names. The __Host- prefix enables the strongest origin-binding protection available, transforming your cookie from site-scoped to origin-scoped security.

Here’s how it works: when a cookie name starts with __Host-, browsers automatically activate special security restrictions. This isn’t just a naming convention; instead, it’s a security feature built into the browser itself.

Here is an example:

Set-Cookie: __Host-SessionCookie=XXXXX; HttpOnly; Secure; Path=/; SameSite=Strict

Requirements for __Host- cookies:

  • No Domain attribute – This locks the cookie to the exact hostname that set it
  • Path must be / – Ensures the cookie applies to the entire origin
  • Must include Secure flag – Enforces HTTPS-only transmission

With the __Host- prefix, a cookie set by https://example.com becomes completely isolated. It will never be sent to:

  • login.example.com
  • api.example.com
  • test.login.example.com

This simple naming convention eliminates the risk of subdomain takeover entirely. Your session cookie is now bound to the exact origin that created it, not just the broader site boundary.

Additional Security Enhancements

Once the core cookie protections are in place, you can further strengthen your BFF security with these measures:

  • CORS
    Cross-Origin Resource Sharing (CORS) controls which origins can communicate with your BFF. We’ll explore this in detail in Part 6, as it deserves dedicated coverage for BFF implementations.
  • Content Security Policy (CSP)
    CSP controls which resources the browser can load, providing strong protection against XSS attacks. Learn more about CSP.
  • Essential Security Headers
    Modern browsers support several security headers that significantly improve your application’s defense:
    • Strict-Transport-Security
      This header enforces HTTPS connections and prevents protocol downgrade attacks by instructing browsers to only communicate with your server over secure connections. Once set, browsers will automatically redirect HTTP requests to HTTPS and reject connections with invalid certificates.
    • X-Content-Type-Options: nosniff
      Prevents browsers from MIME-sniffing responses away from the declared content type. Read more about the X-Content-Type-Options header.
    • X-Frame-Options
      Protects against clickjacking by controlling whether your site can be embedded in frames.
    • Referrer-Policy
      Controls the amount of referrer information included with requests.  Read more about the Referrer-Policy header.

While configuring these headers is beyond the scope of this blog post series, they are an important part of a strong BFF security setup. In ASP.NET Core, most can be added using middleware in the request pipeline.

Summary

Securing the session cookie is critical to the BFF pattern’s success. In this post, we’ve covered the essential layers of protection:

Communication Security

HTTPS – The foundation that enables all other security features

Cookie Protection

  • HttpOnly – Blocks JavaScript access, preventing XSS token theft
  • Secure – Ensures cookies only travel over encrypted HTTPS connections
  • SameSite – Controls cross-site request behavior (use Strict or Lax)
  • Path=/ – Applies the cookie to your entire application
  • __Host- prefix – Locks the cookie to your exact origin, preventing subdomain attacks

Want to Dive Deeper?

These cookie protections are part of a broader security strategy. My Web Security Fundamentals workshop covers the complete spectrum of web vulnerabilities and defenses, from XSS and CSRF to secure authentication patterns and coding practices.

What's Next

Now that we understand how to secure the session cookie properly, it’s time to put this knowledge into practice. Part 4 walks through implementing a BFF in ASP.NET Core, showing you exactly how to configure all the security features we’ve covered. (Coming soon)

More blog posts by the author

Share This Story

About The Author

Hi, I’m Tore! I have been fascinated by computers since I unpacked my first Commodore VIC-20. I am a Microsoft MVP in .NET and  I provide freelance application development, developer training and coaching services, focusing on ASP.NET Core, IdentityServer, OpenID Connect, Architecture, and Web Security. Let’s connect on LinkedIn and Twitter!

Related Posts

Do You Want Tore To Be Your Mentor?

Services 🚀

I offer training and coaching for professional developers and consulting services for startups and enterprises. Find out more on my business website. 

Tore’s Newsletter

Be the First to Know! Get notified about my latest blog posts, upcoming presentations, webinars, and more — subscribe today!

Cartoon of Tore Nestenius

About me

Hi! I’m Tore Nestenius. I’m a trainer and senior software developer focusing on Architecture, Security & Identity, .NET, C#, Backend, the Cloud, and more.

Do You Want Tore To Be Your Mentor?

Services 🚀

I offer training and coaching for professional developers and consulting services for startups and enterprises. Find out more on my business website. 

Blog Categories