ns-auth-sdk 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,12 +12,15 @@ Open‑source, client‑side, decentralized single‑sign‑on (SSO) like NSAuth
12
12
  ## Technology
13
13
 
14
14
  ### Choose your Backend
15
- NSAuth is designed as a frontend SSO where data can be synced in a trust minimized way. The basics are there for extensions to interoperate with Farcaster, Nostr, Ethereum, Solana or even regular webservers.
15
+ NSAuth is designed as a frontend SSO where data can be synced in a trust minimized way. The basics are there for extensions to interoperate with public or private DLT networks or even regular webservers.
16
16
 
17
17
  ### Two Approaches
18
18
  #### PRF Direct Method
19
19
  Derive the private key directly from the PRF value produced by a passkey.
20
20
 
21
+ #### Password Fallback Method
22
+ If PRF is not supported (e.g., on older browsers or devices without WebAuthn), the SDK automatically falls back to a password-protected key. The user's password encrypts the private key using AES-256-GCM, and the encrypted bundle is stored locally. The password is never stored - it's only used to derive the encryption key on-demand.
23
+
21
24
  #### Encryption Method
22
25
  Encrypt an existing private key with a key derived from the passkey’s PRF output. WebAuthn PRF Extension The PRF (Pseudo‑Random Function) extension, part of WebAuthn Level 3, yields deterministic 32‑byte high‑entropy values from an authenticator’s internal private key and a supplied salt. The same credential ID and salt always generate the same PRF output, which never leaves the device except during authentication.
23
26
 
@@ -79,10 +82,34 @@ function App() {
79
82
  // Initialize auth on mount
80
83
  useAuthInit(authService, setAuthenticated);
81
84
 
82
- // ... rest of your app
85
+ // ... rest of your app
86
+ }
87
+ ```
88
+
89
+ ### Password Fallback
90
+
91
+ When PRF is not supported by the browser or device, the SDK automatically uses password encryption. Here's how to handle it in your app:
92
+
93
+ ```typescript
94
+ import { AuthService, checkPRFSupport } from 'ns-auth-sdk';
95
+
96
+ // Check if password fallback is needed
97
+ const prfSupported = await checkPRFSupport();
98
+
99
+ if (!prfSupported) {
100
+ // Show password input to user
101
+ const password = await promptUserForPassword();
83
102
  }
103
+
104
+ // Create key (auto-detects PRF support)
105
+ const keyInfo = await authService.createKey(credentialId, password);
106
+
107
+ // Sign events (pass password for password-protected keys)
108
+ const signedEvent = await authService.signEvent(event, { password });
84
109
  ```
85
110
 
111
+ The SDK handles the complexity automatically - just pass the password when prompted.
112
+
86
113
  ### 3. Use Components
87
114
 
88
115
  #### Registration Flow
@@ -174,19 +201,47 @@ function MembershipPageComponent() {
174
201
  #### Methods
175
202
 
176
203
  - `createPasskey(username?: string): Promise<Uint8Array>` - Create a new passkey
177
- - `createNostrKey(credentialId?: Uint8Array): Promise<NostrKeyInfo>` - Create Nostr key from passkey
204
+ - `createKey(credentialId?: Uint8Array, password?: string): Promise<KeyInfo>` - Create key from passkey (auto-detects PRF support, uses password fallback if needed)
178
205
  - `getPublicKey(): Promise<string>` - Get current public key
179
- - `signEvent(event: NostrEvent): Promise<NostrEvent>` - Sign a Nostr event
180
- - `getCurrentKeyInfo(): NostrKeyInfo | null` - Get current key info
181
- - `setCurrentKeyInfo(keyInfo: NostrKeyInfo): void` - Set current key info
206
+ - `signEvent(event: Event, options?: SignOptions): Promise<Event>` - Sign a event (options.password required for password-protected keys)
207
+ - `getCurrentKeyInfo(): KeyInfo | null` - Get current key info
208
+ - `setCurrentKeyInfo(keyInfo: KeyInfo): void` - Set current key info
182
209
  - `hasKeyInfo(): boolean` - Check if key info exists
183
210
  - `clearStoredKeyInfo(): void` - Clear stored key info
184
- - `isPrfSupported(): Promise<boolean>` - Check if PRF is supported
211
+ - `checkPRFSupport(): Promise<boolean>` - Check if PRF is supported (returns false if password fallback needed)
212
+
213
+ #### Types
214
+
215
+ ```typescript
216
+ // Password-protected key bundle (used when PRF unavailable)
217
+ interface PasswordProtectedBundle {
218
+ publicKeySpkiBase64: string;
219
+ wrappedPrivateKeyBase64: string;
220
+ saltBase64: string;
221
+ ivBase64: string;
222
+ }
223
+
224
+ // KeyInfo with optional password fallback
225
+ interface KeyInfo {
226
+ credentialId: string;
227
+ pubkey: string;
228
+ salt: string;
229
+ username?: string;
230
+ passwordProtectedBundle?: PasswordProtectedBundle;
231
+ }
232
+
233
+ // Sign options with password support
234
+ interface SignOptions {
235
+ clearMemory?: boolean;
236
+ tags?: string[][];
237
+ password?: string;
238
+ }
239
+ ```
185
240
 
186
241
  #### Configuration Options
187
242
 
188
243
  ```typescript
