@thru/passkey 0.2.1

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 ADDED
@@ -0,0 +1,165 @@
1
+ # @thru/passkey
2
+
3
+ Browser-only WebAuthn package for passkey registration, signing, and popup-based flows. Built on top of `@thru/passkey-manager` for platform-agnostic crypto and encoding utilities.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @thru/passkey
9
+ ```
10
+
11
+ This package requires a browser environment with WebAuthn support (`navigator.credentials`).
12
+
13
+ ## Basic Usage
14
+
15
+ ### Register a Passkey
16
+
17
+ Create a new P-256 credential bound to the user's platform authenticator:
18
+
19
+ ```typescript
20
+ import { registerPasskey } from '@thru/passkey';
21
+
22
+ const result = await registerPasskey('alice', 'user-id-123', 'example.com');
23
+ // result.credentialId - base64url credential ID
24
+ // result.publicKeyX - hex-encoded P-256 X coordinate
25
+ // result.publicKeyY - hex-encoded P-256 Y coordinate
26
+ // result.rpId - relying party ID
27
+ ```
28
+
29
+ ### Sign with a Known Credential
30
+
31
+ Sign a challenge using a specific credential ID:
32
+
33
+ ```typescript
34
+ import { signWithPasskey } from '@thru/passkey';
35
+
36
+ const challenge = new Uint8Array(32); // your challenge bytes
37
+ const result = await signWithPasskey(credentialId, challenge, 'example.com');
38
+ // result.signature - 64-byte concatenated r||s (low-S normalized)
39
+ // result.signatureR - 32-byte r component
40
+ // result.signatureS - 32-byte s component
41
+ // result.authenticatorData - raw authenticator data
42
+ // result.clientDataJSON - raw client data JSON
43
+ ```
44
+
45
+ ### Sign with a Stored Passkey
46
+
47
+ For embedded or iframe contexts where you have stored passkey metadata. Automatically falls back to a popup window when inline WebAuthn is restricted:
48
+
49
+ ```typescript
50
+ import { signWithStoredPasskey } from '@thru/passkey';
51
+ import type { PasskeyMetadata } from '@thru/passkey';
52
+
53
+ const result = await signWithStoredPasskey(
54
+ challenge,
55
+ 'example.com',
56
+ preferredPasskey, // PasskeyMetadata | null
57
+ allPasskeys, // PasskeyMetadata[]
58
+ { appName: 'My App', origin: 'https://app.example.com' }
59
+ );
60
+ // result includes .passkey metadata for the credential that signed
61
+ ```
62
+
63
+ ### Sign with a Discoverable Passkey
64
+
65
+ Let the browser prompt the user to choose from their available passkeys:
66
+
67
+ ```typescript
68
+ import { signWithDiscoverablePasskey } from '@thru/passkey';
69
+
70
+ const result = await signWithDiscoverablePasskey(challenge, 'example.com');
71
+ // result.credentialId - the credential the user selected
72
+ // result.rpId - relying party ID
73
+ ```
74
+
75
+ ## Key Capabilities
76
+
77
+ - **P-256 (ES256) credential creation** via `navigator.credentials.create` with platform authenticator selection, resident key, and user verification required
78
+ - **Three signing modes**: known credential, stored passkey with fallback, and discoverable (browser-prompted)
79
+ - **Automatic popup fallback** for iframe/embedded contexts where the Permissions Policy blocks inline WebAuthn
80
+ - **Low-S signature normalization** applied to all signing results for protocol compatibility
81
+ - **Capability detection** to query WebAuthn support, client capabilities, and determine the optimal prompt mode before signing
82
+ - **Re-exports** encoding and crypto utilities from `@thru/passkey-manager` for backward compatibility
83
+
84
+ ## Capability Detection
85
+
86
+ Check browser support and determine the best prompt mode ahead of time:
87
+
88
+ ```typescript
89
+ import {
90
+ isWebAuthnSupported,
91
+ preloadPasskeyClientCapabilities,
92
+ getPasskeyClientCapabilities,
93
+ shouldUsePasskeyPopup,
94
+ isInIframe,
95
+ } from '@thru/passkey';
96
+
97
+ // Quick synchronous check
98
+ if (!isWebAuthnSupported()) {
99
+ // WebAuthn not available
100
+ }
101
+
102
+ // Preload capabilities early (e.g., on app init)
103
+ preloadPasskeyClientCapabilities();
104
+
105
+ // Later, read cached or await capabilities
106
+ const capabilities = await getPasskeyClientCapabilities();
107
+
108
+ // Check if a popup is needed for a given action
109
+ const needsPopup = await shouldUsePasskeyPopup('get');
110
+ ```
111
+
112
+ ## Popup Bridge
113
+
114
+ For applications that host the passkey popup window (e.g., the wallet app), the package provides both the parent-side and popup-side APIs:
115
+
116
+ ### Parent Side
117
+
118
+ ```typescript
119
+ import {
120
+ openPasskeyPopupWindow,
121
+ requestPasskeyPopup,
122
+ closePopup,
123
+ PASSKEY_POPUP_PATH,
124
+ PASSKEY_POPUP_CHANNEL,
125
+ } from '@thru/passkey';
126
+ ```
127
+
128
+ ### Popup Window Side
129
+
130
+ ```typescript
131
+ import {
132
+ toPopupSigningResult,
133
+ buildSuccessResponse,
134
+ decodeChallenge,
135
+ getPopupDisplayInfo,
136
+ getResponseError,
137
+ signWithPreferredPasskey,
138
+ buildStoredPasskeyResult,
139
+ } from '@thru/passkey';
140
+ ```
141
+
142
+ Communication between parent and popup uses `postMessage` with `BroadcastChannel` as a fallback. The popup path defaults to `/passkey/popup`.
143
+
144
+ ## Re-exported Utilities
145
+
146
+ The following are re-exported from `@thru/passkey-manager` for convenience:
147
+
148
+ **Crypto**: `parseDerSignature`, `normalizeLowS`, `normalizeSignatureComponent`, `P256_N`, `P256_HALF_N`, `bytesToBigIntBE`, `bigIntToBytesBE`
149
+
150
+ **Encoding**: `arrayBufferToBase64Url`, `base64UrlToArrayBuffer`, `bytesToBase64Url`, `base64UrlToBytes`, `bytesToHex`, `hexToBytes`, `bytesEqual`, `compareBytes`, `uniqueAccounts`
151
+
152
+ ## Types
153
+
154
+ Key types exported from this package:
155
+
156
+ | Type | Description |
157
+ |------|-------------|
158
+ | `PasskeyRegistrationResult` | Credential ID and P-256 public key coordinates |
159
+ | `PasskeySigningResult` | Signature bytes, authenticator data, and client data |
160
+ | `PasskeyDiscoverableSigningResult` | Signing result with credential ID and rpId |
161
+ | `PasskeyStoredSigningResult` | Signing result with attached passkey metadata |
162
+ | `PasskeyMetadata` | Stored passkey info (credential ID, public key, rpId, timestamps) |
163
+ | `PasskeyClientCapabilities` | WebAuthn client capability flags |
164
+ | `PasskeyPopupContext` | App context passed to popup for display |
165
+ | `PasskeyPopupAccount` | Account info passed through popup bridge |