Summary
- RFC 10017 ranks a full Backend for Frontend above token mediation and a browser-only OAuth client because the BFF keeps access tokens, refresh tokens and confidential-client credentials away from JavaScript.
- The BFF blocks token extraction and independent token acquisition as that client, but hostile code in the application's approved origin can still issue commands through the user's cookie session. Token custody and command authority remain different controls.
- Leaders need an explicit architecture register, one application per origin, strict script admission, protected cookies and CSRF checks, narrow BFF host/path/method mappings, resource authorization, high-impact confirmation and evidence of the committed business effect.
A payroll application uses the architecture its security review preferred. JavaScript never receives an OAuth access token. The refresh token sits in a server vault. The browser holds only an HttpOnly, Secure session cookie. A scanner confirms that no bearer value is present in Local Storage, IndexedDB, page memory or the developer console.
Then a compromised third-party script asks the application's BFF to change an employee's bank account. The browser attaches the protected cookie. The BFF recognizes the session, retrieves the user's token, adds it to the outbound request and forwards the command. The resource server sees an expected client, a valid token and an allowed scope. The token was never stolen. The command still ran.
That is the authority boundary clarified by RFC 10017, OAuth 2.0 for Browser-Based Applications, published in August 2026 as an IETF Best Current Practice. A BFF is materially safer than placing OAuth credentials in browser code. It is not a declaration that every request originating inside the application is legitimate.
Four attacks, not one token-theft story
Security discussions about browser OAuth often begin and end with exfiltration. RFC 10017 uses a broader model. Once malicious JavaScript or WebAssembly executes in the application context, it carries the same browser privileges as legitimate code. It can access data and storage available to the application, interact with same-origin contexts, alter execution flow and send requests from the approved origin.
The RFC separates four attacks. A one-time thief copies the tokens currently available. A persistent thief waits for every replacement and can defeat the comfort supplied by short access-token lifetimes. A more capable attacker ignores existing storage and launches a fresh Authorization Code flow, reusing the user's authorization-server session to obtain an independent token set. A fourth attacker never takes a token at all and simply makes the live browser send an authorized request.
Those distinctions change the value of familiar defenses. Refresh-token rotation can reveal some reuse, but persistent code can take the newest rotated token and prevent the legitimate application from using it. A Web Worker can isolate a stored token, but same-origin code may request a fresh one. DPoP can make a copied token unusable away from a non-exportable key, but hostile code can run a new browser-only flow using its own key, or invoke a live request path.
PKCE prevents an intercepted authorization code from being redeemed by the wrong client instance; it does not make hostile code in the registered origin distinguishable from the application.
The lesson is not that these controls are useless. Each removes a specific capability. The mistake is to let the name of one successful control stand for the state of the whole application.
The BFF moves the client—and the liability
RFC 10017 presents three architectures in decreasing order of security. In a full BFF, a server component becomes the confidential OAuth client. It conducts the Authorization Code flow with PKCE, holds access and refresh tokens, associates them with a cookie-based session and proxies every protected-resource call. The browser receives no OAuth token.
This blocks three major paths. There is no browser token for a one-time thief to copy. Persistent code cannot keep harvesting replacements that never enter its execution environment. Malicious browser code cannot independently exchange a newly captured code as the registered confidential client because it lacks the BFF's credentials. HttpOnly also prevents script from reading the session identifier and converting client hijacking into a portable stolen session.
The remaining attack is different. Malicious code can send requests to the BFF from the legitimate origin. The browser is entitled to attach the cookie, and the BFF is designed to translate that session into token-bearing resource calls. The attacker has not crossed the token boundary; it has used the command boundary.
This is why the BFF must be more than a reverse-proxy-shaped convenience. RFC 10017 requires strict outbound control. Approved frontend endpoints should map to known resource hosts, paths and methods. A request parameter must not be allowed to turn /bff/report into a token-bearing fetch to an arbitrary destination. A generic path-forwarding feature expands a protected session into whatever authority the upstream token carries.
Cookie custody also has its own rules. The RFC requires Secure and HttpOnly, recommends SameSite=Strict, path /, no Domain attribute and a suitable host-bound prefix. Because the browser attaches cookies, state-changing BFF routes still need CSRF protection. A token-free JavaScript heap does not repair an endpoint that accepts a forged cross-site command.
The middle architecture exposes exactly what it saves
A token-mediating backend retains the confidential-client role and the refresh token but returns access tokens to the browser, which calls resource servers directly. It avoids proxying every response and can reduce server burden. Its protection is correspondingly narrower.
Hostile code cannot steal a refresh token that remains on the server or complete a new flow without the backend's credentials. It can still steal the access token presented to JavaScript. Even if storage hides that token, hostile code can ask the mediation endpoint for the latest one through the user's session. The architecture protects duration better than it protects immediate reach.
This pattern also complicates sender constraint. The backend obtains the token while the browser uses it. RFC 10017 does not define a split DPoP responsibility for that arrangement. Leaders should not fill that gap with an architecture diagram that labels both boxes “PoP enabled.” The accepting servers need one implemented key-custody and proof path that can be tested.
The RFC recommends considering token mediation only when system requirements prevent a full BFF. That is not a ban. It is a demand to name the cost that justified leaving access tokens in the browser and to limit their audience, scope and life accordingly.
Browser-only clients remain public clients
In the third pattern, JavaScript is the OAuth client. It has no credential that can remain confidential from the environment in which the application executes. A shared secret compiled into the application does not change that fact.
The browser-only client must use Authorization Code with PKCE, exact registered redirect URIs and appropriate CSRF protection. If the authorization server issues refresh tokens, it must rotate or sender-constrain them and impose a maximum or inactivity lifetime. These are strong minimum rules. They do not remove the four attacks once malicious code runs inside the accepted origin.
Origin is therefore both a security boundary and a concentration of trust. RFC 10017 recommends one application per origin. Several unrelated applications under the same scheme, host and port share browser powers that security teams may have treated as separate. Exact redirect matching, CORS and postMessage origin checks become easier to reason about when the origin has one owner.
CORS must also remain in its lane. It controls whether browser code can read a cross-origin response. It is not server-side authorization, and it cannot distinguish approved code from hostile code already running in an allowed origin. Likewise, a postMessage event is not authentic because it arrived through a browser API; both sender and receiver origins require exact verification.
Why the Service Worker does not become a superior authority
A tempting design puts the OAuth flow and tokens inside a Service Worker. The worker can isolate memory and augment outgoing calls without giving the application the token. At first glance, it seems to produce a BFF inside the browser.
RFC 10017 rejects that conclusion. Malicious application code can unregister the worker. Existing contexts may keep it alive temporarily, but a new browsing context can begin without its protection. The attacker can then launch a fresh flow. The worker successfully guarded one reality layer—stored tokens—without acquiring unremovable authority over the application origin.
The same limit applies to non-exportable Web Crypto keys. “Non-exportable” constrains the JavaScript API; the Web Crypto specification does not promise TPM custody or encrypted filesystem storage. More importantly, a key that cannot be copied may still be used by hostile code in the live environment. Key custody is not code intent.
Evidence must follow the command, not stop at the vault
A useful audit trail begins before OAuth and ends after the resource effect. It should record the application origin and script-release fingerprint, BFF session identifier in privacy-safe form, CSRF and expected-origin results, the exact BFF endpoint-to-resource mapping, method and destination, a hash of token audience and scopes, current resource-policy version, object state, idempotency key and commit result. It should not record raw tokens, cookies or client secrets.
Negative tests should exercise each attack separately. Can JavaScript read a token? Can it obtain one through a new flow? Can it ask the token-mediation endpoint for one? Can it command the BFF without seeing one? Can it change the outbound host, path or method? Can a valid session repeat an irreversible action after the first response is lost? A single browser scan cannot answer those questions.
Running-Code Primacy supplies the right discipline. “BFF” is a design label. Its authority comes from the routes, cookies, server credentials, token vault, resource checks and failure behavior actually running. Minimum Initial Specification keeps shared OAuth mechanics precise while leaving the final command decision with the service that bears the consequence. Reality-layer clarity prevents a protected token from becoming symbolic proof of a protected operation.
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance