blog-hero-background-image
Cyber Security

Backend for Frontend Security Solution

backdrop
Table of Contents

Join thousands of professionals and get the latest insight on Compliance & Cybersecurity.


You've built a slick Single-Page Application (SPA) that makes multiple API calls to different microservices. But now you're struggling with token management, security vulnerabilities, and a growing sense that your frontend is becoming an unmanageable "mess" of API calls. If you're wondering, "Is there a better way to handle all these APIs without compromising security?" – the Backend for Frontend (BFF) pattern might be your solution.

The Modern Frontend Dilemma - Too Many APIs, Not Enough Security

"At work I always had to manage lots of API on the frontend, a BFF could have helped manage that mess," laments one developer on Reddit. This sentiment resonates with many frontend engineers drowning in API spaghetti.

The challenges are multifaceted:

  • Your single UI views require 2-3 separate API calls to different services
  • Managing authentication tokens securely in the browser feels like a losing battle
  • Mobile clients receive the same bloated payloads as desktop clients, despite their "little capacity for API data transactions"
  • You're uncertain whether implementing a BFF adds unnecessary complexity or solves a genuine problem

The Backend for Frontend pattern offers a compelling solution—not just for API organization, but critically, for robust API security. Let's explore how this architectural approach can transform both your development workflow and your application's security posture.

What is the Backend for Frontend (BFF) Pattern?

The BFF pattern, popularized by Sam Newman, emerged from a common architectural challenge: a general-purpose backend struggling to serve multiple frontends with different needs.

The Problem BFF Solves

Imagine a scenario described in Microsoft's architecture guide: Your application began with a desktop web interface. Later, you added a mobile app. Both interfaces need to access the same core functionality, but with very different requirements:

  • The mobile app needs smaller payloads to conserve bandwidth
  • The desktop web app can handle richer, more detailed responses
  • Each interface requires different API endpoints optimized for its unique user experience

This creates competing demands on your backend team, leading to development bottlenecks and compromised user experiences across platforms.

The BFF Solution

The BFF pattern addresses these challenges by creating a dedicated backend service tailored to each specific frontend application. Rather than one generic API serving all clients, each frontend gets its own specialized backend that:

  • Acts as a façade, translating frontend requests into calls to downstream microservices
  • Aggregates data from multiple sources into cohesive, frontend-friendly responses
  • Handles client-specific concerns like authentication, data transformation, and request routing

But beyond these well-known benefits, the BFF pattern has evolved to address one of the most critical challenges in modern web security: protecting API credentials and tokens in browser-based applications.

Why BFF is Your Go-To for Modern API Security

The fundamental security vulnerability of SPAs lies in their status as what OAuth 2.0 calls "public clients." According to Auth0, client applications fall into two categories:

  • Confidential Clients: Applications that can securely store secrets (typically server-side applications)
  • Public Clients: Applications that cannot securely store secrets (browser-based SPAs and mobile apps)

This distinction is crucial because SPAs run entirely in the browser, where any stored tokens (access tokens, refresh tokens) are vulnerable to theft through Cross-Site Scripting (XSS) attacks. As Auth0 notes, storing tokens in local storage or session storage is inherently risky.

The BFF Security Architecture: No Tokens in the Browser

This is where the BFF pattern truly shines as a security solution. The core principle, as Duende Software emphasizes, is simple: "It's crucial to avoid storing high-value tokens in JavaScript-accessible locations."

Here's how the secure flow works:

  1. Authentication Request: The SPA redirects the user to a login endpoint on the BFF (e.g., /login)
  2. OIDC Handshake: The BFF (acting as a confidential client) performs the secure Authorization Code Flow with PKCE with the identity provider
  3. Token Storage: The BFF receives and stores the id_token, access_token, and refresh_token securely in a server-side session
  4. Session Cookie: The BFF creates a session cookie (marked as HttpOnly, Secure, and SameSite=Strict) and sends it to the browser
  5. Authenticated API Calls: For subsequent API calls, the SPA sends this cookie with each request. The BFF validates the session, retrieves the corresponding access token server-side, and uses it to call downstream APIs

The critical security advantage: tokens never reach the browser. They remain safely server-side, inaccessible to any malicious JavaScript.

Additional Security Benefits

Beyond token protection, the BFF pattern offers several other security advantages:

  • Reduced Attack Surface: The BFF shields your internal architecture from direct exposure, hiding microservice details from potential attackers
  • Centralized Security Policies: Following Curity's API Security Best Practices, the BFF can enforce rate limiting, input validation, and consistent logging
  • Fine-Grained Access Control: The BFF can inspect token claims to enforce object-level authorization before proxying requests, preventing Broken Object Level Authorization (BOLA) vulnerabilities
  • Token Exchange: For complex microservice architectures, the BFF can use token exchange flows when calling different internal APIs, ensuring appropriate scoping of access

