dbsc-toolkit 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,13 +9,15 @@ Server-side implementation of [Device Bound Session Credentials](https://w3c.git
9
9
 
10
10
  DBSC is a W3C draft that binds session cookies to a hardware-resident private key inside the browser. A stolen cookie is useless without that key — which never leaves the user's device.
11
11
 
12
- Chrome 147+ supports DBSC natively. This library handles the server side. Verified end-to-end against Chrome 147 on Windows.
12
+ Chromium 145+ supports DBSC natively — that includes Chrome, Edge, Brave, Opera, Arc, Vivaldi, and any other Chromium-based browser. Works across Windows (TPM 2.0), macOS Apple Silicon (Secure Enclave on M1/M2/M3/M4+), and Android (Keystore). This library handles the server side. Verified end-to-end against Chrome 147 on Windows with a real TPM 2.0.
13
+
14
+ **New here?** Read [HOW-IT-WORKS.md](./HOW-IT-WORKS.md) first. It walks through the threat model, the on-the-wire protocol, where the library fits in your app, and tier semantics in ~15 minutes. Skip it only if you already know DBSC.
13
15
 
14
16
  ## Live demo
15
17
 
16
18
  Try it: <https://dbsc-toolkit.onrender.com/>
17
19
 
18
- Open in Chrome 147+, click **Login**, then **Check session** — `tier` reads `"dbsc"` once the TPM key is bound. The demo uses a 60-second bound-cookie TTL so refresh kicks in fast — watch DevTools Network for the automatic `POST /dbsc/refresh` after the cookie expires. Use **Clear cookies** to reset and replay the flow. Source in [examples/express/](./examples/express/).
20
+ Open in any Chromium-based browser version 145+ (Chrome, Edge, Brave, Opera), click **Login**, then **Check session** — `tier` reads `"dbsc"` once the hardware-backed key is bound. The demo uses a 60-second bound-cookie TTL so refresh kicks in fast — watch DevTools Network for the automatic `POST /dbsc/refresh` after the cookie expires. Use **Clear cookies** to reset and replay the flow. Source in [examples/express/](./examples/express/).
19
21
 
20
22
  > Heads up: the demo runs on in-memory storage. Render restarts wipe sessions, so if "Check session" returns `not authenticated` after a while, the instance probably restarted — click **Login** again.
21
23
 
@@ -43,23 +45,41 @@ npm install express cookie-parser pg
43
45
  ```ts
44
46
  import express from "express";
45
47
  import cookieParser from "cookie-parser";
46
- import { dbsc } from "dbsc-toolkit/express";
48
+ import { randomUUID } from "node:crypto";
49
+ import { dbsc, bindSession } from "dbsc-toolkit/express";
47
50
  import { MemoryStorage } from "dbsc-toolkit/storage/memory";
48
51
 
49
52
  const app = express();
53
+ app.set("trust proxy", true);
50
54
  app.use(cookieParser());
51
- app.use(dbsc({ storage: new MemoryStorage() }));
55
+ app.use(express.json());
56
+
57
+ const storage = new MemoryStorage();
58
+ app.use(dbsc({ storage }));
52
59
 
53
- app.get("/me", (req, res) => {
54
- res.json(res.locals.dbsc);
60
+ app.post("/login", async (req, res) => {
61
+ const sessionId = randomUUID();
62
+ await bindSession(res, sessionId, storage, { userId: req.body.username });
63
+ res.json({ ok: true });
55
64
  });
56
65
 
66
+ app.get("/me", (req, res) => res.json(res.locals.dbsc));
67
+
57
68
  app.listen(3000);
58
69
  ```
59
70
 
60
- That single `app.use(dbsc(...))` mounts `POST /dbsc/registration` and `POST /dbsc/refresh` automatically. Chrome drives both your application code never sees those requests.
71
+ `app.use(dbsc(...))` mounts `POST /dbsc/registration` and `POST /dbsc/refresh` automatically Chrome drives both, your code never sees them. `bindSession()` is the one-liner you add to your login route: it writes the session row, issues a challenge, builds the registration header (both legacy + new names), and sets the two short-lived cookies Chrome needs to complete binding.
72
+
73
+ A full demo with `/me`, `/logout`, and `/clear-cookies` is in [examples/express/src/server.js](./examples/express/src/server.js).
61
74
 
62
- A full `/login` flow with cookie issuance is in [examples/express/src/server.js](./examples/express/src/server.js).
75
+ ## Adding DBSC to an existing app
76
+
77
+ If you already have a working session cookie and login route (Express-session, NextAuth, your own table — doesn't matter), DBSC slots in beside what you have. You don't migrate the session store and you don't rewrite login. Two patterns:
78
+
79
+ - Add one `bindSession()` call at the end of your existing login.
80
+ - Or set `autoBind` on the middleware and never touch login at all — DBSC binds users on their next page load.
81
+
82
+ Full integration story, per-route policy table, and rollout timeline in [docs/integrating-existing-auth.md](./docs/integrating-existing-auth.md).
63
83
 
64
84
  ## Subpath imports
65
85
 
@@ -80,12 +100,14 @@ Tree-shaking eliminates anything you don't import.
80
100
  ## How a verified flow looks
81
101
 
82
102
  1. User hits `POST /login`. Server creates a session, issues a challenge, sets `Secure-Session-Registration` response header and two short-lived cookies (`__Host-dbsc-reg`, `__Host-dbsc-challenge`).
83
- 2. Chrome immediately POSTs to `/dbsc/registration` with `Secure-Session-Response: <jws>`. The JWS carries the device public key signed by the matching private key (TPM).
103
+ 2. The browser immediately POSTs to `/dbsc/registration` with `Secure-Session-Response: <jws>`. The JWS carries the device public key signed by the matching private key (held in the platform's hardware key store).
84
104
  3. Middleware verifies the JWS, stores the public key bound to the session, sets `__Host-dbsc-session` cookie, returns DBSC session config JSON.
85
- 4. From now on, every refresh cycle (default 10 min) Chrome signs a fresh challenge with the TPM key. A copied cookie cannot pass refresh — the attacker has no key.
105
+ 4. From now on, every refresh cycle (default 10 min) the browser signs a fresh challenge with the hardware-resident key. A copied cookie cannot pass refresh — the attacker has no key.
86
106
 
87
107
  `tier` on `res.locals.dbsc` reads `"dbsc"` once registration completes.
88
108
 
109
+ For a complete walk-through of the protocol with every header value and timing detail, see [HOW-IT-WORKS.md](./HOW-IT-WORKS.md).
110
+
89
111
  ## Using the tier to actually defend
90
112
 
91
113
  Setting up the middleware does not protect anything on its own. The library does the negotiation and gives you a tier; **enforcing it is your responsibility**. The pattern:
@@ -99,7 +121,7 @@ app.get("/payment", (req, res) => {
99
121
  });
100
122
  ```
101
123
 
102
- If you skip the tier check, a stolen cookie still works. The cookie reaches your server, the session record exists, your code happily proceeds — DBSC bought you nothing. The whole point is the demotion: when a cookie is replayed without the TPM proof, tier drops to `"none"` (or stays at the lower fallback tier) and your gate refuses the request.
124
+ If you skip the tier check, a stolen cookie still works. The cookie reaches your server, the session record exists, your code happily proceeds — DBSC bought you nothing. The whole point is the demotion: when a cookie is replayed without the hardware-signed proof, tier drops to `"none"` (or stays at the lower fallback tier) and your gate refuses the request.
103
125
 
104
126
  Suggested handling per tier in a real application:
105
127
 
@@ -168,12 +190,12 @@ The library negotiates the strongest available binding per session:
168
190
 
169
191
  | Tier | Mechanism | Protection |
170
192
  |------|-----------|------------|
171
- | `dbsc` | Hardware-backed key, Chrome 147+ | Hardware binding — exfiltrated cookie is useless |
193
+ | `dbsc` | Hardware-backed key, Chromium 145+ | Hardware binding — exfiltrated cookie is useless |
172
194
  | `webauthn` | Platform authenticator | Hardware binding via platform authenticator |
173
195
  | `hmac` | HMAC + browser signals | Best-effort context binding, not hardware |
174
196
  | `none` | Standard cookie | No additional binding |
175
197
 
176
- The tier is available at `res.locals.dbsc.tier` (Express), `c.get("dbscTier")` (Hono), `req.dbsc.tier` (Fastify), and via `getDbscSession()` (Next.js). Use it to apply different authorization policies per tier — for example, block payment flows when `tier !== "dbsc"`.
198
+ The tier is available at `res.locals.dbsc.tier` (Express), `c.get("dbsc").tier` (Hono — legacy `c.get("dbscTier")` still works in 1.x, removed in 2.0.0), `req.dbsc.tier` (Fastify), and via `getDbscSession()` (Next.js). Use it to apply different authorization policies per tier — for example, block payment flows when `tier !== "dbsc"`.
177
199
 
178
200
  ## Storage
179
201
 
@@ -237,9 +259,11 @@ app.get("/payment", (req, res) => {
237
259
 
238
260
  Reasons defined by the spec: `unreachable` (couldn't reach the refresh endpoint), `server_error` (refresh got a 5xx), `quota_exceeded` (browser's anti-abuse throttle). These are diagnostics from Chrome — your server cannot disable them, but it can react to them.
239
261
 
262
+ The quota is scoped per `(browser install, origin)`, not per origin globally. A site with a million users has a million separate quota buckets — one user spamming logins on their own Chrome cannot drain quota for anyone else. In production with normal login-once-and-stay-logged-in behavior, registration runs once per user and `quota_exceeded` essentially never trips. You hit it during development because the test loop logs in and out on the same browser dozens of times in a few minutes. To recover during testing, clear site data for the origin (`chrome://settings/clearBrowserData` → last hour → cookies and site data) or test in a fresh Incognito window.
263
+
240
264
  ## Header naming
241
265
 
242
- The W3C draft renamed the headers from `Sec-Session-*` to `Secure-Session-*`. Chrome 147 acts on the new names. The middleware reads both and writes both for compatibility. If you build response headers manually, send both:
266
+ The W3C draft renamed the headers from `Sec-Session-*` to `Secure-Session-*`. Chromium 145+ acts on the new names. The middleware reads both and writes both for compatibility. If you build response headers manually, send both:
243
267
 
244
268
  ```ts
245
269
  res.setHeader("Secure-Session-Registration", header);
@@ -257,9 +281,36 @@ See [SECURITY.md](./SECURITY.md) for reporting vulnerabilities.
257
281
  ## Project status
258
282
 
259
283
  - Single package on npm: `dbsc-toolkit`
260
- - Verified end-to-end on Chrome 147 / Windows / TPM 2.0
284
+ - Support floor: Chromium 145+ (Chrome, Edge, Brave, Opera, Arc, etc.) on Windows / macOS Apple Silicon / Android
285
+ - Verified end-to-end on Chrome 147 / Windows / TPM 2.0 (other Chromium browsers and platforms should work but not independently verified)
261
286
  - No third-party security audit yet
262
287
 
288
+ ## Production readiness
289
+
290
+ Honest table — what you're getting and where the rough edges are.
291
+
292
+ | Area | Status | Confidence |
293
+ |------|--------|-----------|
294
+ | Core protocol (registration + refresh + verification) | Stable | High — verified against real Chrome 147 + TPM 2.0 |
295
+ | Express adapter | Stable | High — used in the live demo, exercised on Render |
296
+ | Fastify / Hono / Next.js adapters | Stable | Medium — unit tests pass, share core code with Express, not battle-tested in production |
297
+ | `MemoryStorage` | Dev / test only | N/A — explicitly non-production |
298
+ | `RedisStorage` | Stable | Medium — atomic challenge consume via Lua, tested locally |
299
+ | `PostgresStorage` | Stable | Medium — migrations included, tested locally |
300
+ | Fallback tiers (WebAuthn, HMAC) | Implemented, lightly tested | Low — protocol shape correct, real-world step-up flows TBD |
301
+ | Security audit | None | — |
302
+ | W3C spec stability | Draft, library tracks Chromium's implementation | Spec may evolve; expect occasional wire-format adjustments |
303
+
304
+ **Should you use this in production?** Yes, with three conditions:
305
+
306
+ 1. **Use Redis or Postgres storage**, not memory. Memory storage on a server that ever restarts (Render free tier, serverless, autoscaling) produces a broken loop where browsers hold cookies that no longer match any stored key.
307
+ 2. **Treat it as defense-in-depth**, never the only auth layer. Your existing session cookie, password, MFA, rate limiting — all still required. DBSC raises the floor on session-replay attacks; it doesn't replace anything else.
308
+ 3. **Pin a version.** The W3C spec is still draft and the library tracks Chromium's implementation. Wire-format changes are unlikely but possible. Pin `dbsc-toolkit@~1.5.0` (patch updates only) and read the changelog before bumping.
309
+
310
+ Rough readiness estimate: **~85%** for the Express + Redis path (core protocol + main adapter + production storage all solid). **~70%** for Fastify / Hono / Next.js (same core, less production mileage). **~60%** for the fallback tier flows (WebAuthn/HMAC code is there, real-world step-up UX is on the user).
311
+
312
+ The realistic adoption pattern: ship it as the second layer behind your existing auth on Chromium-supporting routes. Don't lock non-Chromium users out. Gate genuinely high-value actions (payments, password change, admin) on `tier === "dbsc"`; leave everything else permissive. That's the recipe a Reddit-style site would use — see [docs/integrating-existing-auth.md](./docs/integrating-existing-auth.md).
313
+
263
314
  ## License
264
315
 
265
316
  Apache 2.0
@@ -1,4 +1,4 @@
1
- export type { ProtectionTier, BoundKey, Session, Challenge, RegistrationProof, RefreshProof, StorageAdapter, RateLimiter, DbscOptions, AnyTelemetryEvent, TelemetryEvent, RegistrationEvent, RefreshEvent, VerificationFailureEvent, SessionStolenEvent, FallbackTierEvent, } from "./types.js";
1
+ export type { ProtectionTier, BoundKey, Session, Challenge, RegistrationProof, RefreshProof, StorageAdapter, RateLimiter, DbscOptions, AutoBindResult, AnyTelemetryEvent, TelemetryEvent, RegistrationEvent, RefreshEvent, VerificationFailureEvent, SessionStolenEvent, FallbackTierEvent, } from "./types.js";
2
2
  export { DbscProtocolError, DbscVerificationError, DbscStorageError, ErrorCodes } from "./errors.js";
3
3
  export { validateJwk, detectAlgorithm } from "./crypto/jwk.js";
4
4
  export { verifyDbscJws, parseRegistrationJws } from "./crypto/jws.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,QAAQ,EACR,OAAO,EACP,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,QAAQ,EACR,OAAO,EACP,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErG,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,8BAA8B,EAC9B,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC"}
@@ -81,12 +81,25 @@ export interface FallbackTierEvent extends TelemetryEvent {
81
81
  export type AnyTelemetryEvent = RegistrationEvent | RefreshEvent | VerificationFailureEvent | SessionStolenEvent | FallbackTierEvent;
82
82
  export interface DbscOptions {
83
83
  storage: StorageAdapter;
84
- fallback?: "webauthn" | "hmac" | "none";
85
84
  registrationPath?: string;
86
85
  refreshPath?: string;
87
86
  boundCookieTtl?: number;
88
87
  registrationCookieTtl?: number;
89
88
  rateLimiter?: RateLimiter;
90
89
  onEvent?: (event: AnyTelemetryEvent) => void;
90
+ /**
91
+ * Optional callback for transparent migration. On every request that does not
92
+ * carry the bound cookie yet, the middleware calls this with the
93
+ * framework-native request. If it returns a userId string, the response gets
94
+ * the registration header + the two short-lived cookies, so Chromium 145+
95
+ * triggers /dbsc/registration on its own. Return null to skip.
96
+ * The sessionId used is whatever your existing auth says — supply both via
97
+ * the result type below.
98
+ */
99
+ autoBind?: (req: any) => Promise<AutoBindResult | null> | AutoBindResult | null;
100
+ }
101
+ export interface AutoBindResult {
102
+ sessionId: string;
103
+ userId: string;
91
104
  }
92
105
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { RequestHandler } from "express";
2
- import { type DbscOptions, type ProtectionTier, type SkippedEntry } from "../core/index.js";
1
+ import type { Response, RequestHandler } from "express";
2
+ import { type DbscOptions, type StorageAdapter, type ProtectionTier, type SkippedEntry } from "../core/index.js";
3
3
  export interface DbscExpressOptions extends DbscOptions {
4
4
  secure?: boolean;
5
5
  }
@@ -8,7 +8,6 @@ export interface DbscLocals {
8
8
  tier: ProtectionTier;
9
9
  skipped: SkippedEntry[];
10
10
  revoke: () => Promise<void>;
11
- requireBound: () => void;
12
11
  }
13
12
  declare global {
14
13
  namespace Express {
@@ -17,5 +16,13 @@ declare global {
17
16
  }
18
17
  }
19
18
  }
19
+ export interface BindSessionOptions {
20
+ userId: string;
21
+ secure?: boolean;
22
+ registrationPath?: string;
23
+ registrationCookieTtl?: number;
24
+ sessionTtl?: number;
25
+ }
26
+ export declare function bindSession(res: Response, sessionId: string, storage: StorageAdapter, opts: BindSessionOptions): Promise<void>;
20
27
  export declare function dbsc(opts: DbscExpressOptions): RequestHandler;
21
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,OAAO,EAiBL,KAAK,WAAW,EAEhB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAW1B,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,MAAM;YACd,IAAI,EAAE,UAAU,CAAC;SAClB;KACF;CACF;AAuBD,wBAAgB,IAAI,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CAqP7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,QAAQ,EAAgB,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,OAAO,EAiBL,KAAK,WAAW,EAChB,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAY1B,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,MAAM;YACd,IAAI,EAAE,UAAU,CAAC;SAClB;KACF;CACF;AAuBD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,QAAQ,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CAwP7D"}
@@ -1,5 +1,4 @@
1
- import { randomBytes as nodeRandomBytes } from "node:crypto";
2
- import { handleRegistration, handleRefresh, issueChallenge, buildChallengeHeader, readSessionResponseHeader, parseSessionSkippedHeader, CHALLENGE_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, DbscProtocolError, DbscVerificationError, } from "../core/index.js";
1
+ import { handleRegistration, handleRefresh, issueChallenge, buildRegistrationHeader, buildChallengeHeader, readSessionResponseHeader, parseSessionSkippedHeader, REGISTRATION_HEADER, CHALLENGE_HEADER, LEGACY_REGISTRATION_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, DbscProtocolError, DbscVerificationError, } from "../core/index.js";
3
2
  const cookieNames = (secure) => ({
4
3
  bound: secure ? "__Host-dbsc-session" : "dbsc-session",
5
4
  reg: secure ? "__Host-dbsc-reg" : "dbsc-reg",
@@ -7,6 +6,7 @@ const cookieNames = (secure) => ({
7
6
  });
8
7
  const DEFAULT_BOUND_TTL = 10 * 60 * 1000;
9
8
  const DEFAULT_REG_TTL = 24 * 60 * 60 * 1000;
9
+ const DEFAULT_SESSION_TTL = 24 * 60 * 60 * 1000;
10
10
  function cookieOpts(ttlMs, secure) {
11
11
  return {
12
12
  httpOnly: true,
@@ -27,9 +27,46 @@ function serializeCookie(name, value, opts) {
27
27
  parts.push(`Path=${opts.path}`);
28
28
  return parts.join("; ");
29
29
  }
30
+ export async function bindSession(res, sessionId, storage, opts) {
31
+ const secure = opts.secure ?? true;
32
+ const registrationPath = opts.registrationPath ?? "/dbsc/registration";
33
+ const regCookieTtl = opts.registrationCookieTtl ?? DEFAULT_REG_TTL;
34
+ const sessionTtl = opts.sessionTtl ?? DEFAULT_SESSION_TTL;
35
+ const COOKIES = cookieNames(secure);
36
+ const existing = await storage.getSession(sessionId);
37
+ const now = Date.now();
38
+ if (!existing) {
39
+ await storage.setSession({
40
+ id: sessionId,
41
+ userId: opts.userId,
42
+ tier: "none",
43
+ createdAt: now,
44
+ expiresAt: now + sessionTtl,
45
+ lastRefreshAt: 0,
46
+ });
47
+ }
48
+ const challenge = await issueChallenge(sessionId, storage);
49
+ const regHeader = buildRegistrationHeader({
50
+ refreshPath: registrationPath,
51
+ challenge: challenge.jti,
52
+ cookieName: COOKIES.bound,
53
+ });
54
+ res.setHeader(REGISTRATION_HEADER, regHeader);
55
+ res.setHeader(LEGACY_REGISTRATION_HEADER, regHeader);
56
+ const prior = res.getHeader("Set-Cookie");
57
+ const priorList = Array.isArray(prior)
58
+ ? prior.map(String)
59
+ : prior !== undefined
60
+ ? [String(prior)]
61
+ : [];
62
+ res.setHeader("Set-Cookie", [
63
+ ...priorList,
64
+ serializeCookie(COOKIES.reg, sessionId, cookieOpts(regCookieTtl, secure)),
65
+ serializeCookie(COOKIES.challenge, challenge.jti, cookieOpts(5 * 60 * 1000, secure)),
66
+ ]);
67
+ }
30
68
  export function dbsc(opts) {
31
- const { storage, fallback = "webauthn", registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundCookieTtl = DEFAULT_BOUND_TTL, registrationCookieTtl = DEFAULT_REG_TTL, rateLimiter = new NoopRateLimiter(), onEvent, secure = true, } = opts;
32
- const hmacSecret = nodeRandomBytes(32);
69
+ const { storage, registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundCookieTtl = DEFAULT_BOUND_TTL, registrationCookieTtl = DEFAULT_REG_TTL, rateLimiter = new NoopRateLimiter(), onEvent, autoBind, secure = true, } = opts;
33
70
  const COOKIES = cookieNames(secure);
34
71
  async function handleRegistrationRoute(req, res) {
35
72
  const ip = req.ip ?? "unknown";
@@ -211,12 +248,6 @@ export function dbsc(opts) {
211
248
  serializeCookie(COOKIES.bound, "", { ...cookieOpts(0, secure), maxAge: 0 }),
212
249
  ]);
213
250
  },
214
- requireBound: () => {
215
- if (!sessionId) {
216
- res.status(401).json({ error: "authentication required" });
217
- throw new Error("unauthenticated");
218
- }
219
- },
220
251
  };
221
252
  if (sessionId) {
222
253
  const session = await storage.getSession(sessionId);
@@ -230,6 +261,17 @@ export function dbsc(opts) {
230
261
  }
231
262
  }
232
263
  }
264
+ else if (autoBind && !(req.cookies?.[COOKIES.reg])) {
265
+ const result = await autoBind(req);
266
+ if (result) {
267
+ await bindSession(res, result.sessionId, storage, {
268
+ userId: result.userId,
269
+ secure,
270
+ registrationPath,
271
+ registrationCookieTtl,
272
+ });
273
+ }
274
+ }
233
275
  next();
234
276
  };
235
277
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,26 @@
1
- import type { FastifyPluginAsync } from "fastify";
1
+ import type { FastifyPluginAsync, FastifyReply } from "fastify";
2
2
  import "@fastify/cookie";
3
- import { type DbscOptions, type ProtectionTier, type SkippedEntry } from "../core/index.js";
3
+ import { type DbscOptions, type StorageAdapter, type ProtectionTier, type SkippedEntry } from "../core/index.js";
4
4
  declare module "fastify" {
5
5
  interface FastifyRequest {
6
6
  dbsc: {
7
7
  sessionId: string | null;
8
8
  tier: ProtectionTier;
9
9
  skipped: SkippedEntry[];
10
- revoke(): Promise<void>;
10
+ revoke: () => Promise<void>;
11
11
  };
12
12
  }
13
13
  }
14
14
  export interface DbscFastifyOptions extends DbscOptions {
15
15
  secure?: boolean;
16
16
  }
17
+ export interface BindSessionOptions {
18
+ userId: string;
19
+ secure?: boolean;
20
+ registrationPath?: string;
21
+ registrationCookieTtl?: number;
22
+ sessionTtl?: number;
23
+ }
24
+ export declare function bindSession(reply: FastifyReply, sessionId: string, storage: StorageAdapter, opts: BindSessionOptions): Promise<void>;
17
25
  export declare const dbsc: FastifyPluginAsync<DbscFastifyOptions>;
18
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAgC,MAAM,SAAS,CAAC;AAEhF,OAAO,iBAAiB,CAAC;AACzB,OAAO,EAaL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,IAAI,EAAE;YACJ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;YACzB,IAAI,EAAE,cAAc,CAAC;YACrB,OAAO,EAAE,YAAY,EAAE,CAAC;YACxB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;SACzB,CAAC;KACH;CACF;AAQD,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAsLD,eAAO,MAAM,IAAI,wCAA2D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fastify/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAkB,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhF,OAAO,iBAAiB,CAAC;AACzB,OAAO,EAgBL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,IAAI,EAAE;YACJ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;YACzB,IAAI,EAAE,cAAc,CAAC;YACrB,OAAO,EAAE,YAAY,EAAE,CAAC;YACxB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;SAC7B,CAAC;KACH;CACF;AAYD,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAoMD,eAAO,MAAM,IAAI,wCAA2D,CAAC"}
@@ -1,21 +1,61 @@
1
1
  import fp from "fastify-plugin";
2
2
  import "@fastify/cookie";
3
- import { handleRegistration, handleRefresh, issueChallenge, buildChallengeHeader, readSessionResponseHeader, parseSessionSkippedHeader, CHALLENGE_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, DbscProtocolError, DbscVerificationError, } from "../core/index.js";
4
- const BOUND_COOKIE = "__Host-dbsc-session";
5
- const REGISTRATION_COOKIE = "__Host-dbsc-reg";
6
- const CHALLENGE_COOKIE = "__Host-dbsc-challenge";
7
- const DEFAULT_BOUND_TTL = 10 * 60;
3
+ import { handleRegistration, handleRefresh, issueChallenge, buildRegistrationHeader, buildChallengeHeader, readSessionResponseHeader, parseSessionSkippedHeader, REGISTRATION_HEADER, CHALLENGE_HEADER, LEGACY_REGISTRATION_HEADER, LEGACY_CHALLENGE_HEADER, NoopRateLimiter, emit, DbscProtocolError, DbscVerificationError, } from "../core/index.js";
4
+ const cookieNames = (secure) => ({
5
+ bound: secure ? "__Host-dbsc-session" : "dbsc-session",
6
+ reg: secure ? "__Host-dbsc-reg" : "dbsc-reg",
7
+ challenge: secure ? "__Host-dbsc-challenge" : "dbsc-challenge",
8
+ });
9
+ const DEFAULT_BOUND_TTL_MS = 10 * 60 * 1000;
10
+ const DEFAULT_REG_TTL_MS = 24 * 60 * 60 * 1000;
11
+ const DEFAULT_SESSION_TTL_MS = 24 * 60 * 60 * 1000;
12
+ export async function bindSession(reply, sessionId, storage, opts) {
13
+ const secure = opts.secure ?? true;
14
+ const registrationPath = opts.registrationPath ?? "/dbsc/registration";
15
+ const regCookieTtl = opts.registrationCookieTtl ?? DEFAULT_REG_TTL_MS;
16
+ const sessionTtl = opts.sessionTtl ?? DEFAULT_SESSION_TTL_MS;
17
+ const existing = await storage.getSession(sessionId);
18
+ const now = Date.now();
19
+ if (!existing) {
20
+ await storage.setSession({
21
+ id: sessionId,
22
+ userId: opts.userId,
23
+ tier: "none",
24
+ createdAt: now,
25
+ expiresAt: now + sessionTtl,
26
+ lastRefreshAt: 0,
27
+ });
28
+ }
29
+ const COOKIES = cookieNames(secure);
30
+ const challenge = await issueChallenge(sessionId, storage);
31
+ const regHeader = buildRegistrationHeader({
32
+ refreshPath: registrationPath,
33
+ challenge: challenge.jti,
34
+ cookieName: COOKIES.bound,
35
+ });
36
+ reply.header(REGISTRATION_HEADER, regHeader);
37
+ reply.header(LEGACY_REGISTRATION_HEADER, regHeader);
38
+ const cookieBase = {
39
+ httpOnly: true,
40
+ secure,
41
+ sameSite: "lax",
42
+ path: "/",
43
+ };
44
+ reply.setCookie(COOKIES.reg, sessionId, { ...cookieBase, maxAge: regCookieTtl / 1000 });
45
+ reply.setCookie(COOKIES.challenge, challenge.jti, { ...cookieBase, maxAge: 5 * 60 });
46
+ }
8
47
  const dbscPlugin = async (fastify, opts) => {
9
- const { storage, registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundCookieTtl = DEFAULT_BOUND_TTL * 1000, rateLimiter = new NoopRateLimiter(), onEvent, secure = true, } = opts;
48
+ const { storage, registrationPath = "/dbsc/registration", refreshPath = "/dbsc/refresh", boundCookieTtl = DEFAULT_BOUND_TTL_MS, registrationCookieTtl = DEFAULT_REG_TTL_MS, rateLimiter = new NoopRateLimiter(), onEvent, autoBind, secure = true, } = opts;
10
49
  const cookieOpts = {
11
50
  httpOnly: true,
12
51
  secure,
13
52
  sameSite: "lax",
14
53
  path: "/",
15
54
  };
55
+ const COOKIES = cookieNames(secure);
16
56
  fastify.decorateRequest("dbsc", null);
17
57
  fastify.addHook("onRequest", async (req, reply) => {
18
- const sessionId = req.cookies?.[BOUND_COOKIE] ?? null;
58
+ const sessionId = req.cookies?.[COOKIES.bound] ?? null;
19
59
  const skipped = parseSessionSkippedHeader(req.headers);
20
60
  req.dbsc = {
21
61
  sessionId,
@@ -24,7 +64,7 @@ const dbscPlugin = async (fastify, opts) => {
24
64
  revoke: async () => {
25
65
  if (sessionId)
26
66
  await storage.revokeSession(sessionId);
27
- reply.clearCookie(BOUND_COOKIE, cookieOpts);
67
+ reply.clearCookie(COOKIES.bound, cookieOpts);
28
68
  },
29
69
  };
30
70
  if (sessionId) {
@@ -39,11 +79,22 @@ const dbscPlugin = async (fastify, opts) => {
39
79
  }
40
80
  }
41
81
  }
82
+ else if (autoBind && !req.cookies?.[COOKIES.reg]) {
83
+ const result = await autoBind(req);
84
+ if (result) {
85
+ await bindSession(reply, result.sessionId, storage, {
86
+ userId: result.userId,
87
+ secure,
88
+ registrationPath,
89
+ registrationCookieTtl,
90
+ });
91
+ }
92
+ }
42
93
  });
43
94
  fastify.post(registrationPath, async (req, reply) => {
44
95
  const ip = req.ip;
45
- const sessionId = req.cookies?.[REGISTRATION_COOKIE];
46
- const expectedJti = req.cookies?.[CHALLENGE_COOKIE];
96
+ const sessionId = req.cookies?.[COOKIES.reg];
97
+ const expectedJti = req.cookies?.[COOKIES.challenge];
47
98
  if (!sessionId || !expectedJti) {
48
99
  return reply.status(400).send({ error: "missing session or challenge cookie" });
49
100
  }
@@ -64,11 +115,11 @@ const dbscPlugin = async (fastify, opts) => {
64
115
  algorithm: "ES256",
65
116
  ip,
66
117
  });
67
- reply.setCookie(BOUND_COOKIE, sessionId, {
118
+ reply.setCookie(COOKIES.bound, sessionId, {
68
119
  ...cookieOpts,
69
120
  maxAge: boundCookieTtl / 1000,
70
121
  });
71
- reply.clearCookie(CHALLENGE_COOKIE, cookieOpts);
122
+ reply.clearCookie(COOKIES.challenge, cookieOpts);
72
123
  const origin = `${req.protocol}://${req.hostname}`;
73
124
  return reply.status(200).send({
74
125
  session_identifier: sessionId,
@@ -81,7 +132,7 @@ const dbscPlugin = async (fastify, opts) => {
81
132
  credentials: [
82
133
  {
83
134
  type: "cookie",
84
- name: BOUND_COOKIE,
135
+ name: COOKIES.bound,
85
136
  attributes: "Path=/; Secure; HttpOnly; SameSite=Lax",
86
137
  },
87
138
  ],
@@ -99,7 +150,7 @@ const dbscPlugin = async (fastify, opts) => {
99
150
  const ip = req.ip;
100
151
  const sessionIdHeader = req.headers["sec-secure-session-id"];
101
152
  const sessionId = (Array.isArray(sessionIdHeader) ? sessionIdHeader[0] : sessionIdHeader) ??
102
- req.cookies?.[BOUND_COOKIE];
153
+ req.cookies?.[COOKIES.bound];
103
154
  if (!sessionId)
104
155
  return reply.status(403).send();
105
156
  const allowed = await rateLimiter.checkRefresh(ip, sessionId);
@@ -110,15 +161,15 @@ const dbscPlugin = async (fastify, opts) => {
110
161
  const challenge = await issueChallenge(sessionId, storage);
111
162
  reply.header(CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
112
163
  reply.header(LEGACY_CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
113
- reply.setCookie(CHALLENGE_COOKIE, challenge.jti, { ...cookieOpts, maxAge: 5 * 60 });
164
+ reply.setCookie(COOKIES.challenge, challenge.jti, { ...cookieOpts, maxAge: 5 * 60 });
114
165
  return reply.status(403).send();
115
166
  }
116
- const expectedJti = req.cookies?.[CHALLENGE_COOKIE];
167
+ const expectedJti = req.cookies?.[COOKIES.challenge];
117
168
  if (!expectedJti) {
118
169
  const challenge = await issueChallenge(sessionId, storage);
119
170
  reply.header(CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
120
171
  reply.header(LEGACY_CHALLENGE_HEADER, buildChallengeHeader(challenge.jti, sessionId));
121
- reply.setCookie(CHALLENGE_COOKIE, challenge.jti, { ...cookieOpts, maxAge: 5 * 60 });
172
+ reply.setCookie(COOKIES.challenge, challenge.jti, { ...cookieOpts, maxAge: 5 * 60 });
122
173
  return reply.status(403).send();
123
174
  }
124
175
  try {
@@ -130,8 +181,8 @@ const dbscPlugin = async (fastify, opts) => {
130
181
  timestamp: Date.now(),
131
182
  ip,
132
183
  });
133
- reply.setCookie(BOUND_COOKIE, sessionId, { ...cookieOpts, maxAge: boundCookieTtl / 1000 });
134
- reply.clearCookie(CHALLENGE_COOKIE, cookieOpts);
184
+ reply.setCookie(COOKIES.bound, sessionId, { ...cookieOpts, maxAge: boundCookieTtl / 1000 });
185
+ reply.clearCookie(COOKIES.challenge, cookieOpts);
135
186
  const origin = `${req.protocol}://${req.hostname}`;
136
187
  return reply.status(200).send({
137
188
  session_identifier: sessionId,
@@ -144,7 +195,7 @@ const dbscPlugin = async (fastify, opts) => {
144
195
  credentials: [
145
196
  {
146
197
  type: "cookie",
147
- name: BOUND_COOKIE,
198
+ name: COOKIES.bound,
148
199
  attributes: "Path=/; Secure; HttpOnly; SameSite=Lax",
149
200
  },
150
201
  ],