Passkeys: one-time invite codes to enrol another device
build-container / build (push) Successful in 2m14s
build-container / build (push) Successful in 2m14s
A signed-in device creates a short-lived, single-use code in Settings
("Invite a device"); the new device enters it on the sign-in page to create
its own passkey. Codes are throttled like other secrets and cannot be used
by signed-out clients to create more codes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e8b46bb3aa
commit
6ec98d2527
4 files changed
+58
-12
No files matched your search
+9
-1
@@ -779,7 +779,7 @@ function viewSettings() {
|
||||
const signed = !!sf.token();
|
||||
$('#view').innerHTML = `<div class="wrap"><h1>Settings</h1>
|
||||
<h2>Passkeys</h2><div class="list" id="pks"><div class="row"><span class="grow"><small>Loading…</small></span></div></div>
|
||||
<div class="bar"><button class="btn ghost" id="addpk">Add a passkey</button><button class="btn danger" id="hubout">Sign out of NE Hub</button></div>
|
||||
<div class="bar"><button class="btn ghost" id="addpk">Add a passkey</button><button class="btn ghost" id="invpk">Invite a device</button><button class="btn danger" id="hubout">Sign out of NE Hub</button></div>
|
||||
<h2>Connections</h2><div class="list">
|
||||
<div class="row"><span class="grow"><b>Seafile</b><small>${esc(cfg.seafile)} · ${signed ? 'signed in' : 'signed out'}</small></span></div>
|
||||
<div class="row"><span class="grow"><b>Plex</b><small id="plexst">Checking…</small></span><button class="btn danger" id="plexout" hidden>Sign out</button></div>
|
||||
@@ -820,6 +820,14 @@ function viewSettings() {
|
||||
$('#addpk').onclick = () => textSheet('Add a passkey', 'Name this device', 'Create', async name => {
|
||||
try { await passkeyRegister('', name); toast('Passkey added'); loadPks(); } catch (e) { toast(e.name === 'NotAllowedError' ? 'Cancelled' : e.message); }
|
||||
});
|
||||
$('#invpk').onclick = async () => {
|
||||
try {
|
||||
const { code, minutes } = await authPost('/api/auth/invite');
|
||||
const el = openSheet('Invite a device', 'On the new device, open this app, tap "New device? Use an invite code", and enter:', `<p style="font:700 34px ui-monospace,monospace;letter-spacing:.08em;text-align:center;margin:16px 0">${esc(code)}</p>
|
||||
<p class="sub" style="text-align:center">Works once, and expires in ${minutes} minutes.</p><div class="bar"><button class="btn ghost" id="sx" style="flex:1;justify-content:center">Done</button></div>`);
|
||||
el.querySelector('#sx').onclick = closeSheet;
|
||||
} catch (e) { toast(e.message); }
|
||||
};
|
||||
$('#hubout').onclick = async () => { await authPost('/api/auth/logout'); location.replace('/login'); };
|
||||
const out = $('#out'); if (out) out.onclick = () => { store.del('sf_token'); toast('Signed out'); viewSettings(); };
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user