feat: store OAuth tokens securely
Add bounded token response parsing with refresh-token retention and a cancellable worker-thread libsecret adapter using versioned credential payloads. Verify CRUD, isolation, cancellation, corruption, unavailable service, redaction, and cleanup against an isolated D-Bus and gnome-keyring Secret Service in normal, warning-as-error, and sanitizer profiles.
This commit is contained in:
@@ -215,8 +215,32 @@ the application manifest, and IPv6 loopback redirect addresses are currently
|
||||
unsupported. The advertised `localhost` URL therefore remains distinct from the
|
||||
IPv4-only listener binding.
|
||||
|
||||
Concrete token JSON parsing, Secret Service storage, Graph requests, account UI,
|
||||
and usable account setup are still absent. libsecret's synchronous calls may
|
||||
block; the next adapter isolates them behind an off-render-thread boundary
|
||||
rather than calling them from the TUI loop. Read-only Graph discovery and delta
|
||||
follow token parsing and secret persistence.
|
||||
### Token and Secret Service boundary
|
||||
|
||||
The token decoder is strict and
|
||||
bounded: oversized or structurally invalid JSON, wrong field types, and invalid
|
||||
token lifetimes fail before any credential is exposed to account state. Initial
|
||||
authorization requires a refresh token. A later refresh response replaces it
|
||||
when Microsoft supplies a rotated token and otherwise retains the previously
|
||||
stored refresh token.
|
||||
|
||||
Access and refresh tokens are serialized together in a versioned libsecret
|
||||
secret payload, addressed by an opaque local account identifier. SQLite stores
|
||||
neither token material nor a copy of the secret payload. Token values also stay
|
||||
out of logs, command-line arguments, and environment variables. Schema/version
|
||||
validation prevents an incompatible secret from being mistaken for current
|
||||
credentials.
|
||||
|
||||
The libsecret adapter exposes synchronous, cancellable operations and is
|
||||
worker-thread-only because a D-Bus call or keyring unlock may block. Tests run
|
||||
the real adapter against an isolated D-Bus session and gnome-keyring rather than
|
||||
claiming integration from an in-memory fake alone. Missing credentials are a
|
||||
normal disconnected result. A locked collection, cancellation, parse error, or
|
||||
read/write/delete failure remains an explicit failure; none triggers plaintext
|
||||
fallback or partial connected state. An account becomes connected only after
|
||||
the complete versioned payload has been stored successfully.
|
||||
|
||||
Graph requests, account UI, and usable account setup remain absent. After this
|
||||
boundary passes verification, the Microsoft adapter will call `/me`, discover
|
||||
calendars, and apply read-only delta pages through the durable cache using only
|
||||
delegated `Calendars.Read`.
|
||||
|
||||
Reference in New Issue
Block a user