Implementing a Secure BFF: A Practical Guide

Many developers express frustration that while they "get the logic and purpose" of BFF, applying it "in a real world scenario has been hard." Let's bridge that gap with a concrete implementation example using ASP.NET Core and the Duende.BFF framework.

Step 1: Setup & Configuration

First, install the Duende.BFF NuGet package:

dotnet add package Duende.BFF

Then configure authentication in your Program.cs:

services.AddBff()
    .AddServerSideSessions();

services.AddAuthentication(options => {
    options.DefaultScheme = "cookie"; // Cookie-based session as default
    options.DefaultChallengeScheme = "oidc"; // Redirect to OIDC provider for login
    options.DefaultSignOutScheme = "oidc";
})
.AddCookie("cookie", options => {
    options.Cookie.Name = "__Host-bff-token"; // Secure cookie naming
    options.Cookie.SameSite = SameSiteMode.Strict; // Prevent CSRF
})
.AddOpenIdConnect("oidc", options => {
    options.Authority = "https://your-identity-provider.com";
    options.ClientId = "spa";
    options.ClientSecret = "secret"; // Safe on the server
    options.ResponseType = "code"; // Authorization Code Flow
    options.ResponseMode = "query";

    options.GetClaimsFromUserInfoEndpoint = true;
    options.SaveTokens = true; // Store tokens in the server-side session

    options.Scope.Clear();
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("api1");
    options.Scope.Add("offline_access");
});

Step 2: Create Proxy Endpoints for Downstream APIs

Next, create controllers to proxy your API calls:

[Route("api/[controller]")]
[Authorize]
public class ProductsController : ControllerBase
{
    private readonly HttpClient _httpClient;
    
    public ProductsController(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("ProductsApi");
    }
    
    [HttpGet]
    public async Task<IActionResult> GetProducts()
    {
        // The BFF will automatically add the access token to this request
        var response = await _httpClient.GetAsync("api/products");
        
        if (response.IsSuccessStatusCode)
        {
            var content = await response.Content.ReadAsStringAsync();
            return Ok(content);
        }
        
        return StatusCode((int)response.StatusCode);
    }
}

Step 3: Frontend Integration

Your SPA would now interact with the BFF instead of calling APIs directly:

// Login
const login = () => {
    window.location.href = '/bff/login';
};

// Get user info (no tokens exposed)
const getUserInfo = async () => {
    const response = await fetch('/bff/user');
    const userData = await response.json();
    return userData;
};

// Call an API via the BFF
const getProducts = async () => {
    const response = await fetch('/api/products');
    const products = await response.json();
    return products;
};

// Logout
const logout = () => {
    window.location.href = '/bff/logout';
};

The Strategic Decision: When (and When Not) to Use a BFF

A common concern expressed by developers is whether BFF is "still necessary, or not?" and whether it adds needless complexity. The answer depends on your specific circumstances.

When to Use BFF

  • Multiple Frontend Types: You have distinct interfaces (mobile, web, desktop) with different requirements
  • Complex API Aggregation: Your UI views require multiple API calls that could be streamlined
  • Security-Critical Applications: You're building an SPA or mobile app that handles sensitive data and requires robust token security
  • Microservice Complexity: You have many microservices that need coordinated access patterns

When BFF Might Be Overkill

  • Simple Applications: You have a straightforward application with minimal API needs
  • Homogeneous Interfaces: Your interfaces have very similar data requirements
  • Limited Resources: The operational overhead of an additional service outweighs the benefits for your project

As one Reddit user wisely noted, "you probably see relatively little benefit because you only have 2 microservices." The value of BFF increases with system complexity.

Conclusion: From Architectural Pattern to Security Imperative

The Backend for Frontend pattern has evolved from a convenience for managing multiple frontends to an essential security component for modern web applications. By keeping sensitive tokens server-side and providing a tailored API experience, BFF addresses the inherent security vulnerabilities of browser-based applications.

For teams building SPAs and dealing with the challenges of "managing lots of API on the frontend," the BFF pattern offers a structured way to tame the complexity while significantly enhancing security. As you consider whether to implement BFF, remember that its greatest value may not be in API organization, but in protecting your application's crown jewels: the authentication and authorization tokens that safeguard your users' data and your business logic.

Whether you're managing two microservices or twenty, the security benefits of BFF make it a pattern worth serious consideration in your architectural toolkit.

toaster icon

Thank you for reaching out to us!

We will get back to you soon.