@djangocfg/monitor 2.1.427 → 2.1.428

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/dist/server.mjs CHANGED
@@ -294,6 +294,99 @@ async function tryRefresh() {
294
294
  return _refreshInflight;
295
295
  }
296
296
  __name(tryRefresh, "tryRefresh");
297
+ function dpopEnabled() {
298
+ try {
299
+ return typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DPOP_ENABLED === "true";
300
+ } catch {
301
+ return false;
302
+ }
303
+ }
304
+ __name(dpopEnabled, "dpopEnabled");
305
+ var _DPOP_DB = "cfg-auth";
306
+ var _DPOP_STORE = "keys";
307
+ var _DPOP_KEY_ID = "dpop-ec-p256";
308
+ function _idbOpen() {
309
+ return new Promise((resolve, reject) => {
310
+ const req = indexedDB.open(_DPOP_DB, 1);
311
+ req.onupgradeneeded = () => req.result.createObjectStore(_DPOP_STORE);
312
+ req.onsuccess = () => resolve(req.result);
313
+ req.onerror = () => reject(req.error);
314
+ });
315
+ }
316
+ __name(_idbOpen, "_idbOpen");
317
+ function _idbGet(key) {
318
+ return _idbOpen().then((db) => new Promise((resolve, reject) => {
319
+ const tx = db.transaction(_DPOP_STORE, "readonly");
320
+ const req = tx.objectStore(_DPOP_STORE).get(key);
321
+ req.onsuccess = () => resolve(req.result);
322
+ req.onerror = () => reject(req.error);
323
+ }));
324
+ }
325
+ __name(_idbGet, "_idbGet");
326
+ function _idbPut(key, value) {
327
+ return _idbOpen().then((db) => new Promise((resolve, reject) => {
328
+ const tx = db.transaction(_DPOP_STORE, "readwrite");
329
+ tx.objectStore(_DPOP_STORE).put(value, key);
330
+ tx.oncomplete = () => resolve();
331
+ tx.onerror = () => reject(tx.error);
332
+ }));
333
+ }
334
+ __name(_idbPut, "_idbPut");
335
+ var _dpopKeyPromise = null;
336
+ function _getDpopKeyPair() {
337
+ if (_dpopKeyPromise) return _dpopKeyPromise;
338
+ _dpopKeyPromise = (async () => {
339
+ const existing = await _idbGet(_DPOP_KEY_ID).catch(() => void 0);
340
+ if (existing) return existing;
341
+ const pair = await crypto.subtle.generateKey(
342
+ { name: "ECDSA", namedCurve: "P-256" },
343
+ false,
344
+ // extractable:false — JS can sign but never export the private key
345
+ ["sign"]
346
+ );
347
+ await _idbPut(_DPOP_KEY_ID, pair).catch(() => {
348
+ });
349
+ return pair;
350
+ })();
351
+ return _dpopKeyPromise;
352
+ }
353
+ __name(_getDpopKeyPair, "_getDpopKeyPair");
354
+ function _b64urlFromBytes(bytes) {
355
+ const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
356
+ let s = "";
357
+ for (let i = 0; i < arr.length; i++) s += String.fromCharCode(arr[i]);
358
+ return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
359
+ }
360
+ __name(_b64urlFromBytes, "_b64urlFromBytes");
361
+ function _b64urlFromString(str) {
362
+ return _b64urlFromBytes(new TextEncoder().encode(str));
363
+ }
364
+ __name(_b64urlFromString, "_b64urlFromString");
365
+ async function _publicJwk(pub) {
366
+ const jwk = await crypto.subtle.exportKey("jwk", pub);
367
+ return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y };
368
+ }
369
+ __name(_publicJwk, "_publicJwk");
370
+ async function _makeDpopProof(method, url) {
371
+ try {
372
+ const pair = await _getDpopKeyPair();
373
+ const jwk = await _publicJwk(pair.publicKey);
374
+ const header = { typ: "dpop+jwt", alg: "ES256", jwk };
375
+ const htu = url.split("#")[0].split("?")[0];
376
+ const jti = crypto.randomUUID && crypto.randomUUID() || _b64urlFromBytes(crypto.getRandomValues(new Uint8Array(16)));
377
+ const payload = { htm: method.toUpperCase(), htu, iat: Math.floor(Date.now() / 1e3), jti };
378
+ const signingInput = `${_b64urlFromString(JSON.stringify(header))}.${_b64urlFromString(JSON.stringify(payload))}`;
379
+ const sig = await crypto.subtle.sign(
380
+ { name: "ECDSA", hash: "SHA-256" },
381
+ pair.privateKey,
382
+ new TextEncoder().encode(signingInput)
383
+ );
384
+ return `${signingInput}.${_b64urlFromBytes(sig)}`;
385
+ } catch {
386
+ return null;
387
+ }
388
+ }
389
+ __name(_makeDpopProof, "_makeDpopProof");
297
390
  function installAuthOnClient(client2) {
298
391
  if (_client) return;
299
392
  _client = client2;
@@ -301,7 +394,7 @@ function installAuthOnClient(client2) {
301
394
  baseUrl: auth.getBaseUrl(),
302
395
  credentials: _withCredentials ? "include" : "same-origin"
303
396
  });
304
- client2.interceptors.request.use((request) => {
397
+ client2.interceptors.request.use(async (request) => {
305
398
  const token = auth.getToken();
306
399
  if (token) request.headers.set("Authorization", `Bearer ${token}`);
307
400
  const locale = auth.getLocale();
@@ -314,6 +407,10 @@ function installAuthOnClient(client2) {
314
407
  } catch {
315
408
  }
316
409
  request.headers.set("X-Client-Time", (/* @__PURE__ */ new Date()).toISOString());
410
+ if (dpopEnabled() && typeof window !== "undefined") {
411
+ const proof = await _makeDpopProof(request.method, request.url);
412
+ if (proof) request.headers.set("DPoP", proof);
413
+ }
317
414
  return request;
318
415
  });
319
416
  client2.interceptors.error.use((err, res, req) => {
@@ -347,6 +444,10 @@ function installAuthOnClient(client2) {
347
444
  const retry = request.clone();
348
445
  retry.headers.set("Authorization", `Bearer ${newToken}`);
349
446
  retry.headers.set(RETRY_MARKER, "1");
447
+ if (dpopEnabled() && typeof window !== "undefined") {
448
+ const proof = await _makeDpopProof(retry.method, retry.url);
449
+ if (proof) retry.headers.set("DPoP", proof);
450
+ }
350
451
  try {
351
452
  const retried = await fetch(retry);
352
453
  if (retried.status === 401 && _onUnauthorized) {