Add auth architecture documentation

This commit is contained in:
thePR0M3TH3AN committed 2026-01-07 20:04:52 -05:00
1 parent cc130ae513
commit 9e5b8e2b14
1 file changed
+131
+131
View File
@@ -0,0 +1,131 @@
# Auth architecture overview
This document consolidates how bitvid authentication works today, with a focus on
`js/services/authService.js` and the provider implementations in
`js/services/authProviders/`. It complements the storage details in
[`docs/nostr-auth.md`](nostr-auth.md) and the remote signer specifics in
[`docs/nip46-remote-signers.md`](nip46-remote-signers.md).
## Core building blocks
- **AuthService (`js/services/authService.js`)** orchestrates login/logout flows,
maintains the active identity, updates saved profile storage, and emits auth
events for the rest of the app.
- **Auth providers (`js/services/authProviders/`)** are pluggable adapters that
implement `login()` for a specific signing strategy:
- `nip07` (browser extension signer)
- `nsec` (direct/private key signer stored locally)
- `nip46` (remote signer via Nostr Connect)
- **State + storage** lives in `js/state/appState.js` and `js/state/cache.js`,
backed by `localStorage` keys described in `docs/nostr-auth.md`.
## AuthService responsibilities
### Provider selection and normalization
`AuthService.requestLogin()` is the entry point for logins. It:
1. Normalizes the requested provider id (defaults to `nip07`).
2. Calls the provider’s `login()` method with the active `nostrClient` and
provider-specific options.
3. Normalizes the provider result into `{ pubkey, authType, signer }`.
4. For NIP-07, requests extension permissions before continuing.
5. Either returns the normalized result (when `autoApply: false`) or calls
`login()` to apply the identity.
### Applying a login
`AuthService.login(pubkey, options)` is responsible for applying the session:
- **Identity + session state**
- Normalizes the pubkey to hex, writes it to `appState` (`setPubkey`) and
stores the bech32 `npub` (`setCurrentUserNpub`).
- Updates `nostrClient.pubkey` so downstream services use the new identity.
- **Saved profile persistence**
- Reads + updates the saved profile list in `js/state/cache.js`.
- Persists `bitvid:savedProfiles:v1` with the latest `authType` + `providerId`.
- Ensures there is an `activePubkey` entry when `persistActive` is true.
- **Post-login hydration**
- Kicks off async profile/block/relay loading via `applyPostLoginState()` and
emits `auth:post-login` for consumers (UI updates, etc.).
### Logout and profile switching
- `logout()` clears the active pubkey/npub, resets moderation + caches, and
keeps the saved profile list intact so users can quickly re-auth.
- `switchProfile()` replays the login flow for a previously saved pubkey and
moves it to the front of the saved list.
## Provider flows
### NIP-07 (browser extension signer)
- Implemented by `js/services/authProviders/nip07.js`.
- Delegates `login()` to `nostrClient.login()` and expects a pubkey (and optional
signer) in the result.
- After provider login, `AuthService` requests extension permissions before
completing the session. Permission failure aborts the login.
**Key behavior:** signing stays inside the browser extension; bitvid only stores
pubkey metadata in `localStorage`.
### nsec (local signer)
- Implemented by `js/services/authProviders/nsec.js`.
- Supports two modes:
- **Unlock stored key** (`unlockStored: true`): uses
`nostrClient.unlockStoredSessionActor()` and requires a passphrase.
- **Direct secret**: derives a key from an `nsec`, hex key, or seed via
`nostrClient.derivePrivateKeyFromSecret()` and registers a local signer with
`nostrClient.registerPrivateKeySigner()`.
- Can optionally persist the encrypted key on the device; authService still only
stores public metadata in the saved profile list.
**Key behavior:** signing happens locally in the browser with a derived private
key; storage of the private key is optional and encrypted when persisted.
### NIP-46 (remote signer / Nostr Connect)
- Implemented by `js/services/authProviders/nip46.js`.
- Supports three paths:
- **Reuse stored session** (`reuseStored: true`): use
`nostrClient.useStoredRemoteSigner()` to resume the saved NIP-46 session.
- **Manual connection** (`mode: "manual"`): use a provided
`connectionString` (e.g., `nostrconnect://` or `bunker://`).
- **Handshake flow** (`mode: "handshake"`, default): generate a handshake via
`nostrClient.prepareRemoteSignerHandshake()` and then connect using the
returned connection string + client keypair.
**Key behavior:** signing happens on a remote device. Session material is stored
in `bitvid:nip46:session:v1` as described in
[`docs/nip46-remote-signers.md`](nip46-remote-signers.md).
## Session state + persistence
Auth state is intentionally small and split across caches:
- **Active identity:** `js/state/appState.js` keeps the current `pubkey` + `npub`
in memory and updates `nostrClient.pubkey` on login.
- **Saved profiles:** `js/state/cache.js` manages
`bitvid:savedProfiles:v1`, including `authType` + `providerId` for each entry.
See [`docs/nostr-auth.md`](nostr-auth.md) for the schema and migration notes.
- **Profile cache:** `bitvid:profileCache:v1` is used to show display names +
avatars quickly; it is updated during `loadOwnProfile()` calls.
- **Remote signer session:** `bitvid:nip46:session:v1` stores handshake/session
data for NIP-46 reconnects. See
[`docs/nip46-remote-signers.md`](nip46-remote-signers.md) for details.
## NIP-04 / NIP-44 considerations
AuthService and the provider adapters do **not** implement NIP-04 or NIP-44
message encryption/decryption directly. They simply supply a pubkey and (when
available) a signer object back to the caller. When other features (like direct
messages) need NIP-04 or NIP-44 capabilities, they rely on the active signer
implementation on the `nostrClient`. Remote signers and extensions must support
those encryption methods for DM features to work, while local `nsec` signers can
provide the primitives directly.
## Related docs
- [`docs/nostr-auth.md`](nostr-auth.md)
- [`docs/nip46-remote-signers.md`](nip46-remote-signers.md)