Pisum.BFF 1.11.0
Pisum.Bff
Core library for the Pisum Backend for Frontend (BFF) security pattern implementation.
Overview
Pisum.Bff is a comprehensive security framework that implements the Backend for Frontend (BFF) pattern for ASP.NET Core applications. It moves authentication to the server-side, implements secure session management, and provides CSRF protection for modern SPAs (Single Page Applications).
Key Features
- ✅ Server-Side Authentication - No tokens in browser, httpOnly secure cookies
- ✅ Secure Session Management - Server-side session storage with distributed cache support
- ✅ CSRF Protection - Anti-forgery tokens for all state-changing requests
- ✅ OpenID Connect - Works with any OIDC-compliant identity provider
- ✅ Flexible Endpoints - Login, logout, user info, and backchannel logout
- ✅ Session Revocation - Logout from all sessions or specific sessions
- ✅ Background Cleanup - Automatic cleanup of expired sessions
Installation
From Pisum NuGet Server
dotnet add package Pisum.BFF --source https://nuget.pisum.synology.me/v3/index.json
Or via Package Manager:
Install-Package Pisum.BFF -Source https://nuget.pisum.synology.me/v3/index.json
Configure NuGet Source
Add the Pisum NuGet server to your NuGet configuration:
dotnet nuget add source https://nuget.pisum.synology.me/v3/index.json --name Pisum
Then install normally:
dotnet add package Pisum.BFF
Quick Start
1. Configure Services
// Program.cs or Startup.cs
using Pisum.Bff.Endpoints;
var builder = WebApplication.CreateBuilder(args);
// Add BFF services
builder.Services.AddBffCore(options =>
{
options.AnonymousSessionResponse = AnonymousSessionResponse.Response401;
options.AntiforgeryHeaderName = "X-CSRF-TOKEN";
options.AntiforgeryHeaderValue = "1";
options.EnableAntiForgery = true;
options.ManagementBasePath = "/bff";
})
.AddServerSideSessions();
// Add authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("cookie", options =>
{
options.Cookie.Name = "__Host-bff";
options.Cookie.SameSite = SameSiteMode.Strict;
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://your-identity-provider";
options.ClientId = "your-client-id";
options.ClientSecret = "your-client-secret";
options.ResponseType = "code";
options.Scope.Add("openid");
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
2. Configure Middleware Pipeline
// IMPORTANT: Middleware order matters!
app.UseSession(); // 1. Enable session support
app.UseAuthentication(); // 2. Authentication middleware
app.UseBffMiddleware(); // 3. BFF-specific validation
app.UseAuthorization(); // 4. Authorization middleware
app.UseAntiforgery(); // 5. Anti-forgery token validation
// Map BFF management endpoints
app.MapBffManagementEndpoints();
app.Run();
3. Client-Side Usage
// Login
window.location.href = '/bff/login?returnUrl=/';
// Get user information
const response = await fetch('/bff/user', {
headers: { 'X-CSRF-TOKEN': '1' }
});
const user = await response.json();
// Logout
await fetch('/bff/logout', {
method: 'POST',
headers: { 'X-CSRF-TOKEN': '1' }
});
Architecture
Security Model
┌─────────────────┐ ┌─────────────────┐
│ SPA Client │ │ BFF Server │
│ (Browser) │ │ (ASP.NET Core) │
└────────┬────────┘ └────────┬────────┘
│ │
│ 1. Login Request │
├───────────────────────────>│
│ │
│ 2. Redirect to IdP │
│<───────────────────────────┤
│ │
│ 3. Authenticate at IdP │
│ │
│ 4. Return to BFF │
├───────────────────────────>│
│ │
│ 5. Store session │
│ (server-side) │
│ │
│ 6. Set httpOnly cookie │
│<───────────────────────────┤
│ │
│ 7. API calls with cookie │
├───────────────────────────>│
│ + CSRF token │
│ │
Key Security Benefits:
- ❌ No access tokens in browser
- ✅ Tokens stored server-side only
- ✅ httpOnly, secure cookies
- ✅ CSRF protection
- ✅ Session validation on every request
Core Components
Configuration
BffOptions
public class BffOptions
{
// Anonymous session handling
public AnonymousSessionResponse AnonymousSessionResponse { get; set; }
// Anti-forgery configuration
public bool EnableAntiForgery { get; set; } = true;
public string AntiforgeryHeaderName { get; set; } = "X-CSRF-TOKEN";
public string AntiforgeryHeaderValue { get; set; } = "1";
// Endpoint configuration
public string ManagementBasePath { get; set; } = "/bff";
public string LoginEndpoint { get; set; } = "/login";
public string LogoutEndpoint { get; set; } = "/logout";
public string UserEndpoint { get; set; } = "/user";
// Session configuration
public TimeSpan SessionLifetime { get; set; } = TimeSpan.FromHours(8);
public TimeSpan SlidingExpiration { get; set; } = TimeSpan.FromHours(1);
}
Session Management
Server-Side Sessions
// In-memory session store (development)
builder.Services.AddBffCore()
.AddServerSideSessions();
// Distributed cache session store (production)
builder.Services.AddBffCore()
.AddServerSideSessions(options =>
{
options.CacheName = "bff-sessions";
});
// Configure distributed cache (Redis example)
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
Session Revocation
public class MyService
{
private readonly ISessionRevocationService _revocation;
public MyService(ISessionRevocationService revocation)
{
_revocation = revocation;
}
public async Task RevokeUserSessionsAsync(string userId)
{
await _revocation.RevokeSessionAsync(userId);
}
}
Endpoints
The BFF provides the following management endpoints:
| Endpoint | Method | Description |
|---|---|---|
/bff/login |
GET | Initiates login flow |
/bff/logout |
POST | Logs out current session |
/bff/user |
GET | Returns current user claims |
/bff/backchannel-logout |
POST | Handles backchannel logout from IdP |
Customizing Endpoints
// Custom login service
public class CustomLoginService : ILoginService
{
public Task ProcessRequestAsync(HttpContext context)
{
// Custom login logic
}
}
builder.Services.AddSingleton<ILoginService, CustomLoginService>();
Middleware
BffMiddleware performs:
- Session validation
- Anti-forgery token validation
- Request authentication checks
- Endpoint-specific security
// Mark endpoints as BFF API endpoints
[BffApi]
[HttpGet("/api/data")]
public IActionResult GetData()
{
return Ok(new { data = "secure data" });
}
// Mark endpoints as BFF UI endpoints
[BffUIEndpoint]
[HttpGet("/secure-page")]
public IActionResult SecurePage()
{
return View();
}
Advanced Configuration
CSRF Token Customization
builder.Services.AddBffCore(options =>
{
// For Angular (uses custom header)
options.AntiforgeryHeaderName = "X-CSRF";
options.AntiforgeryHeaderValue = "1";
// For React/Vue (default)
options.AntiforgeryHeaderName = "X-CSRF-TOKEN";
options.AntiforgeryHeaderValue = "1";
});
Anonymous Session Handling
builder.Services.AddBffCore(options =>
{
// Return 401 for anonymous users (default)
options.AnonymousSessionResponse = AnonymousSessionResponse.Response401;
// Return 200 with anonymous claims
options.AnonymousSessionResponse = AnonymousSessionResponse.Response200;
});
Background Cleanup
// Automatic cleanup runs every 1 hour by default
builder.Services.AddBffCore()
.AddServerSideSessions(options =>
{
options.CleanupInterval = TimeSpan.FromMinutes(30);
});
Target Frameworks
- .NET 8.0
- .NET 9.0
Dependencies
- Duende.AccessTokenManagement.OpenIdConnect (3.2.0) - Token management
- Duende.IdentityModel (7.1.0) - Identity model utilities
- Pisum.Bff.Shared (1.0.0) - Shared models
Related Packages
- Pisum.Bff.Shared - Shared models and utilities
- Pisum.Bff.Yarp - YARP integration for API gateway
- Pisum.Bff.Blazor.Client - Blazor WebAssembly client components
Examples
See the samples directory for complete examples:
- Demo.Bff.Blazor.Server - Blazor Server with BFF pattern
- Demo.Bff.Angular - Angular SPA with BFF pattern
Best Practices
- Always use HTTPS in production
- Enable anti-forgery tokens for all state-changing requests
- Use distributed cache for session storage in production
- Set appropriate session lifetime based on your security requirements
- Implement session cleanup to remove expired sessions
- Monitor session store for performance and capacity
- Use secure cookie settings (httpOnly, secure, sameSite)
Security Considerations
- Access tokens are never exposed to the browser
- All sessions are stored server-side
- CSRF protection is enabled by default
- Sessions can be revoked centrally
- Supports backchannel logout from identity provider
Contributing
This is part of the Pisum BFF framework. For contributions and issues, please refer to the main repository.
License
Copyright © 2025 pisum.net
Support
For questions and support, please open an issue in the main repository.
Showing the top 20 packages that depend on Pisum.BFF.
| Packages | Downloads |
|---|---|
|
Pisum.Bff.Yarp
Pisum Backend for Frontend (BFF) security framework YARP library.
|
63 |
.NET 8.0
- Pisum.Bff.Shared (>= 1.11.0)
- Duende.AccessTokenManagement.OpenIdConnect (>= 3.2.0)
- Duende.IdentityModel (>= 7.1.0)
.NET 9.0
- Pisum.Bff.Shared (>= 1.11.0)
- Duende.AccessTokenManagement.OpenIdConnect (>= 3.2.0)
- Duende.IdentityModel (>= 7.1.0)
| Version | Downloads | Last updated |
|---|---|---|
| 1.11.0 | 62 | 10/21/2025 |
| 1.10.0 | 34 | 10/09/2025 |
| 1.9.0 | 13 | 10/09/2025 |
| 1.8.1-preview | 3 | 10/09/2025 |