189
- interface NosskeyManagerOptions {
244
+ interface KeyManagerOptions {
190
245
  cacheOptions?: {
191
246
  enabled: boolean;
192
247
  timeoutMs?: number;
@@ -208,24 +263,24 @@ interface NosskeyManagerOptions {
208
263
  **Cache Options:**
209
264
  - `enabled`: Enable/disable key caching
210
265
  - `timeoutMs`: Cache timeout in milliseconds (default: 30 minutes)
211
- - `cacheOnCreation`: When `true`, caches the key immediately after `createNostrKey()` to reduce biometric prompts from 2-3 to 1-2. This is enabled by default for better user experience.
266
+ - `cacheOnCreation`: When `true`, caches the key immediately after `createKey()` to reduce biometric prompts from 2-3 to 1-2. This is enabled by default for better user experience.
212
267
 
213
268
  ### RelayService
214
269
 
215
- Service for communicating with Nostr relays using applesauce-core.
270
+ Service for communicating with relays.
216
271
 
217
272
  #### Methods
218
273
 
219
274
  - `initialize(eventStore: EventStore): void` - Initialize with EventStore
220
275
  - `getRelays(): string[]` - Get current relay URLs
221
276
  - `setRelays(urls: string[]): void` - Set relay URLs
222
- - `publishEvent(event: NostrEvent, timeoutMs?: number): Promise<boolean>` - Publish event
277
+ - `publishEvent(event: Event, timeoutMs?: number): Promise<boolean>` - Publish event
223
278
  - `fetchProfile(pubkey: string): Promise<ProfileMetadata | null>` - Fetch profile
224
279
  - `fetchProfileRoleTag(pubkey: string): Promise<string | null>` - Fetch role tag
225
280
  - `fetchFollowList(pubkey: string): Promise<FollowEntry[]>` - Fetch follow list
226
281
  - `fetchMultipleProfiles(pubkeys: string[]): Promise<Map<string, ProfileMetadata>>` - Fetch multiple profiles
227
282
  - `queryProfiles(pubkeys?: string[], limit?: number): Promise<Map<string, ProfileMetadata>>` - Query profiles
228
- - `publishFollowList(pubkey: string, followList: FollowEntry[], signEvent: (event: NostrEvent) => Promise<NostrEvent>): Promise<boolean>` - Publish follow list
283
+ - `publishFollowList(pubkey: string, followList: FollowEntry[], signEvent: (event: Event) => Promise<Event>): Promise<boolean>` - Publish follow list
229
284
 
230
285
  ### Components
231
286
 
@@ -241,10 +296,10 @@ All components are framework-agnostic React components that accept callback prop
241
296
 
242
297
  ## Integration with Applesauce
243
298
 
244
- This library is designed to work seamlessly with applesauce-core. The `RelayService` uses applesauce's `EventStore` for all relay operations.
299
+ This library is designed to work seamlessly with applesauce-core. The `RelayService` uses applesauce's `EventStore` for all relay operations. All applesauce-core exports are re-exported from `ns-auth-sdk` for convenience.
245
300
 
246
301
  ```typescript
247
- import { EventStore } from 'applesauce-core';
302
+ import { EventStore } from 'ns-auth-sdk';
248
303
  import { RelayService } from 'ns-auth-sdk';
249
304
 
250
305
  const eventStore = new EventStore({
@@ -255,6 +310,31 @@ const relayService = new RelayService();
255
310
  relayService.initialize(eventStore);
256
311
  ```
257
312
 
313
+ ### Event Support
314
+
315
+ The SDK helpers for building events:
316
+
317
+ ```typescript
318
+ import {
319
+ Helpers,
320
+ finalizeEvent,
321
+ getPublicKey,
322
+ generateSecretKey
323
+ } from 'ns-auth-sdk';
324
+
325
+ // Generate a new key pair
326
+ const sk = generateSecretKey();
327
+ const pubkey = getPublicKey(sk);
328
+
329
+ // Create and sign an event
330
+ const event = finalizeEvent({
331
+ kind: 0,
332
+ content: 'My Event',
333
+ created_at: Math.floor(Date.now() / 1000),
334
+ tags: [],
335
+ }, sk);
336
+ ```
337
+
258
338
  ## Security Guidance
259
339
 
260
340
  - Configure a strict Content Security Policy (CSP) in the host app to restrict script and image sources.