SPA with DPoP

Client-side auth · DPoP token binding · Online Refresh Tokens · Refresh Token Metadata

Security Implications

Strengths

  • DPoP binds the access token to an ephemeral key pair generated in the browser — a token intercepted or exfiltrated alone is useless without the private key.
  • Refresh Token Metadata gives visibility into which device/browser is holding each refresh token, without needing a server-side session.

Risks & Considerations

  • It's still a public client with no client secret — anyone can register a client with the same client_id.
  • DPoP protects the token, not the page: XSS during an active session can still call getTokenSilently() and act as the user for as long as the tab is open.
  • DPoP's guarantee depends on the private key being non-extractable — if it were ever generated as an exportable WebCrypto key, XSS could exfiltrate the key itself alongside the token, defeating the binding entirely. Confirm the SDK generates it non-extractable; don't assume it.

Hardening Checklist

  • Ship a strict Content-Security-Policy — XSS is the primary residual risk once DPoP is in place.
  • Keep the redirect URI allowlist exact-match, not prefix/wildcard.
  • Verify DPoP proof iat/nonce windows are tight enough to make replay impractical.
  • DPoP binding is only as strong as the downstream API's own validation — a Resource Server that checks the access token's signature but not the DPoP proof and jkt thumbprint gets no protection from any of this.