Summary

  • RFC 10017’s Backend for Frontend is the confidential OAuth client. It keeps access and refresh tokens behind a cookie-backed session, so browser JavaScript cannot extract existing tokens or exchange a newly captured authorization code on its own.
  • That boundary does not stop hostile same-origin code from sending an application-valid request through the user’s live BFF session. The remaining consequence is client hijacking: less powerful than portable token theft, but bounded only by the actions the frontend, BFF and resource server actually permit.
  • A defensible deployment preserves the complete request-to-decision receipt: origin and frontend version, session and cookie policy, CSRF result, BFF endpoint, allowed destination/path/method, token audience and scope, resource-server decision, response handling, anomaly policy and remediation.

Imagine the incident report begins with good news: no access token was found in localStorage, no refresh token appeared in a JavaScript heap dump, and the session cookie was HttpOnly. The attacker still changed a delivery address, downloaded a report or initiated an account action.

Nothing in that sequence requires the attacker to possess a token.

The malicious code ran inside the same origin as the legitimate application. It called an endpoint the application was allowed to call. The browser attached the session cookie. The Backend for Frontend found the corresponding access token, forwarded the request and returned the result. Every component performed its nominal function; the unwanted act travelled through the intended path.

This is the boundary made unusually clear in RFC 10017, OAuth 2.0 for Browser-Based Applications. Published in August 2026 as an IETF Best Current Practice, it names Aaron Parecki, Philippe De Ryck and David Waite as authors. Parecki’s current IETF record lists him as a chair of the SCIM working group and records this RFC among two published RFCs. His own site describes him as an identity-standards director at Okta, maintainer of oauth.net and a participant in the IETF OAuth Working Group.

Those facts explain why his work belongs in the record. They do not make the BFF his personal invention or give him control over anyone’s deployment. The RFC is collective work, and its operational result belongs to the people who configure and run each application.

The threat starts after code runs

Browser security discussions often begin too late. They ask where a token should be stored after assuming that the application code is trustworthy. RFC 10017 begins with the harder condition: an attacker has found a way to execute JavaScript or WebAssembly in the application’s execution context.

At that point the attacker’s code is not a foreign caller standing outside the origin. It has the same privileges as the legitimate code. It can inspect accessible storage, call functions, alter control flow, interact with same-origin contexts and send requests to the application’s backend. Content Security Policy, careful encoding, dependency control, Subresource Integrity and origin isolation are essential because preventing that execution remains the only way to prevent client hijacking itself. The architecture analysis asks what damage remains if prevention fails.

The RFC separates four OAuth-specific attack paths. A script can steal the tokens available during one execution. It can install a persistent mechanism that captures each replacement token. It can ignore existing tokens and run a new authorization flow in a hidden frame. Or it can leave the tokens alone and simply send requests from the user’s browser.

That fourth path is the important correction. If the browser or an external component automatically supplies the credential, hostile code can imitate the legitimate request and receive the same augmentation. A storage design can make a credential non-exportable without making the application’s permitted actions non-invocable.

The token leaves browser code; the mandate does not

RFC 10017 presents three main browser-OAuth architectures in decreasing order of security. The strongest is the BFF. The server component assumes all OAuth responsibilities, becomes a confidential client and proxies every resource-server interaction.

The flow creates two different relationships. The authorization server issues access and, where applicable, refresh tokens to the BFF. Separately, the BFF establishes a browser session represented by a cookie. When the frontend wants a protected resource, it sends its request to the BFF with that cookie. The BFF resolves session state, removes the cookie from the outbound request, attaches the appropriate access token and calls the resource server.

This design blocks three severe paths. There is no access or refresh token for JavaScript to extract. Repeated execution does not expose a stream of rotated tokens. A code captured from a new authorization request is not enough to obtain tokens because the attacker lacks the confidential client’s credentials; PKCE adds its own protection to the code transaction.

HttpOnly adds another real boundary. Hostile JavaScript cannot directly read the session state, so client hijacking does not automatically become portable session hijacking. Closing the browser or losing the origin foothold can therefore end capabilities that a stolen bearer token might have carried elsewhere.

But the user’s mandate has not vanished. It has been represented by a server session and made callable through BFF endpoints. Hostile code inside the legitimate origin can still invoke those endpoints while the session is active. The RFC calls the result client hijacking and says that the only viable attack pattern remaining under its model is proxying requests through the user’s browser.

That is not an argument against the BFF. It is the reason to describe its security property accurately. The BFF removes independent, portable authority from the browser. It does not distinguish good JavaScript from bad JavaScript that has already acquired the same execution privileges.

A BFF is a translator with enumerated exits

The BFF translates an inbound session-bearing request into an outbound token-bearing request. A translator that accepts an arbitrary destination is an authority leak.

RFC 10017 therefore requires strict outbound controls. The BFF must validate destination hosts before forwarding requests and maintain an explicit allowlist of approved resource servers. If a route maps /bff/orders/create to an order service, that mapping should terminate at the predefined backend. Dynamic paths must be validated so that user-controlled input cannot turn the BFF into an open proxy. The RFC also identifies per-endpoint HTTP method restrictions as a way to reduce the attack surface.

The control needs more resolution than “host allowed.” A host can contain public and administrative paths. One path can accept GET and become dangerous under DELETE. A query or body field can contain a downstream URL. Redirect handling can cross the approved boundary after the initial destination passes validation. The practical allowlist is a tuple: resource identity, scheme and host, path template, method, request schema, redirect rule, token audience and permitted scopes.

