@ic-reactor/core 3.3.1 → 3.5.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 +60 -0
- package/dist/client.d.ts +28 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +286 -57
- package/dist/client.js.map +1 -1
- package/dist/identity-attributes.d.ts +14 -0
- package/dist/identity-attributes.d.ts.map +1 -0
- package/dist/identity-attributes.js +161 -0
- package/dist/identity-attributes.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/client.d.ts +68 -2
- package/dist/types/client.d.ts.map +1 -1
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/package.json +11 -11
- package/src/client.ts +382 -61
- package/src/identity-attributes.ts +256 -0
- package/src/index.ts +1 -0
- package/src/types/client.ts +82 -2
- package/src/utils/constants.ts +1 -1
package/src/client.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { Identity } from "@icp-sdk/core/agent"
|
|
2
|
-
import type { AuthClient, AuthClientLoginOptions } from "@icp-sdk/auth/client"
|
|
3
2
|
import type {
|
|
4
3
|
ClientManagerParameters,
|
|
5
4
|
AgentState,
|
|
6
5
|
AuthState,
|
|
6
|
+
AuthClientSignInOptions,
|
|
7
|
+
AuthClientLike,
|
|
8
|
+
ClientManagerAuthClientOptions,
|
|
9
|
+
ClientManagerSignInOptions,
|
|
10
|
+
IdentityAttributeResult,
|
|
11
|
+
RequestIdentityAttributesParameters,
|
|
12
|
+
RequestOpenIdIdentityAttributesParameters,
|
|
7
13
|
} from "./types/client"
|
|
8
14
|
import type { Principal } from "@icp-sdk/core/principal"
|
|
9
15
|
import type { QueryClient } from "@tanstack/react-query"
|
|
@@ -20,6 +26,16 @@ import {
|
|
|
20
26
|
getProcessEnvNetwork,
|
|
21
27
|
isDev,
|
|
22
28
|
} from "./utils/helper"
|
|
29
|
+
import {
|
|
30
|
+
decodeIdentityAttributeValues,
|
|
31
|
+
IDENTITY_ATTRIBUTES_BETA_PROVIDER,
|
|
32
|
+
identityAttributeKeys,
|
|
33
|
+
normalizeSignedIdentityAttributes,
|
|
34
|
+
} from "./identity-attributes"
|
|
35
|
+
|
|
36
|
+
type AuthClientConstructor = {
|
|
37
|
+
new (options?: ClientManagerAuthClientOptions): AuthClientLike
|
|
38
|
+
}
|
|
23
39
|
|
|
24
40
|
/**
|
|
25
41
|
* ClientManager is a central class for managing the Internet Computer (IC) agent and authentication state.
|
|
@@ -43,7 +59,7 @@ import {
|
|
|
43
59
|
*/
|
|
44
60
|
export class ClientManager {
|
|
45
61
|
#agent: HttpAgent
|
|
46
|
-
#authClient?:
|
|
62
|
+
#authClient?: AuthClientLike
|
|
47
63
|
#identitySubscribers: Array<(identity: Identity) => void> = []
|
|
48
64
|
#agentStateSubscribers: Array<(state: AgentState) => void> = []
|
|
49
65
|
#authStateSubscribers: Array<(state: AuthState) => void> = []
|
|
@@ -64,6 +80,12 @@ export class ClientManager {
|
|
|
64
80
|
|
|
65
81
|
private initPromise?: Promise<void>
|
|
66
82
|
private authPromise?: Promise<Identity | undefined>
|
|
83
|
+
private authClientConstructor?: AuthClientConstructor
|
|
84
|
+
private authClientConstructorPromise?: Promise<
|
|
85
|
+
AuthClientConstructor | undefined
|
|
86
|
+
>
|
|
87
|
+
private authStateRevision = 0
|
|
88
|
+
private authClientWasProvided = false
|
|
67
89
|
private port: number
|
|
68
90
|
private internetIdentityId?: string
|
|
69
91
|
|
|
@@ -164,15 +186,15 @@ export class ClientManager {
|
|
|
164
186
|
})
|
|
165
187
|
|
|
166
188
|
if (authClient) {
|
|
189
|
+
this.authClientWasProvided = true
|
|
167
190
|
this.#authClient = authClient
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
191
|
+
this.syncAuthStateFromClient(this.authStateRevision).catch((error) => {
|
|
192
|
+
this.updateAuthState({ error: error as Error, isAuthenticating: false })
|
|
193
|
+
})
|
|
194
|
+
} else if (typeof window !== "undefined") {
|
|
195
|
+
this.loadAuthClientConstructor().catch(() => {
|
|
196
|
+
// Optional auth support is reported when an auth method is used.
|
|
197
|
+
})
|
|
176
198
|
}
|
|
177
199
|
}
|
|
178
200
|
|
|
@@ -189,6 +211,25 @@ export class ClientManager {
|
|
|
189
211
|
return this
|
|
190
212
|
}
|
|
191
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Preloads and creates an AuthClient before a user gesture is needed.
|
|
216
|
+
*
|
|
217
|
+
* Browser signer transports must open their channel directly from a click
|
|
218
|
+
* handler. Apps that pass dynamic auth options, such as OpenID provider
|
|
219
|
+
* aliases, can call this from hover/focus/effect code so the later click path
|
|
220
|
+
* can call signIn/requestAttributes without first awaiting a dynamic import.
|
|
221
|
+
*/
|
|
222
|
+
public async prepareAuthClient(options?: ClientManagerAuthClientOptions) {
|
|
223
|
+
if (
|
|
224
|
+
this.#authClient &&
|
|
225
|
+
(!this.shouldRecreateAuthClient(options) || this.authClientWasProvided)
|
|
226
|
+
) {
|
|
227
|
+
return this.#authClient
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return this.initializeAuthClient(options)
|
|
231
|
+
}
|
|
232
|
+
|
|
192
233
|
/**
|
|
193
234
|
* Specifically initializes the HttpAgent.
|
|
194
235
|
* On local networks, this includes fetching the root key for certificate verification.
|
|
@@ -274,25 +315,18 @@ export class ClientManager {
|
|
|
274
315
|
this.updateAuthState({ isAuthenticating: true })
|
|
275
316
|
try {
|
|
276
317
|
if (!this.#authClient) {
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
return null
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
if (!authModule) {
|
|
283
|
-
this.authModuleMissing = true
|
|
318
|
+
const authClient = await this.initializeAuthClient()
|
|
319
|
+
if (!authClient) {
|
|
284
320
|
this.updateAuthState({ isAuthenticating: false })
|
|
285
321
|
return undefined
|
|
286
322
|
}
|
|
287
|
-
|
|
288
|
-
const { AuthClient } = authModule
|
|
289
|
-
this.#authClient = await AuthClient.create()
|
|
290
323
|
}
|
|
291
|
-
const identity = this.#authClient
|
|
324
|
+
const identity = await this.#authClient!.getIdentity()
|
|
325
|
+
const isAuthenticated = await this.#authClient!.isAuthenticated()
|
|
292
326
|
this.updateAgent(identity)
|
|
293
327
|
this.updateAuthState({
|
|
294
328
|
identity,
|
|
295
|
-
isAuthenticated
|
|
329
|
+
isAuthenticated,
|
|
296
330
|
isAuthenticating: false,
|
|
297
331
|
})
|
|
298
332
|
return identity
|
|
@@ -314,11 +348,19 @@ export class ClientManager {
|
|
|
314
348
|
* @param loginOptions - Options for the login flow, including identity provider and callbacks.
|
|
315
349
|
* @throws An error if the authentication module is not installed.
|
|
316
350
|
*/
|
|
317
|
-
public login = async (loginOptions?:
|
|
351
|
+
public login = async (loginOptions?: ClientManagerSignInOptions) => {
|
|
352
|
+
let didCompleteSignIn = false
|
|
353
|
+
|
|
318
354
|
try {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
355
|
+
const identityProvider =
|
|
356
|
+
loginOptions?.identityProvider || this.getDefaultIdentityProvider()
|
|
357
|
+
const authClientOptions = getAuthClientOptions({
|
|
358
|
+
...loginOptions,
|
|
359
|
+
identityProvider,
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
if (!this.ensurePreparedAuthClient(authClientOptions)) {
|
|
363
|
+
await this.initializeAuthClient(authClientOptions)
|
|
322
364
|
}
|
|
323
365
|
|
|
324
366
|
if (!this.#authClient) {
|
|
@@ -333,38 +375,39 @@ export class ClientManager {
|
|
|
333
375
|
|
|
334
376
|
this.updateAuthState({ isAuthenticating: true, error: undefined })
|
|
335
377
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
378
|
+
const identity = await this.signInOrRecoverAuthenticatedIdentity(
|
|
379
|
+
getSignInOptions(loginOptions)
|
|
380
|
+
)
|
|
339
381
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if (identity) {
|
|
346
|
-
this.updateAgent(identity)
|
|
347
|
-
this.updateAuthState({
|
|
348
|
-
identity,
|
|
349
|
-
isAuthenticated: true,
|
|
350
|
-
isAuthenticating: false,
|
|
351
|
-
})
|
|
352
|
-
}
|
|
353
|
-
;(loginOptions?.onSuccess as any)?.()
|
|
354
|
-
},
|
|
355
|
-
onError: (error) => {
|
|
356
|
-
this.updateAuthState({
|
|
357
|
-
error: new Error(error),
|
|
358
|
-
isAuthenticating: false,
|
|
359
|
-
})
|
|
360
|
-
loginOptions?.onError?.(error)
|
|
361
|
-
},
|
|
362
|
-
})
|
|
363
|
-
} catch (error) {
|
|
382
|
+
if (!this.agentState.isInitialized) {
|
|
383
|
+
await this.initializeAgent()
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
this.updateAgent(identity)
|
|
364
387
|
this.updateAuthState({
|
|
365
|
-
|
|
388
|
+
identity,
|
|
389
|
+
isAuthenticated: true,
|
|
366
390
|
isAuthenticating: false,
|
|
367
391
|
})
|
|
392
|
+
didCompleteSignIn = true
|
|
393
|
+
|
|
394
|
+
try {
|
|
395
|
+
await (
|
|
396
|
+
loginOptions?.onSuccess as (() => void | Promise<void>) | undefined
|
|
397
|
+
)?.()
|
|
398
|
+
} catch (callbackError) {
|
|
399
|
+
this.updateAuthState({ error: callbackError as Error })
|
|
400
|
+
await loginOptions?.onError?.((callbackError as Error).message)
|
|
401
|
+
throw callbackError
|
|
402
|
+
}
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if (!didCompleteSignIn) {
|
|
405
|
+
await loginOptions?.onError?.((error as Error).message)
|
|
406
|
+
this.updateAuthState({
|
|
407
|
+
error: error as Error,
|
|
408
|
+
isAuthenticating: false,
|
|
409
|
+
})
|
|
410
|
+
}
|
|
368
411
|
throw error
|
|
369
412
|
}
|
|
370
413
|
}
|
|
@@ -374,25 +417,125 @@ export class ClientManager {
|
|
|
374
417
|
*
|
|
375
418
|
* @throws An error if the authentication module is not installed.
|
|
376
419
|
*/
|
|
377
|
-
public logout = async () => {
|
|
420
|
+
public logout = async (options?: { returnTo?: string }) => {
|
|
378
421
|
if (!this.#authClient) {
|
|
379
422
|
throw new Error(
|
|
380
423
|
"Authentication module is missing or failed to initialize. To use logout, please install the auth package: npm install @icp-sdk/auth"
|
|
381
424
|
)
|
|
382
425
|
}
|
|
383
426
|
this.updateAuthState({ isAuthenticating: true, error: undefined })
|
|
384
|
-
await this.#authClient.logout()
|
|
385
|
-
const identity = this.#authClient.getIdentity()
|
|
386
|
-
|
|
387
|
-
|
|
427
|
+
await this.#authClient.logout(options)
|
|
428
|
+
const identity = await this.#authClient.getIdentity()
|
|
429
|
+
this.updateAgent(identity)
|
|
430
|
+
this.updateAuthState({
|
|
431
|
+
identity,
|
|
432
|
+
isAuthenticated: false,
|
|
433
|
+
isAuthenticating: false,
|
|
434
|
+
})
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
public requestIdentityAttributes = async ({
|
|
438
|
+
keys,
|
|
439
|
+
nonce,
|
|
440
|
+
identityProvider = IDENTITY_ATTRIBUTES_BETA_PROVIDER,
|
|
441
|
+
openIdProvider,
|
|
442
|
+
windowOpenerFeatures,
|
|
443
|
+
signIn = true,
|
|
444
|
+
maxTimeToLive,
|
|
445
|
+
targets,
|
|
446
|
+
}: RequestIdentityAttributesParameters): Promise<IdentityAttributeResult> => {
|
|
447
|
+
const authClientOptions = getAuthClientOptions({
|
|
448
|
+
identityProvider,
|
|
449
|
+
windowOpenerFeatures,
|
|
450
|
+
openIdProvider,
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
if (!this.ensurePreparedAuthClient(authClientOptions)) {
|
|
454
|
+
await this.initializeAuthClient(authClientOptions)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (!this.#authClient) {
|
|
458
|
+
await this.authenticate()
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (!this.#authClient) {
|
|
462
|
+
throw new Error(
|
|
463
|
+
"Authentication module is missing or failed to initialize. To request identity attributes, please install @icp-sdk/auth v6 or provide a compatible authClient."
|
|
464
|
+
)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
this.updateAuthState({ isAuthenticating: true, error: undefined })
|
|
468
|
+
|
|
469
|
+
try {
|
|
470
|
+
const identityPromise = signIn
|
|
471
|
+
? this.signInOrRecoverAuthenticatedIdentity({
|
|
472
|
+
maxTimeToLive,
|
|
473
|
+
targets,
|
|
474
|
+
})
|
|
475
|
+
: Promise.resolve(this.#authClient.getIdentity())
|
|
476
|
+
const requestPromise = this.#authClient.requestAttributes({
|
|
477
|
+
keys,
|
|
478
|
+
nonce,
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
const [signedAttributes, identity] = await Promise.all([
|
|
482
|
+
requestPromise,
|
|
483
|
+
identityPromise,
|
|
484
|
+
])
|
|
485
|
+
|
|
486
|
+
const finalIdentity = identity ?? (await this.#authClient.getIdentity())
|
|
487
|
+
const isAuthenticated = await this.#authClient.isAuthenticated()
|
|
488
|
+
if (!this.agentState.isInitialized) {
|
|
489
|
+
await this.initializeAgent()
|
|
490
|
+
}
|
|
491
|
+
this.updateAgent(finalIdentity)
|
|
388
492
|
this.updateAuthState({
|
|
389
|
-
identity,
|
|
390
|
-
isAuthenticated
|
|
493
|
+
identity: finalIdentity,
|
|
494
|
+
isAuthenticated,
|
|
391
495
|
isAuthenticating: false,
|
|
392
496
|
})
|
|
497
|
+
|
|
498
|
+
const normalizedSignedAttributes =
|
|
499
|
+
normalizeSignedIdentityAttributes(signedAttributes)
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
principal: finalIdentity.getPrincipal().toText(),
|
|
503
|
+
requestedKeys: keys,
|
|
504
|
+
signedAttributes: normalizedSignedAttributes,
|
|
505
|
+
decodedAttributes: decodeIdentityAttributeValues(
|
|
506
|
+
normalizedSignedAttributes.data,
|
|
507
|
+
keys
|
|
508
|
+
),
|
|
509
|
+
completedAt: new Date().toISOString(),
|
|
510
|
+
}
|
|
511
|
+
} catch (error) {
|
|
512
|
+
this.updateAuthState({ error: error as Error, isAuthenticating: false })
|
|
513
|
+
throw error
|
|
393
514
|
}
|
|
394
515
|
}
|
|
395
516
|
|
|
517
|
+
public requestOpenIdIdentityAttributes = async ({
|
|
518
|
+
nonce,
|
|
519
|
+
openIdProvider,
|
|
520
|
+
keys,
|
|
521
|
+
identityProvider = IDENTITY_ATTRIBUTES_BETA_PROVIDER,
|
|
522
|
+
windowOpenerFeatures,
|
|
523
|
+
signIn,
|
|
524
|
+
maxTimeToLive,
|
|
525
|
+
targets,
|
|
526
|
+
}: RequestOpenIdIdentityAttributesParameters): Promise<IdentityAttributeResult> => {
|
|
527
|
+
return this.requestIdentityAttributes({
|
|
528
|
+
keys: identityAttributeKeys({ openIdProvider, keys }),
|
|
529
|
+
nonce,
|
|
530
|
+
identityProvider,
|
|
531
|
+
openIdProvider,
|
|
532
|
+
windowOpenerFeatures,
|
|
533
|
+
signIn,
|
|
534
|
+
maxTimeToLive,
|
|
535
|
+
targets,
|
|
536
|
+
})
|
|
537
|
+
}
|
|
538
|
+
|
|
396
539
|
/**
|
|
397
540
|
* The underlying HttpAgent managed by this class.
|
|
398
541
|
*/
|
|
@@ -407,6 +550,136 @@ export class ClientManager {
|
|
|
407
550
|
return this.#authClient
|
|
408
551
|
}
|
|
409
552
|
|
|
553
|
+
private async initializeAuthClient(
|
|
554
|
+
options?: ClientManagerAuthClientOptions
|
|
555
|
+
): Promise<AuthClientLike | undefined> {
|
|
556
|
+
const AuthClient = await this.loadAuthClientConstructor()
|
|
557
|
+
|
|
558
|
+
if (!AuthClient) {
|
|
559
|
+
return undefined
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
this.#authClient = this.createAuthClient(AuthClient, options)
|
|
563
|
+
return this.#authClient
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
private async signInOrRecoverAuthenticatedIdentity(
|
|
567
|
+
options?: AuthClientSignInOptions
|
|
568
|
+
): Promise<Identity> {
|
|
569
|
+
if (!this.#authClient) {
|
|
570
|
+
throw new Error(
|
|
571
|
+
"Authentication module is missing or failed to initialize. To use login, please install the auth package: npm install @icp-sdk/auth"
|
|
572
|
+
)
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
try {
|
|
576
|
+
return await this.#authClient.signIn(options)
|
|
577
|
+
} catch (error) {
|
|
578
|
+
const identity = await Promise.resolve(
|
|
579
|
+
this.#authClient.getIdentity()
|
|
580
|
+
).catch(() => null)
|
|
581
|
+
const isAuthenticated = await Promise.resolve(
|
|
582
|
+
this.#authClient.isAuthenticated()
|
|
583
|
+
).catch(() => false)
|
|
584
|
+
|
|
585
|
+
if (identity && isAuthenticated) {
|
|
586
|
+
return identity
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
throw error
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
private async loadAuthClientConstructor(): Promise<
|
|
594
|
+
AuthClientConstructor | undefined
|
|
595
|
+
> {
|
|
596
|
+
if (this.authClientConstructor) {
|
|
597
|
+
return this.authClientConstructor
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (!this.authClientConstructorPromise) {
|
|
601
|
+
this.authClientConstructorPromise = import("@icp-sdk/auth/client")
|
|
602
|
+
.then((authModule) => {
|
|
603
|
+
const AuthClient = (
|
|
604
|
+
authModule as { AuthClient?: AuthClientConstructor }
|
|
605
|
+
).AuthClient
|
|
606
|
+
|
|
607
|
+
if (!AuthClient) {
|
|
608
|
+
throw new Error("@icp-sdk/auth/client did not export AuthClient")
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
this.authClientConstructor = AuthClient
|
|
612
|
+
return AuthClient
|
|
613
|
+
})
|
|
614
|
+
.catch((error) => {
|
|
615
|
+
this.authModuleMissing = true
|
|
616
|
+
this.authClientConstructorPromise = undefined
|
|
617
|
+
if (
|
|
618
|
+
error instanceof Error &&
|
|
619
|
+
error.message.includes("did not export AuthClient")
|
|
620
|
+
) {
|
|
621
|
+
throw error
|
|
622
|
+
}
|
|
623
|
+
return undefined
|
|
624
|
+
})
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return this.authClientConstructorPromise
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
private createAuthClient(
|
|
631
|
+
AuthClient: AuthClientConstructor,
|
|
632
|
+
options?: ClientManagerAuthClientOptions
|
|
633
|
+
): AuthClientLike {
|
|
634
|
+
return new AuthClient(options)
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
private ensurePreparedAuthClient(
|
|
638
|
+
options?: ClientManagerAuthClientOptions
|
|
639
|
+
): AuthClientLike | undefined {
|
|
640
|
+
if (
|
|
641
|
+
this.#authClient &&
|
|
642
|
+
(!this.shouldRecreateAuthClient(options) || this.authClientWasProvided)
|
|
643
|
+
) {
|
|
644
|
+
return this.#authClient
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (!this.authClientConstructor || this.authClientWasProvided) {
|
|
648
|
+
return undefined
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
this.#authClient = this.createAuthClient(
|
|
652
|
+
this.authClientConstructor,
|
|
653
|
+
options
|
|
654
|
+
)
|
|
655
|
+
return this.#authClient
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private shouldRecreateAuthClient(
|
|
659
|
+
options?: ClientManagerAuthClientOptions
|
|
660
|
+
): boolean {
|
|
661
|
+
return !this.authClientWasProvided && hasAuthClientOptions(options)
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
private async syncAuthStateFromClient(revision = this.authStateRevision) {
|
|
665
|
+
if (!this.#authClient) {
|
|
666
|
+
return
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const identity = await this.#authClient.getIdentity()
|
|
670
|
+
const isAuthenticated = await this.#authClient.isAuthenticated()
|
|
671
|
+
if (revision !== this.authStateRevision) {
|
|
672
|
+
return
|
|
673
|
+
}
|
|
674
|
+
this.updateAgent(identity)
|
|
675
|
+
this.updateAuthState({
|
|
676
|
+
identity,
|
|
677
|
+
isAuthenticated,
|
|
678
|
+
isAuthenticating: false,
|
|
679
|
+
error: undefined,
|
|
680
|
+
})
|
|
681
|
+
}
|
|
682
|
+
|
|
410
683
|
/**
|
|
411
684
|
* The host URL of the current IC agent.
|
|
412
685
|
*/
|
|
@@ -585,7 +858,55 @@ export class ClientManager {
|
|
|
585
858
|
|
|
586
859
|
private updateAuthState(newState: Partial<AuthState>) {
|
|
587
860
|
if (isDev()) console.debug("[ic-reactor] Updating Auth State:", newState)
|
|
861
|
+
this.authStateRevision += 1
|
|
588
862
|
this.authState = { ...this.authState, ...newState }
|
|
589
863
|
this.notifyAuthStateSubscribers(this.authState)
|
|
590
864
|
}
|
|
591
865
|
}
|
|
866
|
+
|
|
867
|
+
function getAuthClientOptions(
|
|
868
|
+
options?: ClientManagerAuthClientOptions
|
|
869
|
+
): ClientManagerAuthClientOptions | undefined {
|
|
870
|
+
if (!options) {
|
|
871
|
+
return undefined
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
return {
|
|
875
|
+
identityProvider: options.identityProvider,
|
|
876
|
+
windowOpenerFeatures: options.windowOpenerFeatures,
|
|
877
|
+
openIdProvider: getAuthClientOpenIdProvider(options.openIdProvider),
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
function getAuthClientOpenIdProvider(
|
|
882
|
+
openIdProvider?: ClientManagerAuthClientOptions["openIdProvider"]
|
|
883
|
+
): ClientManagerAuthClientOptions["openIdProvider"] | undefined {
|
|
884
|
+
return openIdProvider === "google" ||
|
|
885
|
+
openIdProvider === "apple" ||
|
|
886
|
+
openIdProvider === "microsoft"
|
|
887
|
+
? openIdProvider
|
|
888
|
+
: undefined
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
function hasAuthClientOptions(
|
|
892
|
+
options?: ClientManagerAuthClientOptions
|
|
893
|
+
): boolean {
|
|
894
|
+
return Boolean(
|
|
895
|
+
options?.identityProvider ||
|
|
896
|
+
options?.windowOpenerFeatures ||
|
|
897
|
+
options?.openIdProvider
|
|
898
|
+
)
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
function getSignInOptions(
|
|
902
|
+
options?: ClientManagerSignInOptions
|
|
903
|
+
): AuthClientSignInOptions | undefined {
|
|
904
|
+
if (!options) {
|
|
905
|
+
return undefined
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
return {
|
|
909
|
+
maxTimeToLive: options.maxTimeToLive,
|
|
910
|
+
targets: options.targets,
|
|
911
|
+
}
|
|
912
|
+
}
|