Menu
InfoQ Cloud·April 30, 2026

Solving the DPoP Storage Paradox in Browser-Based OAuth Systems

This article explores the architectural challenges of securely storing private keys for DPoP (Demonstrating Proof-of-Possession) in browser-based applications, a critical component for preventing OAuth token replay attacks. It highlights the "storage paradox" where browser mechanisms like IndexedDB, while preventing key extraction, still allow XSS attacks to use the key as a signing oracle. The discussion then focuses on the Backend-for-Frontend (BFF) pattern as the industry standard solution for shifting key management server-side, outlining its benefits and trade-offs.

Read original on InfoQ Cloud

The Challenge of Browser-Based DPoP Key Storage

DPoP (Demonstrating Proof-of-Possession) is a critical security mechanism in OAuth 2.0, designed to prevent token replay attacks by binding access tokens to a client's cryptographic key pair. While effective, its implementation in browser-based Single Page Applications (SPAs) faces a significant architectural paradox: how to store the private signing key securely while making it usable by client-side code without exposing it to malicious scripts (e.g., via XSS).

The DPoP Storage Paradox

The Web Crypto API allows storing non-extractable CryptoKey objects in IndexedDB. This prevents direct export of the private key bytes. However, this does not prevent an attacker who achieves XSS from using the browser's crypto subsystem as a "signing oracle". The attacker can invoke `crypto.subtle.sign()` with the stored key to generate valid DPoP proofs for arbitrary requests, even without ever extracting the raw key material. This loophole renders the non-extractability insufficient against script-level attacks.

javascript
await crypto.subtle.exportKey('jwk', privateKey); // throws InvalidAccessError
await crypto.subtle.sign(alg, privateKey, payload); // succeeds — valid signature
⚠️

The Oracle Attack

An XSS attacker can use the browser's crypto subsystem as a signing oracle. They can retrieve the non-extractable CryptoKey handle from IndexedDB and call `crypto.subtle.sign()` to produce valid DPoP proofs for arbitrary requests, effectively bypassing the token binding security without ever extracting the private key.

Architectural Solutions: Backend-for-Frontend (BFF)

To address the DPoP storage paradox, the industry has largely converged on the Backend-for-Frontend (BFF) pattern. This shifts the trust boundary and key management responsibility from the insecure browser environment to a server-side component. The BFF acts as a confidential OAuth client, handling the DPoP key generation, authorization code exchange, token management, and DPoP proof generation for outbound API requests. The browser only receives an HTTP-only, Secure, SameSite cookie to maintain a session with the BFF, never directly touching sensitive key material or tokens.

  • Key Material Isolation: DPoP private keys are generated and stored in the BFF's process memory, away from the browser's reach.
  • Confidential Client: The BFF acts as a confidential OAuth client, leveraging server-side security for token handling.
  • Reduced Browser Attack Surface: The browser only manages a session cookie, significantly reducing the impact of client-side vulnerabilities like XSS on token security.

While the BFF pattern introduces additional infrastructure overhead and complexity (e.g., requiring a dedicated server for each frontend type), it is considered the most secure industry standard for browser-based sender-constrained tokens, effectively mitigating the DPoP storage paradox and the oracle attack.

OAuth 2.0DPoPProof-of-PossessionSecurity TokensXSSBackend-for-FrontendBFFWeb Crypto API

Comments

Loading comments...