Skip to content

feat: add DPoP core storage layer (ENG-4782)#199

Merged
mrudatsprint merged 2 commits into
miker/dpop-in-the-javascript-sdkfrom
miker/eng-4782/core-storage-layer
Jul 15, 2026
Merged

feat: add DPoP core storage layer (ENG-4782)#199
mrudatsprint merged 2 commits into
miker/dpop-in-the-javascript-sdkfrom
miker/eng-4782/core-storage-layer

Conversation

@mrudatsprint

Copy link
Copy Markdown
Collaborator

- Add `dpop` v2.1.1 runtime dependency and `fake-indexeddb` devDependency
  to packages/core/package.json

- SDKConfig: add optional `useDpop` and `dpopTokenStorage` fields

- UrlHelper: add `getAuthorizeUrl(state?, dpopJkt?, codeChallenge?)`
  targeting FusionAuth /oauth2/authorize directly; update UrlHelperTypes
  to include response_type, code_challenge, code_challenge_method, dpop_jkt

- DPoPStorage: IndexedDB abstraction for ES256 CryptoKeyPair persistence
  (db: fusionauth-sdk:dpop, store: keypair, keyed by clientId)

- DPoPTokenStore: localStorage/memory token storage for DPoP-bound tokens
  (key: fusionauth-sdk:tokens:<clientId>); includes getAccessToken() and
  isExpired getter

- packages/core/src/DPoP/index.ts re-exports both classes

- 54 tests passing (21 DPoPTokenStore, 6 DPoPStorage, 16 UrlHelper, 7 SDKCore,
  4 CookieHelpers)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the initial “core” building blocks for DPoP mode in @fusionauth-sdk/core, including storage primitives (IndexedDB for key material + localStorage/memory for DPoP-bound tokens) and URL helper support for generating a direct /oauth2/authorize URL with PKCE + dpop_jkt.

Changes:

  • Add DPoPStorage (IndexedDB-backed) and DPoPTokenStore (localStorage/memory) with accompanying Vitest coverage.
  • Extend UrlHelper to generate an OAuth2 authorize URL for DPoP mode, including PKCE parameters and dpop_jkt.
  • Add SDK config surface (useDpop, dpopTokenStorage) and export the new DPoP module from the package entrypoint.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/core/src/UrlHelper/UrlHelperTypes.ts Expands query param typing to include authorize/PKCE/DPoP parameters.
packages/core/src/UrlHelper/UrlHelper.ts Adds getAuthorizeUrl() for DPoP-mode direct /oauth2/authorize URL creation.
packages/core/src/UrlHelper/UrlHelper.test.ts Adds unit tests validating authorize URL parameter composition and state handling.
packages/core/src/SDKConfig/SDKConfig.ts Adds opt-in DPoP config flags and token storage selection.
packages/core/src/index.ts Re-exports the new DPoP module from the core package entrypoint.
packages/core/src/DPoP/index.ts Adds a barrel export for DPoP storage/token-store types.
packages/core/src/DPoP/DPoPTokenStore.ts Implements DPoP token persistence in localStorage or in-memory.
packages/core/src/DPoP/DPoPTokenStore.test.ts Adds Vitest coverage for both localStorage and memory token-store modes.
packages/core/src/DPoP/DPoPStorage.ts Implements IndexedDB persistence for the DPoP keypair (namespaced by clientId).
packages/core/src/DPoP/DPoPStorage.test.ts Adds Vitest coverage using fake-indexeddb for IndexedDB behavior.
packages/core/package.json Adds runtime dependency on dpop and dev dependency on fake-indexeddb.
AGENTS.md Documents repo layout, tooling, and environment/testing conventions (incl. IndexedDB polyfill guidance).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +61 to +65
/** Removes stored tokens. Called on logout. */
clear(): void {
this.memoryStore = null;
this.getLocalStorage()?.removeItem(this.storageKey);
}
Comment on lines +77 to +91
private openDb(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const req = indexedDB.open(DB_NAME, DB_VERSION);

req.onupgradeneeded = event => {
const db = (event.target as IDBOpenDBRequest).result;
if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME);
}
};

req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
}
Comment on lines +129 to +136
it('clear() removes tokens from memory', () => {
const store = new DPoPTokenStore(CLIENT_ID, 'memory');
store.set(makeTokens());

store.clear();

expect(store.get()).toBeNull();
});
@mrudatsprint
mrudatsprint merged commit 9f3e0bc into miker/dpop-in-the-javascript-sdk Jul 15, 2026
6 checks passed
@mrudatsprint
mrudatsprint deleted the miker/eng-4782/core-storage-layer branch July 15, 2026 21:54
@mrudatsprint
mrudatsprint restored the miker/eng-4782/core-storage-layer branch July 15, 2026 21:56
@mrudatsprint
mrudatsprint deleted the miker/eng-4782/core-storage-layer branch July 15, 2026 22:04
@mrudatsprint
mrudatsprint restored the miker/eng-4782/core-storage-layer branch July 15, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants