Implementing BFF Pattern in ASP.NET Core for SPAs

This multi-part blog series will show you how to implement secure authentication for Single-Page Applications using the Backend-for-Frontend (BFF) pattern with ASP.NET Core.

We’ll explore why handling OpenID Connect directly in SPAs creates security risks, then build a complete BFF implementation that eliminates browser token storage and follows OAuth 2.0 best practices. In short, it will help you to build secure applications with less complexity in the frontend!

As this is a big topic, I’m planning to release a new post in this series approximately once a week, with each part building on the previous one. 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 (coming soon)
  • Part 3 – Securing the Cookie Session (coming soon)
  • 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)

The Problem with Direct OIDC in SPAs

In my work, I regularly encounter development teams implementing OpenID Connect authentication directly in their Single-Page Applications. The typical flow looks like this: 

  1. The browser-based frontend authenticates directly with the OIDC provider.
  2. The OIDC JavaScript library stores the received tokens in the browser.
  3. Uses them to call backend APIs.

This approach seems straightforward, but it introduces significant security risks and complexity.

so what exactly are these risks?

The Problem With Tokens In the Browser

Let’s explore the key problems with this approach:

  • Protecting the tokens:
    Storing tokens (access token, ID token, or refresh token) in the browser puts them at risk of theft through cross-site scripting (XSS) attacks or malicious third-party scripts. For example, a compromised browser extension could easily access tokens stored in localStorage, giving attackers full access to your APIs.
  • Increased attack surface:
    Adding OpenID Connect support directly to your SPA means handling tokens, redirects, and callbacks in JavaScript. This prevents you from utilizing secure browser features, such as HTTP-only cookies and same-site protections, while significantly increasing your application’s attack surface.
  • Added Complexity:
    OpenID Connect and token handling introduce a lot of complexity to your frontend. Even with libraries, you need to understand token flows, configure edge cases like renewal and error handling, and manage logout scenarios. This increases security-critical code that requires careful writing, testing, and review.
  • Using a trusted library:
    Searching npm for “oidc” returns thousands of JavaScript libraries, but only a small number are certified by the OpenID Foundation. Using an unmaintained or insecure library can introduce subtle bugs or serious security vulnerabilities.

These problems are well-documented in the security community. Rather than diving deep into every detail, I recommend these excellent talks that explain the issues clearly:

Curious about OpenID-Connect?
Head over to my OpenID Connect for Developers article for an accessible, in-depth introduction to OpenID Connect for developers.

The Impact of Stolen Tokens

The impact extends far beyond browser access. Once an attacker exfiltrates these tokens, they gain portable, offline access to your APIs. The stolen access token can be used from any client application or system. The attacker doesn’t need continued access to the victim’s browser.

This means they can:

  • Call your APIs from their own systems.
  • Use automated tools to exploit the token.
  • Continue accessing resources until the token expires (potentially hours or days later).
  • Potentially use the token across multiple applications if it has a broad scope.

Refresh tokens make this even worse. If a refresh token is also stolen, the attacker can:

  • Generate new access tokens indefinitely.
  • Maintain persistent access even after the original access token expires.
  • Continue the attack for weeks or months until the refresh token is revoked or expired.

This transforms a temporary browser compromise into a persistent, distributed security threat that’s much harder to detect and contain.

The Solution: the Backend-for-Frontend (BFF) Pattern

So what’s the better approach? Instead of handling authentication directly in the SPA, we move all token management to the backend and use a simple session cookie for communication between the frontend and backend.

This creates a much cleaner and more secure architecture:

Key principles of the BFF approach:

  • No tokens in the browser:
    Eliminating tokens from the frontend removes a major security risk and reduces complexity. No more worrying about XSS attacks stealing your tokens or implementing secure storage in JavaScript.
  • Use the browser’s built-in security features:
    Without frontend token management, you can fully utilize HTTP-only cookies, same-site protection, and secure flags. All of these are battle-tested browser security mechanisms that work without additional configuration.
  • Keep the frontend simple and focused:
    Your SPA can concentrate on what it does best: user interface and experience. Authentication complexity stays in the backend where it belongs.
  • Centralize trust and session handling in the backend:
    The backend handles the OpenID Connect flow, manages sessions, and securely stores tokens. This makes logging, monitoring, and auditing much easier.
  • Reducing complexity:
    Moving the authentication into the backend reduces the number of moving parts in the frontend and cuts down the attack surface. This also means fewer security concerns for frontend developers to worry about.

This approach is called the Backend-for-Frontend (BFF) pattern. It’s not a new concept, but it’s particularly effective for securing modern SPAs.

What you’ll learn: By the end of this series, you’ll have a solid starter implementation that eliminates browser token storage, leverages HTTP-only cookies, and centralizes authentication in ASP.NET Core, giving you a strong foundation for your own BFF journey.

Official Recommendation

The BFF pattern isn’t just a theoretical improvement; it’s recognized as the current best practice by the OAuth working group. The IETF draft specification for OAuth 2.0 for Browser-Based Apps explicitly states:

“This architecture is strongly recommended for business applications, sensitive applications, and applications that handle personal data.”

This official endorsement reinforces the message that moving authentication to the backend is more than a matter of convenience; it is also about meeting established security standards suited to modern web applications in today’s world.

Why I Created This Series

I wrote this series for two main reasons, both rooted in real-world experience.

First, I wanted to deepen my own understanding of BFF implementations. Reading about authentication patterns is one thing, but actually building, testing, and troubleshooting them reveals nuances you can’t get from just theory alone.

Second, I needed a comprehensive, working example for the security workshops I run with development teams. When I’m explaining secure SPA architectures, nothing beats having actual ASP.NET Core code that teams can examine, run, and adapt to their own projects.

You can learn more about these security workshops here.

These workshops focus on practical security implementation: the kind of hands-on knowledge that helps teams avoid common pitfalls and build more secure applications from the start.

Ready for the Deep Dive?

I’m taking the same approach in this deep dive on BFF, taking the best of theory and practice to help you secure your web applications (and hopefully with less of the headaches, too!).

In Part 2, we’ll explore exactly how the BFF pattern works and why it solves these security challenges.  (coming soon)

About the author

Hey! I’m Tore 👋 I’m an independent consultant, trainer, and coach for developers in the world of authentication, authorization, and beyond. I help teams to build secure, scalable, and visible applications with a specialism in Duende IdentityServer, OIDC, and OAuth. Interested in training, consulting, or an extra pair of hands for your web security skills or project? You can find out more here

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