BFF + OIDC Cookie: when Nginx silently kills the TLS connection
Context
Migrating a Blazor WASM application from client-side OIDC authentication (oidc-client-ts + JWT Bearer) to a BFF (Backend For Frontend) pattern: the ASP.NET Core server handles the full OIDC flow, the client receives an HttpOnly session cookie.
The stack:
- Blazor WASM (client) behind ASP.NET Core (server)
- Logto as identity provider (OIDC)
- Nginx as reverse proxy (Jelastic Cloud / Infomaniak)
- Session cookie via
AddCookie()+AddOpenIdConnect()server-side
The symptom
After deploying the BFF, authentication works fine on the Logto side (login OK), but when redirecting back to the application:
Secure Connection Failed
The connection to app.example.com was interrupted while the page was loading. The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
The error only appears after authentication. Unauthenticated pages (/health, static files) work perfectly. The TLS certificate is valid.
The investigation
What works
- Private browsing without authentication: OK
/healthendpoint: OK- SSL certificate: valid (Let’s Encrypt, 2 months until expiry)
ASPNETCORE_FORWARDEDHEADERS_ENABLED=true: properly configured
What breaks
- Any navigation after the session cookie is issued
- The redirect from Logto to
/signin-oidc
The culprit: large_client_header_buffers
The default Jelastic Nginx configuration:
1
2
client_header_buffer_size 1k;
large_client_header_buffers 4 2k;
The problem becomes obvious when you know that Nginx’s default value is 4 8k (official documentation). Jelastic reduced this to 4 2k in their default configuration - four times smaller than the standard value.
This is a well-known issue in environments where Nginx acts as a reverse proxy in front of applications with cookie-based authentication. JWT tokens alone can be 1-2 KB, and with OIDC session cookies, state parameters, and CSRF tokens, header size quickly spirals out of control (source).
With the BFF pattern, the ASP.NET Core session cookie contains:
- Encrypted user claims (sub, email, name, roles)
- Session metadata (expiration, sliding window)
- With
SaveTokens = true: OIDC tokens (access + id + refresh) - easily 2-3 KB more
The encrypted cookie easily exceeds 2 KB. But Nginx is configured with header buffers of 2 KB max (instead of the standard 8 KB). When the browser sends the cookie on the next request, Nginx kills the TLS connection before forwarding to the backend. No error log on the application side, no HTTP status code - just a broken TLS connection that the browser interprets as a security error.
Typically, when buffers are exceeded, Nginx returns a
400 Bad Request: Request Header or Cookie Too Largeerror. But in our case, the TLS connection is severed before Nginx can send an HTTP response - hence the misleading security error in the browser.
The fix
1. Increase Nginx header buffers
In nginx-jelastic.conf (inside the http block):
1
2
3
4
5
# Before (Jelastic default - 4x smaller than Nginx's default!)
large_client_header_buffers 4 2k;
# After - restoring Nginx's default, sufficient for OIDC session cookies
large_client_header_buffers 4 8k;
Restart Nginx after the change.
Note:
4 8kis Nginx’s default value. Some configurations even recommend4 16kfor applications with complex SSO (DigitalOcean). Memory is only allocated when headers exceed theclient_header_buffer_size(1 KB), so the impact is negligible.
2. Reduce cookie size
Disable SaveTokens if tokens aren’t needed server-side after authentication:
1
2
3
4
5
.AddOpenIdConnect(options =>
{
// ...
options.SaveTokens = false; // don't store tokens in the cookie
});
With BFF, tokens are typically only useful during the authentication flow (code exchange → tokens → claims). Once claims are extracted and stored in the session cookie, raw tokens are no longer needed - unless you need to call third-party APIs with the access token.
3. (Optional) Chunked cookie
For cases where the cookie still exceeds 4 KB, ASP.NET Core can split it into multiple chunks automatically. But it’s better to reduce the size upfront.
Why this problem didn’t exist before
With client-side JWT Bearer authentication:
- The JWT was sent in the
Authorization: Bearer xxxheader - The browser sent no authentication cookie
- Request headers stayed small
With BFF + Cookie:
- The session cookie is sent on every same-origin request
- Header size increases significantly
- Nginx configurations with restrictive buffers (< 4 KB) break silently
Summary
| Aspect | Detail |
|---|---|
| Symptom | TLS error after authentication, no HTTP error |
| Root cause | Nginx large_client_header_buffers too small for session cookie |
| Server fix | large_client_header_buffers 4 8k; in Nginx |
| App fix | SaveTokens = false to reduce cookie size |
| Gotcha | No application-side logs - Nginx drops the connection before reaching the backend |
References
- Nginx documentation -
large_client_header_buffers- default value4 8k - Fixing Request Header or Cookie Too Large (DEV Community)
- Resolving 400 Bad Request in Nginx (Stackademic)
- How to Optimize Nginx Configuration (DigitalOcean)
- Kubernetes ingress-nginx - Header Too Large (GitHub) - same issue in a K8s context