Skip to content

Add multi-device WebAuthN support#120

Merged
julianlam merged 10 commits into
masterfrom
multi-webauthn
May 25, 2026
Merged

Add multi-device WebAuthN support#120
julianlam merged 10 commits into
masterfrom
multi-webauthn

Conversation

@julianlam
Copy link
Copy Markdown
Member

@julianlam julianlam commented May 22, 2026

  • Backend: add getAuthnDevices, removeDevice, renameDevice methods
  • API routes: GET/DELETE/PATCH /2factor/authn/device endpoints
  • Registration: prompt for device name, store in Redis hash
  • Login: device selection dropdown when multiple devices exist
  • Settings: device list with rename/remove buttons
  • Templates: login-authn device selection, 2factor device container
  • Translations: 8 new keys across all 8 language directories

Assisted-by: unsloth/Qwen3.6-35B-A3B-GGUF

AI Summary All changes are complete. Here's a summary of what was implemented:

Summary of Multi-Device WebAuthN Support

Backend Changes (library.js)

  • getAuthnDevices(uid): Returns array of {id, name} objects by merging key IDs with device names from Redis
  • saveAuthn(uid, authnrData, deviceName): Now accepts optional deviceName parameter, stored in 2factor:webauthn:${uid}:names hash
  • removeDevice(uid, id): Removes single device from both credentials and names storage
  • renameDevice(uid, id, newName): Updates device name in the names hash
  • disassociate(uid): Now also clears the names hash
  • 3 new API routes:
    • GET /2factor/authn/devices - list all devices
    • PATCH /2factor/authn/device - rename device (body: {id, name})
    • DELETE /2factor/authn/device/:id - remove single device
  • Updated POST /2factor/authn/register to accept optional deviceName in request body

Controller Changes (lib/controllers.js)

  • renderAuthnChallenge now fetches full device list and passes it to the template

Frontend Changes

  • static/lib/settings.js: Device management UI with rename/remove buttons, prompts for device name during registration, renders device list on page load
  • static/lib/authn.js: Handles device selection during login - when multiple devices exist, shows dropdown; otherwise proceeds directly
  • static/templates/login-authn.tpl: Device selection dropdown for multiple devices, auto-assertion for single device
  • static/templates/account/2factor.tpl: Added device list container

Translations (languages/*/2factor.json)

Added 8 new keys:

  • authn.register.prompt, authn.login.select, authn.rename, authn.rename.prompt
  • authn.renamed, authn.remove, authn.remove.confirm, authn.removed

Updated in all 8 language directories (en-GB, fa-IR, fr, it, ko, pl, ru, zh-CN).

julianlam added 10 commits May 22, 2026 15:26
- Backend: add getAuthnDevices, removeDevice, renameDevice methods
- API routes: GET/DELETE/PATCH /2factor/authn/device endpoints
- Registration: prompt for device name, store in Redis hash
- Login: device selection dropdown when multiple devices exist
- Settings: device list with rename/remove buttons
- Templates: login-authn device selection, 2factor device container
- Translations: 8 new keys across all 8 language directories

Assisted-by: unsloth/Qwen3.6-35B-A3B-GGUF
Upgrade fido2-lib from ^2.8.1 to ^3.5.8, which removes the vulnerable
elliptic dependency chain (fido2-lib → jwk-to-pem → elliptic).
The public API is unchanged so no code modifications needed.

Assisted-by: unsloth/Qwen3.6-35B-A3B-GGUF
- Pass devices array from renderSettings to template
- Add device list partial for server-side and client-side rendering
- Replace JS-built HTML string in renderDevicesList with app.parseAndTranslate
- Device list markup now lives in templates, not client-side JS
db.getObjectKeys was called on the sorted set key
2factor:webauthn:counters instead of the hash key — Redis throws
WRONGTYPE. db.sortedSetRemove is idempotent so the check is unnecessary.
- Remove mute condition on the enable button when a key already exists
- Add 'authn.add' translation key for 'Add key' label shown when
  hasAuthn is true
- Users can now register additional hardware keys alongside existing ones
@julianlam julianlam marked this pull request as ready for review May 25, 2026 17:41
@julianlam julianlam merged commit b7b3f33 into master May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant