Native API token auth and websocket routes#168
Conversation
There was a problem hiding this comment.
Look good, but we need a little bit of hardening ;p
- Fix private room/message leaks
Highest priority. Native REST history and WS events must respect room membership and target_user_ids. This is the only issue that can expose user content.
- Restore test compilation
Add native_challenges to test State builders. This is small, but until fixed the branch weakens CI signal.
- Hash stored bearer tokens
Store only a SHA-256/HMAC hash of the token in native_tokens, not the raw token. On auth, hash the presented token and compare by hash. If DB leaks, raw tokens should not be directly usable.
- Move websocket auth token out of query string if possible
Query params leak into logs/proxies more often. Prefer Authorization: Bearer ... if the client stack allows it, or a short-lived WS ticket minted via authenticated REST and used once.
- Rate-limit native auth
Add limits for:
GET /api/native/challenge
POST /api/native/token
failed token auth attempts
WS connection attempts
Start per-IP. If easy, also rate-limit by fingerprint on /token.
- Add token revocation/logout
Add DELETE /api/native/token or /api/native/logout for current token. Optional but useful: revoke all native tokens for the user.
- Track token metadata
Add last_used_at, maybe user_agent/device_name, and maybe created_ip. This helps debugging and future token management. Keep IP retention policy in mind.
- Purge expired tokens
Either call NativeToken::purge_expired periodically or make it part of startup/background maintenance. Not urgent for security because queries check expiry, but important for DB hygiene.
|
Copy that |
Co-authored-by: Cursor <cursoragent@cursor.com>
What changed
This change adds a native-client API surface to
late-sshand a matching token model inlate-core.native_tokenstable andNativeTokenmodel for persistent bearer tokens with expiry.NativeChallengeStorefor short-lived nonces issued byGET /api/native/challenge.late-ssh/src/native_api.rsand mounted its routes under/api/native/*plus/api/ws/native.deadpool-postgreswhere needed for the new DB-backed native endpoints.Auth flow
The native auth flow is challenge-based:
GET /api/native/challenge.POST /api/native/tokenverifies the SSH signature and fingerprint.native_tokens.This keeps the native API aligned with the existing SSH identity model instead of introducing a separate password-based auth path.
API surface
The new native API exposes endpoints for:
Why
The repo already had the core app state and websocket/event infrastructure, but it did not expose a dedicated native-client API with a reusable bearer-token auth flow. This change fills that gap so a native app can authenticate with an SSH-backed identity and consume the same real-time app data without going through the browser-oriented routes.