Passkeys (WebAuthn / FIDO2)
Monetro supports passwordless authentication using Passkeys — powered by the WebAuthn standard (FIDO2). Users can sign in with Touch ID, Face ID, Windows Hello, or hardware security keys like YubiKey.
Prerequisites
- HTTPS connection (Passkeys do not work over HTTP)
- Browser with WebAuthn support (Chrome 67+, Safari 14+, Firefox 60+)
- Platform authenticator (Touch ID, Face ID, Windows Hello) or hardware key (YubiKey)
Register a Passkey
- Go to Settings > Security > Passkeys
- Enter an optional name (e.g., "MacBook Touch ID")
- Click "Add Passkey"
- Confirm the browser dialog (Touch ID / Face ID / PIN)
The passkey is now stored in your browser and on the Monetro server.
Sign In with Passkey
- Open the login page
- Click "Sign in with Passkey" (only visible if a passkey has been registered)
- Confirm the browser dialog
No password or 2FA code needed — the passkey is your full authentication.
Delete a Passkey
You must delete the passkey in both places:
- In Monetro: Settings > Security > click "Remove" next to the passkey entry
- In your browser/OS: macOS > System Preferences > Passwords > search "monetro" > delete
caution
Always delete in both places. A passkey that exists only in your browser (but not on the server) will fail silently on login.
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/auth/passkey/register-options | Get registration challenge |
POST | /api/auth/passkey/register | Store new passkey |
POST | /api/auth/passkey/authenticate-options | Get login challenge |
POST | /api/auth/passkey/authenticate | Login with passkey (returns JWT) |
GET | /api/auth/passkey/list | List all passkeys for current user |
DELETE | /api/auth/passkey/:id | Delete a passkey |
Troubleshooting
| Error | Cause | Solution |
|---|---|---|
| "WebAuthn is not supported on sites with TLS certificate errors" | Invalid or expired SSL certificate | Renew certificate (Traefik / Let's Encrypt) |
| "Registration was cancelled or blocked by the browser" | NotAllowedError from browser | Don't cancel the browser dialog; ensure no other dialog is open |
| "Unknown Passkey" (PASSKEY_NOT_FOUND) | Passkey exists in browser but not in database | Delete the old passkey from your browser, register a new one |
| Backend returns 502 on passkey login | Backend container is down | Redeploy backend in Dokploy |
| "expected https:// got http://" | Trust proxy not configured | Ensure app.set('trust proxy', 1) is set in Express |