fedipod 1.57.0 → 1.57.5

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.
@@ -34591,49 +34591,89 @@ function solidOidcSession({ dbName = "solid-oidc-session", clientName = "Solid a
34591
34591
  await idbDel("session");
34592
34592
  await idbDel("pending");
34593
34593
  }
34594
- function sessionHandle(s) {
34595
- let { accessToken, expiresAt, refreshToken } = s;
34596
- const jwkP = publicJwk(s.pair);
34597
- const refresh = async () => {
34598
- if (!refreshToken) throw new Error("session expired and there is no refresh token \u2014 sign in again");
34594
+ const ended = (message) => Object.assign(new Error(message), { signedOut: true });
34595
+ const stillGood = (row) => Date.now() < row.expiresAt - 3e4;
34596
+ const locks = () => globalThis.navigator?.locks;
34597
+ const oneAtATime = (fn) => locks()?.request ? locks().request(`${dbName}:renew`, fn) : fn();
34598
+ const RACE_WAIT_MS = 1500;
34599
+ function sessionHandle(first) {
34600
+ let s = first;
34601
+ let jwkP = publicJwk(s.pair);
34602
+ const host = () => new URL(s.tokenEndpoint).host;
34603
+ const takeUp = (row) => {
34604
+ s = row;
34605
+ jwkP = publicJwk(row.pair);
34606
+ };
34607
+ const reread = async () => {
34608
+ const row = await idbGet("session");
34609
+ if (!row) throw ended("signed out \u2014 sign in again");
34610
+ if (row.webId !== s.webId) throw new Error("signed in as somebody else since this session was read");
34611
+ takeUp(row);
34612
+ };
34613
+ const refresh = () => oneAtATime(async () => {
34614
+ const mine = s.accessToken;
34615
+ await reread();
34616
+ if (s.accessToken !== mine && stillGood(s)) return;
34617
+ if (!s.refreshToken) {
34618
+ await idbDel("session");
34619
+ throw ended("session expired and there is no refresh token \u2014 sign in again");
34620
+ }
34621
+ const sent = s;
34599
34622
  const jwk = await jwkP;
34600
34623
  let res;
34601
34624
  try {
34602
- res = await fetch(s.tokenEndpoint, {
34625
+ res = await fetch(sent.tokenEndpoint, {
34603
34626
  method: "POST",
34604
- headers: { "content-type": "application/x-www-form-urlencoded", dpop: await dpopProof(s.pair, jwk, "POST", s.tokenEndpoint) },
34605
- body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: refreshToken, client_id: s.client_id, scope: "openid webid offline_access" })
34627
+ headers: { "content-type": "application/x-www-form-urlencoded", dpop: await dpopProof(sent.pair, jwk, "POST", sent.tokenEndpoint) },
34628
+ body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: sent.refreshToken, client_id: sent.client_id, scope: "openid webid offline_access" })
34606
34629
  });
34607
34630
  } catch (e) {
34608
- throw new Error(`${e.message} \u2014 renewing your sign-in at ${new URL(s.tokenEndpoint).host}`);
34631
+ throw new Error(`${e.message} \u2014 renewing your sign-in at ${host()}`);
34609
34632
  }
34610
34633
  const tok = await res.json().catch(() => ({}));
34634
+ const now = await idbGet("session");
34635
+ if (now && now.webId !== sent.webId) throw new Error("signed in as somebody else while this session was refreshing");
34636
+ if (res.ok && tok.access_token) {
34637
+ if (!now) throw ended("signed out while this sign-in was being renewed");
34638
+ takeUp({
34639
+ ...sent,
34640
+ accessToken: tok.access_token,
34641
+ refreshToken: tok.refresh_token || sent.refreshToken,
34642
+ expiresAt: Date.now() + Math.max(30, tok.expires_in || 300) * 1e3
34643
+ });
34644
+ await idbPut("session", s);
34645
+ return;
34646
+ }
34611
34647
  if (res.status === 429) {
34612
- throw new Error(`${new URL(s.tokenEndpoint).host} is asking us to slow down \u2014 your sign-in could not be renewed just now`);
34648
+ throw new Error(`${host()} is asking us to slow down \u2014 your sign-in could not be renewed just now`);
34613
34649
  }
34614
- if (!res.ok || !tok.access_token) {
34650
+ if (res.status >= 400 && res.status < 500 && typeof tok.error === "string") {
34651
+ let row = now;
34652
+ if (row && row.accessToken === sent.accessToken && !locks()?.request) {
34653
+ await new Promise((r) => setTimeout(r, RACE_WAIT_MS));
34654
+ row = await idbGet("session");
34655
+ }
34656
+ if (row && row.webId === sent.webId && row.accessToken !== sent.accessToken && stillGood(row)) {
34657
+ takeUp(row);
34658
+ return;
34659
+ }
34660
+ if (!row) throw ended("signed out \u2014 sign in again");
34615
34661
  await idbDel("session");
34616
- throw new Error("refresh failed \u2014 sign in again");
34617
- }
34618
- accessToken = tok.access_token;
34619
- expiresAt = Date.now() + Math.max(30, tok.expires_in || 300) * 1e3;
34620
- if (tok.refresh_token) refreshToken = tok.refresh_token;
34621
- const now = await idbGet("session");
34622
- if (now && now.webId !== s.webId) {
34623
- throw new Error("signed in as somebody else while this session was refreshing");
34662
+ throw ended("refresh failed \u2014 sign in again");
34624
34663
  }
34625
- await idbPut("session", { ...s, accessToken, expiresAt, refreshToken });
34626
- };
34664
+ throw new Error(`${host()} could not renew your sign-in just now (HTTP ${res.status})`);
34665
+ });
34627
34666
  const send = async (url, init) => {
34667
+ const { accessToken, pair } = s;
34628
34668
  const jwk = await jwkP;
34629
34669
  const ath = b64u(await sha2562(accessToken));
34630
- const headers = { ...init.headers || {}, authorization: `DPoP ${accessToken}`, dpop: await dpopProof(s.pair, jwk, init.method || "GET", url, ath) };
34670
+ const headers = { ...init.headers || {}, authorization: `DPoP ${accessToken}`, dpop: await dpopProof(pair, jwk, init.method || "GET", url, ath) };
34631
34671
  return fetch(url, { ...init, headers });
34632
34672
  };
34633
34673
  const authFetch = async (url, init = {}) => {
34634
- if (Date.now() > expiresAt - 3e4) await refresh();
34674
+ if (!stillGood(s)) await refresh();
34635
34675
  const res = await send(url, init);
34636
- if (res.status === 401 && refreshToken) {
34676
+ if (res.status === 401 && s.refreshToken) {
34637
34677
  try {
34638
34678
  await refresh();
34639
34679
  } catch {
@@ -34643,7 +34683,17 @@ function solidOidcSession({ dbName = "solid-oidc-session", clientName = "Solid a
34643
34683
  }
34644
34684
  return res;
34645
34685
  };
34646
- return { webId: s.webId, issuer: s.issuer, fetch: authFetch, refresh, signOut: signOut2 };
34686
+ const check = async () => {
34687
+ try {
34688
+ await reread();
34689
+ if (!stillGood(s)) await refresh();
34690
+ return true;
34691
+ } catch (e) {
34692
+ if (e.signedOut) return false;
34693
+ throw e;
34694
+ }
34695
+ };
34696
+ return { webId: first.webId, issuer: first.issuer, fetch: authFetch, refresh, check, signOut: signOut2 };
34647
34697
  }
34648
34698
  return { beginLogin: beginLogin2, completeLogin: completeLogin2, getSession: getSession2, signOut: signOut2 };
34649
34699
  }
@@ -34836,11 +34886,18 @@ window.fedipodOnLoad = async () => {
34836
34886
  await bootWorker({ reset: true });
34837
34887
  return "signed-in";
34838
34888
  }
34839
- if (await getSession()) {
34840
- await bootWorker();
34841
- return "restored";
34889
+ const kept = await getSession();
34890
+ if (!kept) return "anonymous";
34891
+ if (await kept.check().catch(() => true) === false) {
34892
+ try {
34893
+ location.href = (await beginLogin({ issuer: kept.issuer, redirectUri: REDIRECT })).authorizationUrl;
34894
+ return "leaving";
34895
+ } catch {
34896
+ return "anonymous";
34897
+ }
34842
34898
  }
34843
- return "anonymous";
34899
+ await bootWorker();
34900
+ return "restored";
34844
34901
  };
34845
34902
  window.fedipodSignOut = async () => {
34846
34903
  await signOut();
@@ -34943,6 +35000,7 @@ if (typeof document !== "undefined") (async () => {
34943
35000
  };
34944
35001
  const known = {
34945
35002
  "sign-in-refused": { title: "Your pod refused this sign-in", retry: "Sign in again", go: signIn },
35003
+ "signed-out": { title: "Your sign-in has ended", retry: "Sign in again", go: signIn },
34946
35004
  "pod-busy": { title: "Your pod is asking for a pause", retry: "Reload", go: reload, wait: 45 },
34947
35005
  "pod-error": { title: "Your pod had an error", retry: "Reload", go: reload, wait: 20 },
34948
35006
  "pod-unreachable": { title: "Your pod could not be reached", retry: "Reload", go: reload, wait: 20 },
@@ -35018,6 +35076,7 @@ ${e.detail}` : "");
35018
35076
  });
35019
35077
  return;
35020
35078
  }
35079
+ if (state === "leaving") return;
35021
35080
  if (state === "signed-in" || state === "restored") {
35022
35081
  location.href = "/admin/client/";
35023
35082
  return;