diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-14 23:02:49 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-14 23:02:49 +0200 |
| commit | 3131630d900aa4a72bf880bfa9c5232bff64d6d6 (patch) | |
| tree | 5ef229f9a3f589fad6e7543f14b58ec7f9526758 /packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js | |
| parent | 422647e7898b8df67cd11f8fb060aec23dec84aa (diff) | |
| download | meshbay-3131630d900aa4a72bf880bfa9c5232bff64d6d6.tar.gz | |
fix(client): link a device from the application; approve one match only
"Get a linking code" called the connection the page had just closed on the
node's unknown_device refusal, so it never filed anything. It now retries
with the request filed on that connection, before the proof (MNP 6.3), and
the page tries the group again after each refusal until a linked device
approves the code. Offered only in the desktop application: a browser's
minted identity is gone by its next connection.
Approving refuses a code that matches more than one pending request:
filing needs only the account's token, so somebody holding the passphrase
who saw a code could file their own keys under it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js b/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js index 3d56f69b..5c6adef4 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js @@ -227,15 +227,24 @@ extendTransport(class { const listed = await this._sendAndWait({ type: 'device_lookup', v: '0.1' }); if (listed.type === 'error') throw new Error(listed.detail || 'Not found'); - let match = null; + // Every match, not the first: a request is filed with the account's token + // alone, so somebody holding the passphrase who saw the code on screen can + // file a second one with the same code and keys of their own. Neither is + // approved then — the person's device asks again, with a new code. + const matches = []; for (const req of listed.requests || []) { const expect = await C.deviceCodeHash( normalized, req.pk_ed25519, req.pk_x25519); - if (expect === req.code_hash) { match = req; break; } + if (expect === req.code_hash) matches.push(req); } - if (!match) { + if (!matches.length) { throw new Error('No device is waiting with that code'); } + if (matches.length > 1) { + throw new Error('More than one device is waiting with that code, so none was ' + + 'approved. Get a new code on the device you are linking.'); + } + const match = matches[0]; return this._countersign(userId, match.code_hash, match.pk_ed25519, match.pk_x25519); } |