From 8b13a618329b476581567bc6c0d768385e95335b Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Tue, 24 Mar 2026 19:35:40 -0700 Subject: [PATCH] Simplify gRPC auth: password-per-request over TLS - gRPC sync sends username+password in metadata on every RPC, verified by unary interceptor. No login RPC or token management. - Password stored in Android EncryptedSharedPreferences (Keystore) - Web UI retains bearer token flow for browser sessions - FIDO2/U2F scoped to web UI only, not gRPC sync path Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/SERVER_DESIGN.md | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/docs/SERVER_DESIGN.md b/docs/SERVER_DESIGN.md index 8909624..ed45039 100644 --- a/docs/SERVER_DESIGN.md +++ b/docs/SERVER_DESIGN.md @@ -276,23 +276,44 @@ render at 300 DPI for JPG. ## Authentication -### Password Auth +### gRPC Auth (Android App) +The app sends `username` and `password` in gRPC metadata on every +sync RPC. No separate login step, no token management on the app side. + +- TLS required — no plaintext gRPC connections accepted +- A unary interceptor extracts credentials from metadata, verifies + the password against Argon2id hash in the DB +- If invalid, returns `UNAUTHENTICATED` +- Password stored on the Android device in EncryptedSharedPreferences + (hardware-backed Android Keystore) + +This is simpler than a token-based flow and acceptable because: +- Sync is manual and infrequent +- The password travels over TLS +- The app stores the password in hardware-backed encrypted storage + +### Web Auth (Password + Bearer Token) + +The web UI uses a traditional login flow: + +- `POST /v1/auth/login` with username/password → returns bearer token +- Token stored as `HttpOnly`, `Secure`, `SameSite=Strict` session cookie +- Token validated via SHA-256 keyed lookup with short TTL cache - Argon2id hashing (memory-hard, tuned to hardware) -- Bearer tokens returned on login, stored as session cookies for web UI -- Token validation via SHA-256 keyed lookup with short TTL cache -### FIDO2/U2F (WebAuthn) +### FIDO2/U2F (WebAuthn) — Web UI Only Users can register multiple security keys after initial password login. -Once registered, keys can be used as an alternative login method. +Once registered, keys can be used as an alternative login method for +the web UI. This does not apply to the gRPC sync path. Implementation via the `go-webauthn/webauthn` library: 1. **Registration flow**: - - User logs in with password + - User logs in with password via web UI - Calls `POST /v1/auth/webauthn/register/begin` → gets challenge - - Browser/client signs challenge with security key + - Browser signs challenge with security key - Calls `POST /v1/auth/webauthn/register/finish` with attestation - Server stores credential in `webauthn_credentials` table @@ -341,8 +362,10 @@ New files: ### Configuration -Server URL and auth token stored in `EngPadApp` SharedPreferences. -First sync prompts for server URL and login credentials. +Server URL, username, and password stored in Android +EncryptedSharedPreferences (hardware-backed Keystore). Configured +via a Sync settings screen accessible from the library view. +First sync prompts for server URL and credentials if not configured. ## Server Repository Layout