aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/keyderive.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/keyderive.js24
1 files changed, 19 insertions, 5 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js b/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
index 9f28b5c..6bd5896 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
@@ -195,14 +195,25 @@ async function nodeBundleKey(sessionKey, nodePkB64) {
}
/**
- * GET the pepper for a session that is already open — a stored session from
- * before the pepper existed, a passphrase change. Sign-in carries it already.
+ * The pepper for a session that is already open but lacks the key derived from
+ * it — a restored session, a passphrase change. Sign-in carries it already. The
+ * hub asks for the passphrase proof: a token alone never obtains the pepper.
*/
-async function fetchBundlePepper(token) {
+async function fetchBundlePepper(token, authKey) {
const resp = await hubCall('/v1/users/me/bundle-pepper', {
- headers: { Authorization: `Bearer ${token}` },
+ method: 'POST',
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
+ body: JSON.stringify({ auth_key: authKey }),
});
- if (!resp.ok) throw new Error(`bundle pepper: ${resp.status}`);
+ if (!resp.ok) {
+ // The hub's own words: a wrong passphrase and a locked account are what a
+ // person can act on, a bare status is not.
+ let detail = `bundle pepper: ${resp.status}`;
+ try { const j = await resp.json(); detail = j.detail || j.error || detail; } catch { /* not JSON */ }
+ const err = new Error(String(detail));
+ err.status = resp.status;
+ throw err;
+ }
const data = await resp.json();
return { pepper: data.bundle_pepper, version: data.bundle_pepper_version };
}
@@ -446,6 +457,9 @@ async function loginAndRecover(username, password) {
const result = {
accessToken: data.access_token,
refreshToken: data.refresh_token,
+ // Kept for the one call that follows a sign-in and must prove the
+ // passphrase again: registering this device's key. Not stored.
+ authKey,
// The pepper rides on the sign-in response, so this costs no extra call;
// it is folded into the key here and not kept.
bundleKey: await sessionBundleKey(