Decision. You cannot wave the BCP away as “written for consumer apps.” Its strongest sentence — “This architecture is strongly recommended for business applications, sensitive applications, and applications that handle personal data” (§6.1.4.3) — names your case to your face [1]. But it is a trade-off, not a mandate: §6 presents the patterns as “a different trade-off between security and simplicity … in decreasing order of security” [2], and attaches no RFC 2119 keyword to the choice. Weight it as a strong prior, not a proof.
Status (Jul 2026)
Revision -27, IESG-approved as Best Current Practice, in the RFC Editor queue — no RFC number yet [3]. Authors: Parecki (Okta), De Ryck (Pragmatic Web Security), Waite (Ping) [1].
The one assumption doing all the work
§5: “even when applying these security guidelines, there remains a risk that the attacker finds a way to trigger the execution of malicious JavaScript”, and “the malicious JavaScript code has the same privileges as the legitimate application code” [2]. CSP and SRI appear only as preventive measures the document then declares insufficient. Note what is not assumed: nothing about public users, third parties, or consumer scale. The threat model is “your own origin runs attacker code” — internal-ness does not touch it.
Assumptions vs. an internal console
| BCP assumption | Holds? |
|---|---|
| XSS happens despite best practice (§5) | ✓ Internal ≠ XSS-free; supply-chain hits first-party code [2] |
| App is a “business application” (§6.1.4.3) | ✓ This is the named case [1] |
| Frontend + API on different origins, tokens needed in-browser | ✗ §1: “many web applications consist of a frontend and API running on a common domain, allowing for an architecture that does not rely on OAuth 2.0 … not within scope of this specification” [1] |
| Token theft is the dominant consequence | ⚠ §5.1.4 request-proxying “cannot be stopped or prevented by application-level security measures” — a BFF does not stop it [1] |
Row 3 cuts both ways. The BCP’s own carve-out — same-site frontend + API, OIDC login, server-held session — is outside the document. But that escape hatch is not “SPA with a JWT in memory”; it describes a server-maintained session, i.e. already BFF-shaped. A browser-based OAuth client holding Keycloak bearer tokens lands squarely back in scope, at §6.3, bottom of the ranking.
⚠ Row 4 bounds the prize: under XSS a BFF stops token exfiltration and persistence, not session riding through the BFF. For an admin console, seconds of authenticated admin API access is already catastrophic. → BFF trims the tail (offline replay, refresh-token abuse), not the body of the risk.
Reading the room
- Curity (sells a Token Handler): “SPAs have no means of keeping access and refresh tokens secure from malicious code” — absolutist, zero acknowledgement of any acceptable SPA case, product links throughout [4]. ⚠ Self-serving.
- Duende (sells
Duende.BFF): browser holds only a session cookie, never tokens [5]. True, and commercially convenient. - Auth0/Okta — employer of the lead author, and the most interesting witness because it argues against its own interest: “in some contexts, using the Authorization Code Flow with PKCE and all the concerns about token management in a SPA may be acceptable. In other contexts, it is not” [6]. The vendor closest to the document is the least absolutist about it.
- Independent 2026 read: “Prefer BFF when you can”, alternatives are “a compromise” — but never discusses cost, same-domain, or internal apps [7].
- The WG itself shows no dissent on the ranking; late-stage traffic is about cookie prefixes [8]. The ordering has consensus.
Verdict
Decisive, regardless of audience: keep refresh tokens out of the browser, and don’t treat “internal + CSP” as licence to relax token handling. Every one of the BCP’s four attack scenarios survives contact with an internal, first-party, single-origin console.
Not decisive: “the IETF ranks BFF first” is a claim about security ordering, not about whether the marginal security is worth a .NET BFF’s cost here. The document prices its own advice in “simplicity” [2] and declines to issue a SHOULD. Reading the ranking as a mandate is the blog-post telephone game, not the text.
On security grounds alone the BCP breaks the tie toward BFF — while naming business apps explicitly. It does not license anyone to claim the standard requires it.