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 +94 -14
- package/dist/index.cjs +786 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +380 -18
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +380 -18
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +766 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/utils-B6mbFG4c.mjs +0 -3
- package/dist/utils-DlRwlNxK.cjs +0 -3
- package/dist/utils-HZ1CkHN-.mjs +0 -500
- package/dist/utils-HZ1CkHN-.mjs.map +0 -1
- package/dist/utils-f_bV5svh.cjs +0 -536
- package/dist/utils-f_bV5svh.cjs.map +0 -1
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
|
|
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
|
-
|
|
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
|
-
- `
|
|
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:
|
|
180
|
-
- `getCurrentKeyInfo():
|
|
181
|
-
- `setCurrentKeyInfo(keyInfo:
|
|
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
|
-
- `
|
|
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
|
|
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 `
|
|
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
|
|
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:
|
|
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:
|
|
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 '
|
|
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.
|