|
| 1 | +# Sign in with passkeys |
| 2 | + |
| 3 | +Passkeys let you sign in to Sable using your device's fingerprint reader, face |
| 4 | +recognition, PIN, or a FIDO2 security key, without entering a username or password. |
| 5 | +They are enabled by default and work on **standalone servers and clusters**. |
| 6 | +Passwords, OpenID Connect (OIDC), and passkeys can all be available together. |
| 7 | + |
| 8 | +Sable stores the credential's public key. The private key stays with your device |
| 9 | +or passkey provider. Passkeys use normal Sable browser sessions and account |
| 10 | +permissions; they do not replace API tokens. |
| 11 | + |
| 12 | +## Before you begin |
| 13 | + |
| 14 | +- Enable console authentication and complete initial administrator setup with a |
| 15 | + password. You can make that password optional after adding a passkey. |
| 16 | +- Access Sable through a stable HTTPS DNS hostname with a certificate trusted by |
| 17 | + your browser. A standalone server uses its configured HTTPS identities; no |
| 18 | + cluster or separate passkey configuration is required. |
| 19 | +- Use a browser and authenticator that support passkeys and device verification. |
| 20 | + Sable requires a discoverable credential and verification with a fingerprint, |
| 21 | + face, device PIN, or security-key PIN. |
| 22 | + |
| 23 | +Ordinary HTTP connections cannot register or use passkeys. The sign-in button, |
| 24 | +registration name field, and Add passkey button stay hidden when the browser |
| 25 | +lacks a secure context or the WebAuthn API. `http://localhost` is supported for |
| 26 | +local development. Access by IP address is not supported for passkey enrollment |
| 27 | +or sign-in, even when HTTPS is available. |
| 28 | + |
| 29 | +## Add and use a passkey |
| 30 | + |
| 31 | +1. Sign in with your password or OIDC provider. |
| 32 | +2. Open **Profile → Account**. The **Passkeys** card is below Account details and |
| 33 | + above Password. |
| 34 | +3. Enter a descriptive name, such as “Personal phone,” and select **Add passkey**. |
| 35 | +4. Complete your browser's prompt to save the passkey. |
| 36 | +5. Sign out and select **Sign in with a passkey** to test it. |
| 37 | + |
| 38 | +Each account can have up to 20 passkeys. The list shows the name, domain, |
| 39 | +creation time, and last use. Select **Remove** and confirm in Sable's dialog to |
| 40 | +remove a saved credential. Removing it from Sable prevents it from being used |
| 41 | +for that account; it does not delete the entry from your device's passkey manager. |
| 42 | + |
| 43 | +On a standalone server, manage passkeys directly on that server. In a cluster, |
| 44 | +register and remove them on the primary. Replicas can accept passkey sign-ins |
| 45 | +after receiving the credential through replication. |
| 46 | + |
| 47 | +## Disable or re-enable password sign-in |
| 48 | + |
| 49 | +After adding and testing a passkey, select **Disable password sign-in** on the |
| 50 | +right side of the **Password** card header and confirm. Your existing password |
| 51 | +is retained but cannot be used to sign in. Linked OIDC accounts remain available. |
| 52 | + |
| 53 | +To restore the same password, sign in with a passkey or OIDC and select |
| 54 | +**Enable password sign-in** in the Password header. Confirm the change; no |
| 55 | +password reset is required. |
| 56 | + |
| 57 | +You can instead fill in New Password and Confirm New Password and select |
| 58 | +**Set new password and enable sign-in**. Setting a new password enables password |
| 59 | +sign-in and signs out existing browser sessions. An account that never had a |
| 60 | +password must set one before it can use password sign-in. |
| 61 | + |
| 62 | +First-run administrator setup and locally created accounts start with a |
| 63 | +password. Accounts provisioned through OIDC can add passkeys without ever |
| 64 | +setting a password. |
| 65 | + |
| 66 | +Keep a backup passkey or a tested recovery administrator before disabling your |
| 67 | +password. Sable refuses to remove your final passkey while password sign-in is |
| 68 | +disabled. When disabling a password, it also requires an active administrator |
| 69 | +with password or passkey access so recovery does not depend entirely on an |
| 70 | +external identity provider. If you lose access to your authenticators, another |
| 71 | +administrator can reset your password and enable password sign-in through |
| 72 | +Administration. |
| 73 | + |
| 74 | +## Administrator setting |
| 75 | + |
| 76 | +Open **Settings → Web → Passkeys**, change **Enable passkeys**, then select |
| 77 | +**Save Settings**. Changing the switch alone does not save it. |
| 78 | + |
| 79 | +Turning it off hides passkey sign-in and enrollment and rejects both new and |
| 80 | +in-progress passkey ceremonies. Saved credentials remain in place for later |
| 81 | +re-enabling, and they can still be removed from Profile. Password and OIDC |
| 82 | +sign-in continue to work when enabled for the account. |
| 83 | + |
| 84 | +The settings form refuses to disable passkeys if an active account has neither |
| 85 | +an enabled password nor a link to the currently enabled OIDC issuer. A link to |
| 86 | +a different or disabled provider does not count as an alternative. |
| 87 | + |
| 88 | +The setting takes effect without restarting. On a standalone server it applies |
| 89 | +to that server; in a cluster it replicates to the other nodes. The configuration |
| 90 | +is: |
| 91 | + |
| 92 | +```toml |
| 93 | +[security] |
| 94 | +enabled = true |
| 95 | +passkeys_disabled = false |
| 96 | +``` |
| 97 | + |
| 98 | +Set `passkeys_disabled = true` to disable the feature. Before editing TOML |
| 99 | +directly, ensure every active account has another enabled sign-in method; the |
| 100 | +account check described above is performed by the settings form. |
| 101 | + |
| 102 | +## Hostnames and cluster failover |
| 103 | + |
| 104 | +Sable derives the relying party ID (RP ID) from the registrable parent domain of |
| 105 | +the hostname you access, using the Public Suffix List. No manual RP ID or |
| 106 | +separate allowed-origins list is needed. |
| 107 | + |
| 108 | +| Console address | RP ID | |
| 109 | +| --- | --- | |
| 110 | +| `https://dns.example.com` | `example.com` | |
| 111 | +| `https://ns1.penree.net` | `penree.net` | |
| 112 | +| `https://ns2.penree.net` | `penree.net` | |
| 113 | +| `http://localhost:5391` | `localhost` | |
| 114 | + |
| 115 | +For a cluster named `ns.penree.net` with nodes `ns1.penree.net` and |
| 116 | +`ns2.penree.net`, the RP ID is `penree.net`. The cluster domain itself does not |
| 117 | +set the RP ID. Sable handles public suffixes such as `co.uk` and private hosting |
| 118 | +suffixes when deriving the registrable domain. |
| 119 | + |
| 120 | +Trusted origins come from existing configuration: |
| 121 | + |
| 122 | +- Advertised HTTPS URLs in the cluster registry and the local advertised URL. |
| 123 | +- The HTTPS console's listener hostname and explicit certificate DNS names. |
| 124 | +- `encrypted_dns.acme.domains` for ACME, or the explicit names in a manually |
| 125 | + installed or generated certificate. |
| 126 | + |
| 127 | +Sable recognizes the configured HTTPS listener port and standard HTTPS port |
| 128 | +443. Wildcard certificate names do not authorize arbitrary sibling websites. |
| 129 | +Adding or removing a configured identity changes the trusted origins without |
| 130 | +maintaining another passkey-specific list. |
| 131 | + |
| 132 | +After replication, a credential registered on `ns1.penree.net` can sign in on |
| 133 | +`ns2.penree.net` when both addresses are trusted. Joining a cluster, promoting a |
| 134 | +replica, or removing the old primary does not change the RP ID. Browser sessions |
| 135 | +and in-progress authentication challenges are node-local: begin a new sign-in |
| 136 | +on the replacement node if failover interrupts a login. |
| 137 | + |
| 138 | +Nodes under unrelated registrable domains cannot share a passkey with this |
| 139 | +default. Use names under the same domain or retain password/OIDC access. A |
| 140 | +credential's RP ID cannot be changed after enrollment; moving to a different |
| 141 | +domain requires a new passkey. |
| 142 | + |
| 143 | +## Reverse proxies and backups |
| 144 | + |
| 145 | +A reverse proxy must preserve the original Host and send |
| 146 | +`X-Forwarded-Proto: https` to Sable. The browser's origin must match that address. |
| 147 | +When no explicit HTTPS identities are configured, such as an HTTP-only backend |
| 148 | +behind a proxy, sign-in falls back to the exact verified enrollment origin. |
| 149 | + |
| 150 | +Authorization backups and cluster snapshots include public credentials and user |
| 151 | +handles. Restoring them preserves ownership but cannot change their domain |
| 152 | +binding or recover a lost private key. The restored server must be reachable at |
| 153 | +an authorized HTTPS address under the same domain. Replication preserves newer |
| 154 | +local signature counters when applying older credential state. |
| 155 | + |
| 156 | +## Troubleshooting |
| 157 | + |
| 158 | +- **No passkey button:** check the administrator setting, browser support, and |
| 159 | + whether you opened an HTTPS hostname or localhost. |
| 160 | +- **Hostname rejected:** use a DNS name present in the existing HTTPS identities. |
| 161 | + Check the exact hostname and port, certificate names, and proxy headers. |
| 162 | +- **Passkey missing on another node:** confirm replication has caught up and the |
| 163 | + node uses a trusted address under the same registrable domain. |
| 164 | +- **Canceled or timed-out prompt:** retry the sign-in or registration action. |
| 165 | +- **Demo passkeys do not work:** the demo's MacBook and iPhone entries are display |
| 166 | + fixtures. Their private keys are discarded; keep the demo password enabled or |
| 167 | + register your own passkey using localhost. |
0 commit comments