You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
You can onboard once with a raw password, optionally discard it immediately using `drop_password=True`, export authentication artifacts, and later resume without storing the raw secret:
On a 401, the client will transparently reauthenticate using the stored Argon2id `password_hash` if available. When `drop_password=True`, the raw password is never retained after initial onboarding.
This document proposes and specifies an artifact-based authentication flow for `fmd_api` that avoids storing the raw user password in long-running integrations (e.g., Home Assistant), while preserving the ability to decrypt data and reauthenticate when tokens expire.
4
+
5
+
## Goals
6
+
7
+
- Do not retain the user's raw password in memory/storage after onboarding.
8
+
- Support seamless reauthentication (401 → new token) without prompting the user again.
9
+
- Keep the local RSA private key as a long-lived client secret to avoid re-fetching/decrypting each session.
10
+
- Provide clear import/export and resume flows for integrations.
11
+
12
+
## Terms
13
+
14
+
-`fmd_id`: The FMD identity (username-like identifier).
15
+
-`password_hash`: The full Argon2id string expected by the server when calling `/api/v1/requestAccess` (includes salt and parameters).
16
+
-`access_token`: The current session token used in API requests; expires after the requested duration.
17
+
-`private_key`: The RSA private key used to decrypt location/picture blobs and sign commands. Long-lived, stored client-side.
18
+
-`session_duration`: Seconds requested when creating tokens (client default: 3600).
19
+
-`token_issued_at`: Local timestamp to optionally preempt expiry.
20
+
21
+
## Overview
22
+
23
+
Two operating modes:
24
+
25
+
1. Password mode (existing): Onboard with raw password; derive `password_hash`, request `access_token`, download and decrypt `private_key`. After success, the client may optionally discard the raw password.
26
+
2. Artifact mode (new): Resume using stored artifacts (no raw password). On 401 Unauthorized, the client uses `password_hash` to request a fresh `access_token`. The `private_key` is already local.
- After successful onboarding, if `drop_password=True`, clears the in-memory `_password` attribute.
48
+
49
+
### Internal Helpers
50
+
51
+
-`async def _reauth_with_hash(self) -> None`
52
+
- Calls `/api/v1/requestAccess` with stored `password_hash` and `session_duration`. Updates `access_token` on success.
53
+
54
+
-`_make_api_request` changes
55
+
- On 401: if `_password` is present, behave as today (reauth using raw password).
56
+
- Otherwise, if `password_hash` is present, call `_reauth_with_hash()` once and retry.
57
+
- Else: raise.
58
+
59
+
## Data Handling
60
+
61
+
-`private_key` must be loadable from PEM or DER. `export_auth_artifacts()` will prefer PEM for portability.
62
+
-`password_hash` is an online-equivalent secret for token requests. It is preferable to raw password, but should still be stored carefully (consider HA secrets storage if available).
63
+
- No raw password is stored or exported by default.
64
+
65
+
## Failure Modes
66
+
67
+
- User changes password or server salt/params: stored `password_hash` becomes invalid. Reauth fails; caller should prompt the user once, produce a new `password_hash`, and update artifacts.
68
+
- Server caps or rejects long `session_duration`: token would expire earlier than requested; client handles 401 via reauth.
69
+
- Private key rotation: if the server issues a new private key (unlikely in normal flow), onboarding should refresh artifacts.
0 commit comments