The resource server remains a separate principal. It should validate the token’s issuer, audience, expiry and permissions and apply its own policy to the requested object and action. A broad token plus a broad BFF route makes client hijacking powerful. Narrow routes and object-level authorization preserve the difference between “the application can view this user’s invoices” and “any code in the application origin can administer every account.”

This is Minimum Initial Specification in operational form. The shared standard can require a confidential client, protected cookie, CSRF defense and bounded proxy. It cannot publish one universal endpoint map for every business. Each operator must supply the local portion without pretending that “standards-compliant BFF” describes the reachable action set.

Cookie hardening protects session identity, not intent

The session cookie is sensitive because it connects the browser to the server-held tokens. RFC 10017 requires Secure and HttpOnly, recommends SameSite=Strict, path /, omission of the Domain attribute and an HTTP-set prefix such as __Host-Http-. A client-side session containing token material should be encrypted so that token contents are not persisted in plaintext.

These controls answer concrete questions. Can script read the cookie? Can an insecure transport receive it? Can a sibling subdomain set or receive it? Can malware reading the browser profile see token material? None answers whether the request expressed the user’s current intention.

Cookie authentication also brings CSRF into scope. The BFF must implement a proper defense. SameSite=Strict may be adequate when no other application shares the same site, but “site” is wider than “origin.” Two subdomains under the same registrable domain are same-site and cross-origin. A compromised sibling can therefore create a forgery route even when ordinary cross-site cookies are blocked.

CORS can help, but only when the design forces a preflight. Browsers may send safelisted requests before withholding the response from the calling origin. RFC 10017 recommends a custom header so cross-origin script requests require preflight and requires the BFF to verify that header when this mechanism is chosen. Framework anti-forgery or double-submit mechanisms can supply another route.

CSRF and malicious same-origin code are different problems. A good anti-forgery token distinguishes the legitimate origin from an external origin. It cannot distinguish the legitimate application from hostile code already executing in that legitimate origin. Treating a passed CSRF check as proof of human intent would assign the control a mandate it never had.

The remaining attack is constrained by what the application can do

Client hijacking is not equivalent to direct token theft. RFC 10017 says it is less powerful because the attacker cannot take direct control of the tokens and remains restricted by policies enforced on the client application. A resource server may refuse calls from one origin through its CORS policy, and BFF routes can expose only a subset of backend operations. The attacker also needs the user’s browser and active execution opportunity.

Those constraints are valuable only when they are real. An architecture diagram cannot prove them. The operator needs an inventory of every BFF endpoint, the downstream host/path/method it can reach, the token and scopes it selects, the object-level authorization it expects and the response data it returns. The inventory should be exercised with hostile same-origin code, not merely reviewed as configuration.

The BFF is also a natural observation point. It sees every proxied request and response. RFC 10017 notes that anomaly detection and rate limiting can mitigate the consequences of hijacking there. Useful signals include a burst of normally human-paced actions, an unusual sequence of endpoints, access to an atypical object set, a new frontend build calling an old route, or a session continuing after its refresh token has become invalid.

That visibility has a cost. A third-party-hosted BFF can observe all traffic between the frontend and resource servers. Data minimization, retention rules, tenant isolation and operator access therefore belong beside the security controls. Moving tokens to a server can reduce browser exposure while concentrating both traffic knowledge and enforcement power.

Session lifetime must also follow the authority it represents. The RFC advises aligning the BFF session lifetime with the refresh token’s maximum lifetime and invalidating an active session when its refresh token becomes unusable. A long-lived session wrapping an expired or revoked token relationship creates contradictory state. A client-side session can scale more easily but makes direct session revocation harder; its effective control follows token revocation and expiry. A server-side session offers more direct control at the cost of replicated or sticky state.

Build the request-to-decision receipt

Do not log raw access tokens, refresh tokens, client secrets or full session cookies. Evidence can be specific without becoming a credential dump.

For each sensitive action, retain a correlation-safe session identifier, session creation and expiry, cookie policy version, authentication and authorization-code transaction, BFF client identity and frontend build. Record the incoming endpoint, normalized method and path template, CSRF/origin/CORS result and request-schema outcome.

Then preserve the translation. Name the outbound resource server, path template and method, the allowlist policy version, and a non-secret token fingerprint or identifier with issuer, audience, scopes and expiry. Record refresh, rotation, revocation or invalidation events when they affect the action. Keep the resource server’s authorization result, status, response transformation, rate-limit or anomaly decision and the operator-owned remediation path.

This joined receipt distinguishes failures that a “token safe” badge collapses. Token exfiltration is different from direct session theft. CSRF is different from hostile same-origin execution. An open-proxy destination bug is different from an overbroad resource-server permission. A correctly denied request is different from a BFF routing failure. Each has a different owner and repair.

Running-Code Primacy supplies the final test. Execute a controlled hostile script in the application origin. Verify that it cannot read tokens or session state, cannot start an independent token flow, cannot escape the approved destination/path/method set, cannot exceed downstream object authorization, and produces an intelligible alert and receipt when it attempts an allowed but abnormal action.

The BFF succeeds when that exercise proves two things at once: the token cannot leave, and the remaining request authority is narrow, observable and reversible.

Sources