@icp-sdk/auth 7.1.0 → 8.0.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.
|
@@ -53,6 +53,29 @@ export interface AuthClientCreateOptions {
|
|
|
53
53
|
* @example "toolbar=0,location=0,menubar=0,width=500,height=500,left=100,top=100"
|
|
54
54
|
*/
|
|
55
55
|
windowOpenerFeatures?: string;
|
|
56
|
+
/**
|
|
57
|
+
* How the client communicates with the identity provider.
|
|
58
|
+
*
|
|
59
|
+
* - `'window'` (default) — the identity provider opens in a separate browser
|
|
60
|
+
* tab or window (a popup when {@link windowOpenerFeatures} is set) and
|
|
61
|
+
* communicates over the ICRC-29 `postMessage` transport.
|
|
62
|
+
* - `'redirect'` — the current page navigates to the identity provider over
|
|
63
|
+
* the ICRC-167 URL transport, which returns to this same page. The callback
|
|
64
|
+
* URL is the current page's URL (`location.origin + location.pathname`), so
|
|
65
|
+
* that page must be on an origin you control and declared in that origin's
|
|
66
|
+
* `/.well-known/ii-auth-callbacks` allow-list. Use it for full-page sign-in
|
|
67
|
+
* that shouldn't need a user gesture to open a window (e.g. redirecting on a
|
|
68
|
+
* restricted route), or native apps handing off via universal links.
|
|
69
|
+
*
|
|
70
|
+
* With `'redirect'` the page unloads on each step and the flow re-runs on the
|
|
71
|
+
* return load, so call `signIn` / `requestAttributes` directly on the page's
|
|
72
|
+
* load (not deferred behind, say, a click handler): a fresh visit starts the
|
|
73
|
+
* flow and the identity provider's return replays it to completion. Give each
|
|
74
|
+
* flow its own route so its persisted state stays isolated.
|
|
75
|
+
* @default 'window'
|
|
76
|
+
* @see https://github.com/dfinity/wg-identity-authentication/blob/main/topics/icrc_167_browser_url_transport.md
|
|
77
|
+
*/
|
|
78
|
+
transport?: 'window' | 'redirect';
|
|
56
79
|
/**
|
|
57
80
|
* OpenID provider for one-click sign-in. When set, the identity provider
|
|
58
81
|
* URL includes an `openid` search param so the user authenticates via
|
|
@@ -132,24 +155,69 @@ export declare class AuthClient {
|
|
|
132
155
|
/**
|
|
133
156
|
* Requests signed identity attributes from the identity provider.
|
|
134
157
|
*
|
|
135
|
-
* The `nonce`
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
158
|
+
* The `nonce` is a callback that produces the 32-byte nonce (typically
|
|
159
|
+
* fetched from the RP canister), returning a promise resolving to it. It is a
|
|
160
|
+
* callback rather than a value so the redirect flow can journal the nonce and
|
|
161
|
+
* reuse the exact same bytes when the flow replays on the return load,
|
|
162
|
+
* instead of fetching a fresh single-use nonce that the signer never signed
|
|
163
|
+
* against.
|
|
164
|
+
*
|
|
165
|
+
* In 'window' mode the callback lets the identity provider window open while the
|
|
166
|
+
* nonce is still resolving, avoiding a perceived delay before the user sees
|
|
167
|
+
* the prompt; auto-close of the signer transport channel is temporarily
|
|
168
|
+
* disabled while awaiting so the window cannot be closed out from under the
|
|
169
|
+
* pending flow.
|
|
141
170
|
*
|
|
142
171
|
* @param params - Request parameters.
|
|
143
172
|
* @param params.keys - Attribute keys to request (e.g. `['email', 'name']`).
|
|
144
|
-
* @param params.nonce - 32-byte nonce issued by the RP canister,
|
|
145
|
-
* resolving to
|
|
173
|
+
* @param params.nonce - Produces the 32-byte nonce issued by the RP canister,
|
|
174
|
+
* as a promise resolving to it.
|
|
146
175
|
* @returns Signed attribute data and signature.
|
|
147
176
|
* @throws When the identity provider returns an error or an invalid response.
|
|
148
177
|
*/
|
|
149
178
|
requestAttributes(params: {
|
|
150
179
|
keys: string[];
|
|
151
|
-
nonce:
|
|
180
|
+
nonce: () => Promise<Uint8Array>;
|
|
152
181
|
}): Promise<SignedAttributes>;
|
|
182
|
+
/**
|
|
183
|
+
* Runs and journals a piece of your own async work so its result stays stable
|
|
184
|
+
* across the `'redirect'` flow.
|
|
185
|
+
*
|
|
186
|
+
* In `'redirect'` mode the page unloads on each step and `signIn` /
|
|
187
|
+
* `requestAttributes` re-run on the return load, so a value you compute on the
|
|
188
|
+
* first visit (from `location`, a fetch, `crypto`, …) would otherwise be
|
|
189
|
+
* recomputed — and may differ — on the return. Wrap it in `memoize`: it runs
|
|
190
|
+
* `produce` once on the first visit, journals the result, and replays that
|
|
191
|
+
* result on the return load instead of re-running. Use it for a value the
|
|
192
|
+
* post-flow code depends on, e.g. the URL to navigate to once sign-in
|
|
193
|
+
* completes:
|
|
194
|
+
*
|
|
195
|
+
* ```ts
|
|
196
|
+
* const next = await authClient.memoize(
|
|
197
|
+
* () => new URLSearchParams(location.search).get('next') ?? '/',
|
|
198
|
+
* );
|
|
199
|
+
* await authClient.signIn();
|
|
200
|
+
* location.assign(next); // the value captured before the redirect
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* Call `memoize` in a stable order relative to `signIn` / `requestAttributes`
|
|
204
|
+
* across loads (same order every load — branch only on values recovered from
|
|
205
|
+
* earlier results), and keep the result JSON-serializable, since the journal
|
|
206
|
+
* is JSON.
|
|
207
|
+
*
|
|
208
|
+
* In `'window'` mode there is no redirect, so this simply runs `produce` and
|
|
209
|
+
* returns its result without persisting anything.
|
|
210
|
+
*
|
|
211
|
+
* Mirrors the producer's shape: a synchronous `produce` returns its value
|
|
212
|
+
* directly, an asynchronous one returns a promise. Awaiting the result is
|
|
213
|
+
* always safe (`await` on a non-promise is a no-op); the synchronous form lets
|
|
214
|
+
* a value be memoized where an `await` is not possible, such as in a
|
|
215
|
+
* constructor.
|
|
216
|
+
* @param produce - Produces the value to journal on the first load.
|
|
217
|
+
* @returns The produced value, or the journaled value on a replay load.
|
|
218
|
+
*/
|
|
219
|
+
memoize<T>(produce: () => Promise<T>): Promise<T>;
|
|
220
|
+
memoize<T>(produce: () => T): T;
|
|
153
221
|
/**
|
|
154
222
|
* Clears the stored session and resets the client to an anonymous state.
|
|
155
223
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnonymousIdentity } from '@icp-sdk/core/agent';
|
|
2
2
|
import { DelegationChain, DelegationIdentity, ECDSAKeyIdentity, Ed25519KeyIdentity, isDelegationValid, PartialDelegationIdentity, } from '@icp-sdk/core/identity';
|
|
3
3
|
import { Signer } from '@icp-sdk/signer';
|
|
4
|
-
import { PostMessageTransport } from '@icp-sdk/signer/web';
|
|
4
|
+
import { PostMessageTransport, UrlTransport } from '@icp-sdk/signer/web';
|
|
5
5
|
import { IdleManager } from './idle-manager.js';
|
|
6
6
|
import { IdbStorage, KEY_STORAGE_DELEGATION, KEY_STORAGE_KEY, KEY_VECTOR, LocalStorage, } from './storage.js';
|
|
7
7
|
const NANOSECONDS_PER_SECOND = BigInt(1_000_000_000);
|
|
@@ -14,6 +14,10 @@ const ED25519_KEY_LABEL = 'Ed25519';
|
|
|
14
14
|
// localStorage key used to cache the delegation expiration so that
|
|
15
15
|
// isAuthenticated() can answer synchronously without hitting IndexedDB.
|
|
16
16
|
const KEY_STORAGE_EXPIRATION = 'ic-delegation_expiration';
|
|
17
|
+
// Storage key prefix for a redirect flow's session key, held only while the
|
|
18
|
+
// flow is in progress (keyed by a per-flow id) and removed once the delegation
|
|
19
|
+
// is persisted. See AuthClient.#acquireSessionKey.
|
|
20
|
+
const PENDING_KEY_PREFIX = 'ic-auth-pending-key:';
|
|
17
21
|
export const OPENID_PROVIDER_URLS = {
|
|
18
22
|
google: 'https://accounts.google.com',
|
|
19
23
|
apple: 'https://appleid.apple.com',
|
|
@@ -35,6 +39,9 @@ export class AuthClient {
|
|
|
35
39
|
#chain = null;
|
|
36
40
|
#storage;
|
|
37
41
|
#signer;
|
|
42
|
+
// Set only in redirect mode, so the redirect-specific paths (nonce/key
|
|
43
|
+
// journaling) can reach `memoize`. Undefined in the default 'window' mode.
|
|
44
|
+
#urlTransport;
|
|
38
45
|
#options;
|
|
39
46
|
#initPromise = null;
|
|
40
47
|
idleManager;
|
|
@@ -45,13 +52,29 @@ export class AuthClient {
|
|
|
45
52
|
if (options.openIdProvider) {
|
|
46
53
|
identityProviderUrl.searchParams.set('openid', OPENID_PROVIDER_URLS[options.openIdProvider]);
|
|
47
54
|
}
|
|
48
|
-
const transport =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
const transport = options.transport === 'redirect'
|
|
56
|
+
? new UrlTransport({
|
|
57
|
+
url: identityProviderUrl.toString(),
|
|
58
|
+
// The callback is this page: a fresh visit starts the flow and the
|
|
59
|
+
// provider's return lands back here to replay it. Drop any query
|
|
60
|
+
// and fragment so it stays stable across the redirect.
|
|
61
|
+
callbackUrl: `${globalThis.location.origin}${globalThis.location.pathname}`,
|
|
62
|
+
})
|
|
63
|
+
: new PostMessageTransport({
|
|
64
|
+
url: identityProviderUrl.toString(),
|
|
65
|
+
windowOpenerFeatures: options.windowOpenerFeatures,
|
|
66
|
+
});
|
|
67
|
+
this.#urlTransport = transport instanceof UrlTransport ? transport : undefined;
|
|
52
68
|
this.#signer = new Signer({
|
|
53
69
|
transport,
|
|
54
|
-
|
|
70
|
+
// Journal the derivation origin so it survives the top-level redirect: the
|
|
71
|
+
// return load reconstructs this client from a query-less callback URL, so
|
|
72
|
+
// `options.derivationOrigin` (like the identity provider) is no longer
|
|
73
|
+
// available — the memoized value replays from the journal instead.
|
|
74
|
+
// `memoize` returns synchronously for a synchronous producer, so the value
|
|
75
|
+
// is usable directly here; in the window flow it is a passthrough that runs
|
|
76
|
+
// the producer without persisting anything.
|
|
77
|
+
derivationOrigin: this.memoize(() => options.derivationOrigin?.toString()),
|
|
55
78
|
});
|
|
56
79
|
this.#registerDefaultIdleCallback();
|
|
57
80
|
// Eagerly start restoring a previous session from storage.
|
|
@@ -93,10 +116,27 @@ export class AuthClient {
|
|
|
93
116
|
* }
|
|
94
117
|
*/
|
|
95
118
|
async signIn(options) {
|
|
96
|
-
await this.#signer.openChannel();
|
|
97
119
|
const maxTimeToLive = options?.maxTimeToLive ?? DEFAULT_MAX_TIME_TO_LIVE;
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
const keyType = this.#options.keyType ?? ECDSA_KEY_LABEL;
|
|
121
|
+
// Start session-key acquisition BEFORE opening the channel, awaiting it only
|
|
122
|
+
// after. In the redirect flow the acquisition's first `transport.memoize`
|
|
123
|
+
// runs synchronously when invoked, so its in-flight bump lands in the same
|
|
124
|
+
// tick `signIn` is called — holding the transport's batch flush from the
|
|
125
|
+
// very start of the flow rather than only after the `openChannel` await.
|
|
126
|
+
// Under `Promise.all([signIn, requestAttributes])` this is what keeps a
|
|
127
|
+
// faster concurrent request from flushing before this flow's delegation
|
|
128
|
+
// request is buffered.
|
|
129
|
+
const sessionKeyPromise = this.#urlTransport
|
|
130
|
+
? this.#ensureSessionKeyForRedirectFlow(this.#urlTransport, keyType)
|
|
131
|
+
: this.#ensureSessionKeyForWindowFlow(keyType).then((key) => ({ key }));
|
|
132
|
+
// The acquisition is started eagerly, before the awaits below. If one of
|
|
133
|
+
// those throws first, `sessionKeyPromise` is never awaited, so attach a
|
|
134
|
+
// no-op rejection handler now to keep a later acquisition failure from
|
|
135
|
+
// surfacing as an unhandled rejection. The `await` below still observes a
|
|
136
|
+
// rejection and propagates it when reached.
|
|
137
|
+
void sessionKeyPromise.catch(() => undefined);
|
|
138
|
+
await this.#signer.openChannel();
|
|
139
|
+
const { key, pendingKeySlot } = await sessionKeyPromise;
|
|
100
140
|
const delegationChain = await this.#signer.requestDelegation({
|
|
101
141
|
publicKey: key.getPublicKey(),
|
|
102
142
|
targets: options?.targets,
|
|
@@ -118,27 +158,92 @@ export class AuthClient {
|
|
|
118
158
|
// Persist so the session survives page reloads.
|
|
119
159
|
await persistChain(this.#storage, this.#chain);
|
|
120
160
|
await persistKey(this.#storage, key);
|
|
161
|
+
// The flow is complete: the delegation is bound to this key and stored, so
|
|
162
|
+
// the per-flow pending copy is no longer needed.
|
|
163
|
+
if (pendingKeySlot !== undefined) {
|
|
164
|
+
await this.#storage.remove(pendingKeySlot);
|
|
165
|
+
}
|
|
121
166
|
return this.#identity;
|
|
122
167
|
}
|
|
168
|
+
// Window flow: sign-in completes in a single load, so a fresh session key per
|
|
169
|
+
// sign-in is enough (or the caller-provided identity), with nothing to
|
|
170
|
+
// persist for a later load.
|
|
171
|
+
async #ensureSessionKeyForWindowFlow(keyType) {
|
|
172
|
+
return this.#options.identity ?? (await generateKey(keyType));
|
|
173
|
+
}
|
|
174
|
+
// Redirect flow: `signIn` runs twice — once on the load that navigates to the
|
|
175
|
+
// identity provider, and again on the return load that replays the delegation
|
|
176
|
+
// minted for the FIRST load's key. Both runs must therefore use the same key.
|
|
177
|
+
// A per-flow key id is journaled via the transport (stable across the
|
|
178
|
+
// redirect) and the key is kept in storage under that id, so the return load
|
|
179
|
+
// restores the same key rather than generating a fresh one that would not
|
|
180
|
+
// match the replayed delegation. A caller-provided identity is already stable
|
|
181
|
+
// across the redirect, so it is used as-is with nothing persisted.
|
|
182
|
+
async #ensureSessionKeyForRedirectFlow(transport, keyType) {
|
|
183
|
+
if (this.#options.identity !== undefined) {
|
|
184
|
+
return { key: this.#options.identity };
|
|
185
|
+
}
|
|
186
|
+
const keyId = await transport.memoize(() => globalThis.crypto.randomUUID());
|
|
187
|
+
const pendingKeySlot = `${PENDING_KEY_PREFIX}${keyId}`;
|
|
188
|
+
// Acquire the per-flow key inside a `memoize` producer so the transport
|
|
189
|
+
// holds its batch flush across the (async) key restore/generate + storage
|
|
190
|
+
// write. The transport coalesces concurrently issued requests into one
|
|
191
|
+
// redirect by flushing on a macrotask once no memoize producer is in
|
|
192
|
+
// flight; without this hold, a faster concurrent request (e.g. the nonce
|
|
193
|
+
// path of `requestAttributes`) buffers first and trips that flush before
|
|
194
|
+
// this flow's delegation request — issued only once the key is ready — is
|
|
195
|
+
// buffered, splitting what should be one redirect into two.
|
|
196
|
+
//
|
|
197
|
+
// The key is captured in a closure, not read back after the producer: on
|
|
198
|
+
// the FIRST load the producer sets `acquired`, so the delegation request
|
|
199
|
+
// that follows is issued with no intervening storage read — a read there
|
|
200
|
+
// would re-open the very flush gap this closes. The producer is skipped on
|
|
201
|
+
// the replay load (its result is journaled), where the key is instead
|
|
202
|
+
// restored from storage. Only the id is journaled; the key lives in storage.
|
|
203
|
+
let acquired = null;
|
|
204
|
+
await transport.memoize(async () => {
|
|
205
|
+
acquired = await restoreKeyAt(this.#storage, pendingKeySlot);
|
|
206
|
+
if (acquired === null) {
|
|
207
|
+
acquired = await generateKey(keyType);
|
|
208
|
+
await this.#storage.set(pendingKeySlot, serializeKey(acquired));
|
|
209
|
+
}
|
|
210
|
+
return keyId;
|
|
211
|
+
});
|
|
212
|
+
const key = acquired ?? (await restoreKeyAt(this.#storage, pendingKeySlot));
|
|
213
|
+
if (key === null) {
|
|
214
|
+
throw new Error('Session key missing after acquisition');
|
|
215
|
+
}
|
|
216
|
+
return { key, pendingKeySlot };
|
|
217
|
+
}
|
|
123
218
|
/**
|
|
124
219
|
* Requests signed identity attributes from the identity provider.
|
|
125
220
|
*
|
|
126
|
-
* The `nonce`
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
221
|
+
* The `nonce` is a callback that produces the 32-byte nonce (typically
|
|
222
|
+
* fetched from the RP canister), returning a promise resolving to it. It is a
|
|
223
|
+
* callback rather than a value so the redirect flow can journal the nonce and
|
|
224
|
+
* reuse the exact same bytes when the flow replays on the return load,
|
|
225
|
+
* instead of fetching a fresh single-use nonce that the signer never signed
|
|
226
|
+
* against.
|
|
227
|
+
*
|
|
228
|
+
* In 'window' mode the callback lets the identity provider window open while the
|
|
229
|
+
* nonce is still resolving, avoiding a perceived delay before the user sees
|
|
230
|
+
* the prompt; auto-close of the signer transport channel is temporarily
|
|
231
|
+
* disabled while awaiting so the window cannot be closed out from under the
|
|
232
|
+
* pending flow.
|
|
132
233
|
*
|
|
133
234
|
* @param params - Request parameters.
|
|
134
235
|
* @param params.keys - Attribute keys to request (e.g. `['email', 'name']`).
|
|
135
|
-
* @param params.nonce - 32-byte nonce issued by the RP canister,
|
|
136
|
-
* resolving to
|
|
236
|
+
* @param params.nonce - Produces the 32-byte nonce issued by the RP canister,
|
|
237
|
+
* as a promise resolving to it.
|
|
137
238
|
* @returns Signed attribute data and signature.
|
|
138
239
|
* @throws When the identity provider returns an error or an invalid response.
|
|
139
240
|
*/
|
|
140
241
|
async requestAttributes(params) {
|
|
141
|
-
|
|
242
|
+
// In redirect mode the nonce is journaled (base64, since the journal is
|
|
243
|
+
// JSON) so the replay on the return load signs against the same bytes.
|
|
244
|
+
const nonceBytes = this.#urlTransport
|
|
245
|
+
? fromBase64(await this.#urlTransport.memoize(async () => toBase64(await params.nonce())))
|
|
246
|
+
: await this.#resolveNonce(params.nonce);
|
|
142
247
|
const response = await this.#signer.sendRequest({
|
|
143
248
|
jsonrpc: '2.0',
|
|
144
249
|
id: globalThis.crypto.randomUUID(),
|
|
@@ -162,6 +267,12 @@ export class AuthClient {
|
|
|
162
267
|
throw new Error('Invalid response: data or signature is not valid base64', { cause });
|
|
163
268
|
}
|
|
164
269
|
}
|
|
270
|
+
memoize(produce) {
|
|
271
|
+
if (this.#urlTransport) {
|
|
272
|
+
return this.#urlTransport.memoize(produce);
|
|
273
|
+
}
|
|
274
|
+
return produce();
|
|
275
|
+
}
|
|
165
276
|
/**
|
|
166
277
|
* Clears the stored session and resets the client to an anonymous state.
|
|
167
278
|
*
|
|
@@ -181,21 +292,19 @@ export class AuthClient {
|
|
|
181
292
|
}
|
|
182
293
|
}
|
|
183
294
|
}
|
|
184
|
-
//
|
|
185
|
-
//
|
|
295
|
+
// Popup-mode nonce resolution. Start the fetch, then open the transport
|
|
296
|
+
// channel so the identity provider window is visible while we wait, and
|
|
186
297
|
// suspend auto-close so it can't fire mid-await (e.g. due to a close
|
|
187
298
|
// scheduled by a prior request on the same signer). The original auto-close
|
|
188
299
|
// setting is restored before sendRequest, so the next response resumes
|
|
189
300
|
// normal close behaviour.
|
|
190
301
|
async #resolveNonce(nonce) {
|
|
191
|
-
|
|
192
|
-
return nonce;
|
|
193
|
-
}
|
|
302
|
+
const value = nonce();
|
|
194
303
|
await this.#signer.openChannel();
|
|
195
304
|
const previousAutoClose = this.#signer.autoCloseTransportChannel;
|
|
196
305
|
this.#signer.autoCloseTransportChannel = false;
|
|
197
306
|
try {
|
|
198
|
-
return await
|
|
307
|
+
return await value;
|
|
199
308
|
}
|
|
200
309
|
finally {
|
|
201
310
|
this.#signer.autoCloseTransportChannel = previousAutoClose;
|
|
@@ -315,6 +424,28 @@ async function restoreKey(storage, keyType) {
|
|
|
315
424
|
return null;
|
|
316
425
|
}
|
|
317
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Loads a session key from a specific storage slot, deserializing by stored
|
|
429
|
+
* shape (`CryptoKeyPair` → ECDSA, JSON string → Ed25519). Unlike
|
|
430
|
+
* {@link restoreKey} it does not migrate from localStorage — it reads only the
|
|
431
|
+
* given slot, as used for a redirect flow's per-flow pending key.
|
|
432
|
+
* @param storage - The storage backend.
|
|
433
|
+
* @param storageKey - The slot to read.
|
|
434
|
+
*/
|
|
435
|
+
async function restoreKeyAt(storage, storageKey) {
|
|
436
|
+
const stored = await storage.get(storageKey);
|
|
437
|
+
if (!stored)
|
|
438
|
+
return null;
|
|
439
|
+
try {
|
|
440
|
+
if (typeof stored === 'object') {
|
|
441
|
+
return await ECDSAKeyIdentity.fromKeyPair(stored);
|
|
442
|
+
}
|
|
443
|
+
return Ed25519KeyIdentity.fromJSON(stored);
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
318
449
|
/**
|
|
319
450
|
* Converts a key into a format suitable for storage.
|
|
320
451
|
* @param key - The key to serialize.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../../src/client/auth-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth-client.js","sourceRoot":"","sources":["../../../src/client/auth-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@icp-sdk/auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.1",
|
|
4
4
|
"author": "DFINITY Stiftung <sdk@dfinity.org>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Authentication library for Internet Computer web apps",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@icp-sdk/core": "^5"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@icp-sdk/signer": "^5.
|
|
57
|
+
"@icp-sdk/signer": "^5.6.0",
|
|
58
58
|
"idb": "^7.1.1"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '@icp-sdk/core/identity';
|
|
11
11
|
import type { Principal } from '@icp-sdk/core/principal';
|
|
12
12
|
import { Signer } from '@icp-sdk/signer';
|
|
13
|
-
import { PostMessageTransport } from '@icp-sdk/signer/web';
|
|
13
|
+
import { PostMessageTransport, UrlTransport } from '@icp-sdk/signer/web';
|
|
14
14
|
import { IdleManager, type IdleManagerOptions } from './idle-manager.js';
|
|
15
15
|
import {
|
|
16
16
|
type AuthClientStorage,
|
|
@@ -37,6 +37,11 @@ type BaseKeyType = typeof ECDSA_KEY_LABEL | typeof ED25519_KEY_LABEL;
|
|
|
37
37
|
// isAuthenticated() can answer synchronously without hitting IndexedDB.
|
|
38
38
|
const KEY_STORAGE_EXPIRATION = 'ic-delegation_expiration';
|
|
39
39
|
|
|
40
|
+
// Storage key prefix for a redirect flow's session key, held only while the
|
|
41
|
+
// flow is in progress (keyed by a per-flow id) and removed once the delegation
|
|
42
|
+
// is persisted. See AuthClient.#acquireSessionKey.
|
|
43
|
+
const PENDING_KEY_PREFIX = 'ic-auth-pending-key:';
|
|
44
|
+
|
|
40
45
|
export type OpenIdProvider = 'google' | 'apple' | 'microsoft';
|
|
41
46
|
|
|
42
47
|
export const OPENID_PROVIDER_URLS = {
|
|
@@ -94,6 +99,30 @@ export interface AuthClientCreateOptions {
|
|
|
94
99
|
*/
|
|
95
100
|
windowOpenerFeatures?: string;
|
|
96
101
|
|
|
102
|
+
/**
|
|
103
|
+
* How the client communicates with the identity provider.
|
|
104
|
+
*
|
|
105
|
+
* - `'window'` (default) — the identity provider opens in a separate browser
|
|
106
|
+
* tab or window (a popup when {@link windowOpenerFeatures} is set) and
|
|
107
|
+
* communicates over the ICRC-29 `postMessage` transport.
|
|
108
|
+
* - `'redirect'` — the current page navigates to the identity provider over
|
|
109
|
+
* the ICRC-167 URL transport, which returns to this same page. The callback
|
|
110
|
+
* URL is the current page's URL (`location.origin + location.pathname`), so
|
|
111
|
+
* that page must be on an origin you control and declared in that origin's
|
|
112
|
+
* `/.well-known/ii-auth-callbacks` allow-list. Use it for full-page sign-in
|
|
113
|
+
* that shouldn't need a user gesture to open a window (e.g. redirecting on a
|
|
114
|
+
* restricted route), or native apps handing off via universal links.
|
|
115
|
+
*
|
|
116
|
+
* With `'redirect'` the page unloads on each step and the flow re-runs on the
|
|
117
|
+
* return load, so call `signIn` / `requestAttributes` directly on the page's
|
|
118
|
+
* load (not deferred behind, say, a click handler): a fresh visit starts the
|
|
119
|
+
* flow and the identity provider's return replays it to completion. Give each
|
|
120
|
+
* flow its own route so its persisted state stays isolated.
|
|
121
|
+
* @default 'window'
|
|
122
|
+
* @see https://github.com/dfinity/wg-identity-authentication/blob/main/topics/icrc_167_browser_url_transport.md
|
|
123
|
+
*/
|
|
124
|
+
transport?: 'window' | 'redirect';
|
|
125
|
+
|
|
97
126
|
/**
|
|
98
127
|
* OpenID provider for one-click sign-in. When set, the identity provider
|
|
99
128
|
* URL includes an `openid` search param so the user authenticates via
|
|
@@ -152,6 +181,9 @@ export class AuthClient {
|
|
|
152
181
|
#chain: DelegationChain | null = null;
|
|
153
182
|
#storage: AuthClientStorage;
|
|
154
183
|
#signer: Signer;
|
|
184
|
+
// Set only in redirect mode, so the redirect-specific paths (nonce/key
|
|
185
|
+
// journaling) can reach `memoize`. Undefined in the default 'window' mode.
|
|
186
|
+
#urlTransport: UrlTransport | undefined;
|
|
155
187
|
#options: AuthClientCreateOptions;
|
|
156
188
|
#initPromise: Promise<void> | null = null;
|
|
157
189
|
idleManager: IdleManager | undefined;
|
|
@@ -167,14 +199,31 @@ export class AuthClient {
|
|
|
167
199
|
identityProviderUrl.searchParams.set('openid', OPENID_PROVIDER_URLS[options.openIdProvider]);
|
|
168
200
|
}
|
|
169
201
|
|
|
170
|
-
const transport =
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
202
|
+
const transport =
|
|
203
|
+
options.transport === 'redirect'
|
|
204
|
+
? new UrlTransport({
|
|
205
|
+
url: identityProviderUrl.toString(),
|
|
206
|
+
// The callback is this page: a fresh visit starts the flow and the
|
|
207
|
+
// provider's return lands back here to replay it. Drop any query
|
|
208
|
+
// and fragment so it stays stable across the redirect.
|
|
209
|
+
callbackUrl: `${globalThis.location.origin}${globalThis.location.pathname}`,
|
|
210
|
+
})
|
|
211
|
+
: new PostMessageTransport({
|
|
212
|
+
url: identityProviderUrl.toString(),
|
|
213
|
+
windowOpenerFeatures: options.windowOpenerFeatures,
|
|
214
|
+
});
|
|
215
|
+
this.#urlTransport = transport instanceof UrlTransport ? transport : undefined;
|
|
174
216
|
|
|
175
217
|
this.#signer = new Signer({
|
|
176
218
|
transport,
|
|
177
|
-
|
|
219
|
+
// Journal the derivation origin so it survives the top-level redirect: the
|
|
220
|
+
// return load reconstructs this client from a query-less callback URL, so
|
|
221
|
+
// `options.derivationOrigin` (like the identity provider) is no longer
|
|
222
|
+
// available — the memoized value replays from the journal instead.
|
|
223
|
+
// `memoize` returns synchronously for a synchronous producer, so the value
|
|
224
|
+
// is usable directly here; in the window flow it is a passthrough that runs
|
|
225
|
+
// the producer without persisting anything.
|
|
226
|
+
derivationOrigin: this.memoize(() => options.derivationOrigin?.toString()),
|
|
178
227
|
});
|
|
179
228
|
|
|
180
229
|
this.#registerDefaultIdleCallback();
|
|
@@ -220,13 +269,33 @@ export class AuthClient {
|
|
|
220
269
|
* }
|
|
221
270
|
*/
|
|
222
271
|
async signIn(options?: AuthClientSignInOptions): Promise<Identity> {
|
|
223
|
-
await this.#signer.openChannel();
|
|
224
|
-
|
|
225
272
|
const maxTimeToLive = options?.maxTimeToLive ?? DEFAULT_MAX_TIME_TO_LIVE;
|
|
273
|
+
const keyType = this.#options.keyType ?? ECDSA_KEY_LABEL;
|
|
274
|
+
|
|
275
|
+
// Start session-key acquisition BEFORE opening the channel, awaiting it only
|
|
276
|
+
// after. In the redirect flow the acquisition's first `transport.memoize`
|
|
277
|
+
// runs synchronously when invoked, so its in-flight bump lands in the same
|
|
278
|
+
// tick `signIn` is called — holding the transport's batch flush from the
|
|
279
|
+
// very start of the flow rather than only after the `openChannel` await.
|
|
280
|
+
// Under `Promise.all([signIn, requestAttributes])` this is what keeps a
|
|
281
|
+
// faster concurrent request from flushing before this flow's delegation
|
|
282
|
+
// request is buffered.
|
|
283
|
+
const sessionKeyPromise: Promise<{
|
|
284
|
+
key: SignIdentity | PartialIdentity;
|
|
285
|
+
pendingKeySlot?: string;
|
|
286
|
+
}> = this.#urlTransport
|
|
287
|
+
? this.#ensureSessionKeyForRedirectFlow(this.#urlTransport, keyType)
|
|
288
|
+
: this.#ensureSessionKeyForWindowFlow(keyType).then((key) => ({ key }));
|
|
289
|
+
// The acquisition is started eagerly, before the awaits below. If one of
|
|
290
|
+
// those throws first, `sessionKeyPromise` is never awaited, so attach a
|
|
291
|
+
// no-op rejection handler now to keep a later acquisition failure from
|
|
292
|
+
// surfacing as an unhandled rejection. The `await` below still observes a
|
|
293
|
+
// rejection and propagates it when reached.
|
|
294
|
+
void sessionKeyPromise.catch(() => undefined);
|
|
226
295
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
296
|
+
await this.#signer.openChannel();
|
|
297
|
+
|
|
298
|
+
const { key, pendingKeySlot } = await sessionKeyPromise;
|
|
230
299
|
|
|
231
300
|
const delegationChain = await this.#signer.requestDelegation({
|
|
232
301
|
publicKey: key.getPublicKey(),
|
|
@@ -253,31 +322,107 @@ export class AuthClient {
|
|
|
253
322
|
await persistChain(this.#storage, this.#chain);
|
|
254
323
|
await persistKey(this.#storage, key);
|
|
255
324
|
|
|
325
|
+
// The flow is complete: the delegation is bound to this key and stored, so
|
|
326
|
+
// the per-flow pending copy is no longer needed.
|
|
327
|
+
if (pendingKeySlot !== undefined) {
|
|
328
|
+
await this.#storage.remove(pendingKeySlot);
|
|
329
|
+
}
|
|
330
|
+
|
|
256
331
|
return this.#identity;
|
|
257
332
|
}
|
|
258
333
|
|
|
334
|
+
// Window flow: sign-in completes in a single load, so a fresh session key per
|
|
335
|
+
// sign-in is enough (or the caller-provided identity), with nothing to
|
|
336
|
+
// persist for a later load.
|
|
337
|
+
async #ensureSessionKeyForWindowFlow(
|
|
338
|
+
keyType: BaseKeyType,
|
|
339
|
+
): Promise<SignIdentity | PartialIdentity> {
|
|
340
|
+
return this.#options.identity ?? (await generateKey(keyType));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Redirect flow: `signIn` runs twice — once on the load that navigates to the
|
|
344
|
+
// identity provider, and again on the return load that replays the delegation
|
|
345
|
+
// minted for the FIRST load's key. Both runs must therefore use the same key.
|
|
346
|
+
// A per-flow key id is journaled via the transport (stable across the
|
|
347
|
+
// redirect) and the key is kept in storage under that id, so the return load
|
|
348
|
+
// restores the same key rather than generating a fresh one that would not
|
|
349
|
+
// match the replayed delegation. A caller-provided identity is already stable
|
|
350
|
+
// across the redirect, so it is used as-is with nothing persisted.
|
|
351
|
+
async #ensureSessionKeyForRedirectFlow(
|
|
352
|
+
transport: UrlTransport,
|
|
353
|
+
keyType: BaseKeyType,
|
|
354
|
+
): Promise<{ key: SignIdentity | PartialIdentity; pendingKeySlot?: string }> {
|
|
355
|
+
if (this.#options.identity !== undefined) {
|
|
356
|
+
return { key: this.#options.identity };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const keyId = await transport.memoize(() => globalThis.crypto.randomUUID());
|
|
360
|
+
const pendingKeySlot = `${PENDING_KEY_PREFIX}${keyId}`;
|
|
361
|
+
|
|
362
|
+
// Acquire the per-flow key inside a `memoize` producer so the transport
|
|
363
|
+
// holds its batch flush across the (async) key restore/generate + storage
|
|
364
|
+
// write. The transport coalesces concurrently issued requests into one
|
|
365
|
+
// redirect by flushing on a macrotask once no memoize producer is in
|
|
366
|
+
// flight; without this hold, a faster concurrent request (e.g. the nonce
|
|
367
|
+
// path of `requestAttributes`) buffers first and trips that flush before
|
|
368
|
+
// this flow's delegation request — issued only once the key is ready — is
|
|
369
|
+
// buffered, splitting what should be one redirect into two.
|
|
370
|
+
//
|
|
371
|
+
// The key is captured in a closure, not read back after the producer: on
|
|
372
|
+
// the FIRST load the producer sets `acquired`, so the delegation request
|
|
373
|
+
// that follows is issued with no intervening storage read — a read there
|
|
374
|
+
// would re-open the very flush gap this closes. The producer is skipped on
|
|
375
|
+
// the replay load (its result is journaled), where the key is instead
|
|
376
|
+
// restored from storage. Only the id is journaled; the key lives in storage.
|
|
377
|
+
let acquired: SignIdentity | PartialIdentity | null = null;
|
|
378
|
+
await transport.memoize(async () => {
|
|
379
|
+
acquired = await restoreKeyAt(this.#storage, pendingKeySlot);
|
|
380
|
+
if (acquired === null) {
|
|
381
|
+
acquired = await generateKey(keyType);
|
|
382
|
+
await this.#storage.set(pendingKeySlot, serializeKey(acquired));
|
|
383
|
+
}
|
|
384
|
+
return keyId;
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
const key = acquired ?? (await restoreKeyAt(this.#storage, pendingKeySlot));
|
|
388
|
+
if (key === null) {
|
|
389
|
+
throw new Error('Session key missing after acquisition');
|
|
390
|
+
}
|
|
391
|
+
return { key, pendingKeySlot };
|
|
392
|
+
}
|
|
393
|
+
|
|
259
394
|
/**
|
|
260
395
|
* Requests signed identity attributes from the identity provider.
|
|
261
396
|
*
|
|
262
|
-
* The `nonce`
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
397
|
+
* The `nonce` is a callback that produces the 32-byte nonce (typically
|
|
398
|
+
* fetched from the RP canister), returning a promise resolving to it. It is a
|
|
399
|
+
* callback rather than a value so the redirect flow can journal the nonce and
|
|
400
|
+
* reuse the exact same bytes when the flow replays on the return load,
|
|
401
|
+
* instead of fetching a fresh single-use nonce that the signer never signed
|
|
402
|
+
* against.
|
|
403
|
+
*
|
|
404
|
+
* In 'window' mode the callback lets the identity provider window open while the
|
|
405
|
+
* nonce is still resolving, avoiding a perceived delay before the user sees
|
|
406
|
+
* the prompt; auto-close of the signer transport channel is temporarily
|
|
407
|
+
* disabled while awaiting so the window cannot be closed out from under the
|
|
408
|
+
* pending flow.
|
|
268
409
|
*
|
|
269
410
|
* @param params - Request parameters.
|
|
270
411
|
* @param params.keys - Attribute keys to request (e.g. `['email', 'name']`).
|
|
271
|
-
* @param params.nonce - 32-byte nonce issued by the RP canister,
|
|
272
|
-
* resolving to
|
|
412
|
+
* @param params.nonce - Produces the 32-byte nonce issued by the RP canister,
|
|
413
|
+
* as a promise resolving to it.
|
|
273
414
|
* @returns Signed attribute data and signature.
|
|
274
415
|
* @throws When the identity provider returns an error or an invalid response.
|
|
275
416
|
*/
|
|
276
417
|
async requestAttributes(params: {
|
|
277
418
|
keys: string[];
|
|
278
|
-
nonce:
|
|
419
|
+
nonce: () => Promise<Uint8Array>;
|
|
279
420
|
}): Promise<SignedAttributes> {
|
|
280
|
-
|
|
421
|
+
// In redirect mode the nonce is journaled (base64, since the journal is
|
|
422
|
+
// JSON) so the replay on the return load signs against the same bytes.
|
|
423
|
+
const nonceBytes = this.#urlTransport
|
|
424
|
+
? fromBase64(await this.#urlTransport.memoize(async () => toBase64(await params.nonce())))
|
|
425
|
+
: await this.#resolveNonce(params.nonce);
|
|
281
426
|
|
|
282
427
|
const response = await this.#signer.sendRequest({
|
|
283
428
|
jsonrpc: '2.0',
|
|
@@ -305,6 +450,52 @@ export class AuthClient {
|
|
|
305
450
|
}
|
|
306
451
|
}
|
|
307
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Runs and journals a piece of your own async work so its result stays stable
|
|
455
|
+
* across the `'redirect'` flow.
|
|
456
|
+
*
|
|
457
|
+
* In `'redirect'` mode the page unloads on each step and `signIn` /
|
|
458
|
+
* `requestAttributes` re-run on the return load, so a value you compute on the
|
|
459
|
+
* first visit (from `location`, a fetch, `crypto`, …) would otherwise be
|
|
460
|
+
* recomputed — and may differ — on the return. Wrap it in `memoize`: it runs
|
|
461
|
+
* `produce` once on the first visit, journals the result, and replays that
|
|
462
|
+
* result on the return load instead of re-running. Use it for a value the
|
|
463
|
+
* post-flow code depends on, e.g. the URL to navigate to once sign-in
|
|
464
|
+
* completes:
|
|
465
|
+
*
|
|
466
|
+
* ```ts
|
|
467
|
+
* const next = await authClient.memoize(
|
|
468
|
+
* () => new URLSearchParams(location.search).get('next') ?? '/',
|
|
469
|
+
* );
|
|
470
|
+
* await authClient.signIn();
|
|
471
|
+
* location.assign(next); // the value captured before the redirect
|
|
472
|
+
* ```
|
|
473
|
+
*
|
|
474
|
+
* Call `memoize` in a stable order relative to `signIn` / `requestAttributes`
|
|
475
|
+
* across loads (same order every load — branch only on values recovered from
|
|
476
|
+
* earlier results), and keep the result JSON-serializable, since the journal
|
|
477
|
+
* is JSON.
|
|
478
|
+
*
|
|
479
|
+
* In `'window'` mode there is no redirect, so this simply runs `produce` and
|
|
480
|
+
* returns its result without persisting anything.
|
|
481
|
+
*
|
|
482
|
+
* Mirrors the producer's shape: a synchronous `produce` returns its value
|
|
483
|
+
* directly, an asynchronous one returns a promise. Awaiting the result is
|
|
484
|
+
* always safe (`await` on a non-promise is a no-op); the synchronous form lets
|
|
485
|
+
* a value be memoized where an `await` is not possible, such as in a
|
|
486
|
+
* constructor.
|
|
487
|
+
* @param produce - Produces the value to journal on the first load.
|
|
488
|
+
* @returns The produced value, or the journaled value on a replay load.
|
|
489
|
+
*/
|
|
490
|
+
memoize<T>(produce: () => Promise<T>): Promise<T>;
|
|
491
|
+
memoize<T>(produce: () => T): T;
|
|
492
|
+
memoize<T>(produce: () => T | Promise<T>): T | Promise<T> {
|
|
493
|
+
if (this.#urlTransport) {
|
|
494
|
+
return this.#urlTransport.memoize(produce);
|
|
495
|
+
}
|
|
496
|
+
return produce();
|
|
497
|
+
}
|
|
498
|
+
|
|
308
499
|
/**
|
|
309
500
|
* Clears the stored session and resets the client to an anonymous state.
|
|
310
501
|
*
|
|
@@ -326,22 +517,19 @@ export class AuthClient {
|
|
|
326
517
|
}
|
|
327
518
|
}
|
|
328
519
|
|
|
329
|
-
//
|
|
330
|
-
//
|
|
520
|
+
// Popup-mode nonce resolution. Start the fetch, then open the transport
|
|
521
|
+
// channel so the identity provider window is visible while we wait, and
|
|
331
522
|
// suspend auto-close so it can't fire mid-await (e.g. due to a close
|
|
332
523
|
// scheduled by a prior request on the same signer). The original auto-close
|
|
333
524
|
// setting is restored before sendRequest, so the next response resumes
|
|
334
525
|
// normal close behaviour.
|
|
335
|
-
async #resolveNonce(nonce:
|
|
336
|
-
|
|
337
|
-
return nonce;
|
|
338
|
-
}
|
|
339
|
-
|
|
526
|
+
async #resolveNonce(nonce: () => Promise<Uint8Array>): Promise<Uint8Array> {
|
|
527
|
+
const value = nonce();
|
|
340
528
|
await this.#signer.openChannel();
|
|
341
529
|
const previousAutoClose = this.#signer.autoCloseTransportChannel;
|
|
342
530
|
this.#signer.autoCloseTransportChannel = false;
|
|
343
531
|
try {
|
|
344
|
-
return await
|
|
532
|
+
return await value;
|
|
345
533
|
} finally {
|
|
346
534
|
this.#signer.autoCloseTransportChannel = previousAutoClose;
|
|
347
535
|
}
|
|
@@ -475,6 +663,31 @@ async function restoreKey(
|
|
|
475
663
|
}
|
|
476
664
|
}
|
|
477
665
|
|
|
666
|
+
/**
|
|
667
|
+
* Loads a session key from a specific storage slot, deserializing by stored
|
|
668
|
+
* shape (`CryptoKeyPair` → ECDSA, JSON string → Ed25519). Unlike
|
|
669
|
+
* {@link restoreKey} it does not migrate from localStorage — it reads only the
|
|
670
|
+
* given slot, as used for a redirect flow's per-flow pending key.
|
|
671
|
+
* @param storage - The storage backend.
|
|
672
|
+
* @param storageKey - The slot to read.
|
|
673
|
+
*/
|
|
674
|
+
async function restoreKeyAt(
|
|
675
|
+
storage: AuthClientStorage,
|
|
676
|
+
storageKey: string,
|
|
677
|
+
): Promise<SignIdentity | PartialIdentity | null> {
|
|
678
|
+
const stored = await storage.get(storageKey);
|
|
679
|
+
if (!stored) return null;
|
|
680
|
+
|
|
681
|
+
try {
|
|
682
|
+
if (typeof stored === 'object') {
|
|
683
|
+
return await ECDSAKeyIdentity.fromKeyPair(stored);
|
|
684
|
+
}
|
|
685
|
+
return Ed25519KeyIdentity.fromJSON(stored);
|
|
686
|
+
} catch {
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
478
691
|
/**
|
|
479
692
|
* Converts a key into a format suitable for storage.
|
|
480
693
|
* @param key - The key to serialize.
|