added passkey support (closes #6)
All checks were successful
test-and-lint / test-and-lint (pull_request) Successful in 2m50s
All checks were successful
test-and-lint / test-and-lint (pull_request) Successful in 2m50s
This commit is contained in:
@@ -4,7 +4,7 @@ This document summarizes the current security-relevant behavior of MiauInv. It i
|
||||
|
||||
## Authentication
|
||||
|
||||
MiauInv uses signed JWT access tokens, database-backed refresh tokens, and optional TOTP-based two-factor authentication.
|
||||
MiauInv uses signed JWT access tokens, database-backed refresh tokens, optional TOTP-based two-factor authentication, and optional WebAuthn passkeys.
|
||||
|
||||
JWTs are signed with `JWT_SECRET`. They are not encrypted. Normal access tokens and purpose tokens should therefore contain only identity and authorization metadata.
|
||||
|
||||
@@ -66,9 +66,23 @@ Recovery codes are single-use. During login, a submitted value is first checked
|
||||
|
||||
The account settings UI warns the user when the remaining unused recovery-code count is low.
|
||||
|
||||
## Passkeys
|
||||
|
||||
Passkeys use WebAuthn public-key credentials. The server stores credential metadata and public-key material, but not private keys. Private keys remain controlled by the authenticator, browser, operating system, or security key.
|
||||
|
||||
Passkey registration requires the current account password. Registration uses a server-side challenge stored in `passkey_challenges` and returned to the browser only as an opaque challenge token. The browser response is verified before the credential is stored.
|
||||
|
||||
Passkey login creates a one-time server-side challenge. The login flow uses discoverable passkeys and does not require entering a username first. User verification is required for passkey registration and login.
|
||||
|
||||
Passkey login is treated as a complete phishing-resistant sign-in method. Because passkey registration and login require WebAuthn user verification, the server issues a normal session after a valid passkey assertion instead of asking for an additional TOTP code.
|
||||
|
||||
When passkeys are added, removed, or disabled, existing refresh sessions are revoked and a fresh current session is issued.
|
||||
|
||||
Passkey ceremonies require HTTPS except for localhost. Reverse proxy deployments must preserve the correct public `Host`, `X-Forwarded-Host`, and `X-Forwarded-Proto` information so that the relying party origin and ID match the browser-visible origin.
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
Basic in-memory rate limiting protects login, 2FA, refresh, registration, and sensitive account endpoints.
|
||||
Basic in-memory rate limiting protects login, passkey ceremonies, 2FA, refresh, registration, and sensitive account endpoints.
|
||||
|
||||
This is suitable for a single-instance private deployment. It is not sufficient for multi-instance deployments because limiter state is process-local. A public or multi-instance deployment should use persistent or distributed rate limiting at the application, reverse proxy, or infrastructure layer.
|
||||
|
||||
@@ -76,8 +90,8 @@ This is suitable for a single-instance private deployment. It is not sufficient
|
||||
|
||||
- Automated testing is currently limited.
|
||||
- TOTP secrets are stored in the database after confirmation because the server must validate future codes.
|
||||
- Passkey credential metadata and public-key data are stored in the database after registration.
|
||||
- TOTP secrets are not encrypted at rest.
|
||||
- There is no dedicated session/device management UI yet.
|
||||
- There is no audit log for account security changes yet.
|
||||
- The current rate limiter is process-local and memory-only.
|
||||
- Passkeys/WebAuthn are intentionally not implemented yet.
|
||||
|
||||
Reference in New Issue
Block a user