@0xsequence/wallet-wdk 3.0.1 → 3.0.3
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +24 -0
- package/dist/sequence/handlers/authcode.d.ts.map +1 -1
- package/dist/sequence/handlers/authcode.js +6 -0
- package/dist/sequence/handlers/identity.d.ts +1 -0
- package/dist/sequence/handlers/identity.d.ts.map +1 -1
- package/dist/sequence/handlers/identity.js +3 -0
- package/dist/sequence/handlers/idtoken.d.ts +33 -0
- package/dist/sequence/handlers/idtoken.d.ts.map +1 -0
- package/dist/sequence/handlers/idtoken.js +110 -0
- package/dist/sequence/handlers/index.d.ts +1 -0
- package/dist/sequence/handlers/index.d.ts.map +1 -1
- package/dist/sequence/handlers/index.js +1 -0
- package/dist/sequence/manager.d.ts +20 -14
- package/dist/sequence/manager.d.ts.map +1 -1
- package/dist/sequence/manager.js +21 -3
- package/dist/sequence/sessions.d.ts.map +1 -1
- package/dist/sequence/sessions.js +5 -1
- package/dist/sequence/signers.d.ts.map +1 -1
- package/dist/sequence/signers.js +4 -0
- package/dist/sequence/types/signer.d.ts +1 -1
- package/dist/sequence/types/signer.js +1 -1
- package/dist/sequence/types/wallet.d.ts +1 -1
- package/dist/sequence/wallets.d.ts +7 -1
- package/dist/sequence/wallets.d.ts.map +1 -1
- package/dist/sequence/wallets.js +69 -7
- package/package.json +6 -6
- package/src/sequence/handlers/authcode.ts +6 -0
- package/src/sequence/handlers/identity.ts +4 -0
- package/src/sequence/handlers/idtoken.ts +140 -0
- package/src/sequence/handlers/index.ts +1 -0
- package/src/sequence/manager.ts +78 -29
- package/src/sequence/sessions.ts +7 -1
- package/src/sequence/signers.ts +5 -0
- package/src/sequence/types/signer.ts +1 -1
- package/src/sequence/types/wallet.ts +1 -1
- package/src/sequence/wallets.ts +88 -9
- package/test/authcode-pkce.test.ts +1 -1
- package/test/authcode.test.ts +2 -2
- package/test/identity-auth-dbs.test.ts +86 -2
- package/test/identity-signer.test.ts +1 -1
- package/test/idtoken.test.ts +327 -0
- package/test/sessions-idtoken.test.ts +97 -0
- package/test/signers-kindof.test.ts +22 -0
- package/test/transactions.test.ts +19 -0
- package/test/wallets.test.ts +141 -1
package/dist/sequence/wallets.js
CHANGED
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
import { Wallet as CoreWallet, Envelope, Signers, State } from '@0xsequence/wallet-core';
|
|
2
2
|
import { Config, Constants, Payload } from '@0xsequence/wallet-primitives';
|
|
3
3
|
import { Address, Provider, RpcTransport } from 'ox';
|
|
4
|
+
import { AuthCodeHandler } from './handlers/authcode.js';
|
|
5
|
+
import { IdTokenHandler } from './handlers/idtoken.js';
|
|
4
6
|
import { MnemonicHandler } from './handlers/mnemonic.js';
|
|
5
7
|
import { Kinds } from './types/signer.js';
|
|
8
|
+
function getSignupHandlerKey(kind) {
|
|
9
|
+
if (kind === 'google-pkce') {
|
|
10
|
+
return Kinds.LoginGoogle;
|
|
11
|
+
}
|
|
12
|
+
if (kind.startsWith('custom-')) {
|
|
13
|
+
return kind;
|
|
14
|
+
}
|
|
15
|
+
return 'login-' + kind;
|
|
16
|
+
}
|
|
17
|
+
function getSignerKindForSignup(kind) {
|
|
18
|
+
if (kind === 'google-id-token' || kind === 'google-pkce') {
|
|
19
|
+
return Kinds.LoginGoogle;
|
|
20
|
+
}
|
|
21
|
+
if (kind.startsWith('custom-')) {
|
|
22
|
+
return kind;
|
|
23
|
+
}
|
|
24
|
+
return ('login-' + kind);
|
|
25
|
+
}
|
|
26
|
+
function getIdTokenSignupHandler(shared, kind) {
|
|
27
|
+
const handler = shared.handlers.get(kind);
|
|
28
|
+
if (!handler) {
|
|
29
|
+
throw new Error('handler-not-registered');
|
|
30
|
+
}
|
|
31
|
+
if (!(handler instanceof IdTokenHandler)) {
|
|
32
|
+
throw new Error('handler-does-not-support-id-token');
|
|
33
|
+
}
|
|
34
|
+
return handler;
|
|
35
|
+
}
|
|
6
36
|
export function isLoginToWalletArgs(args) {
|
|
7
37
|
return 'wallet' in args;
|
|
8
38
|
}
|
|
@@ -13,7 +43,10 @@ export function isLoginToPasskeyArgs(args) {
|
|
|
13
43
|
return 'kind' in args && args.kind === 'passkey';
|
|
14
44
|
}
|
|
15
45
|
export function isAuthCodeArgs(args) {
|
|
16
|
-
return '
|
|
46
|
+
return 'code' in args && 'commitment' in args;
|
|
47
|
+
}
|
|
48
|
+
export function isIdTokenArgs(args) {
|
|
49
|
+
return 'idToken' in args;
|
|
17
50
|
}
|
|
18
51
|
function buildCappedTree(members) {
|
|
19
52
|
const loginMemberWeight = 1n;
|
|
@@ -277,9 +310,22 @@ export class Wallets {
|
|
|
277
310
|
loginEmail: returnedEmail,
|
|
278
311
|
};
|
|
279
312
|
}
|
|
313
|
+
case 'google-id-token': {
|
|
314
|
+
const handler = getIdTokenSignupHandler(this.shared, Kinds.LoginGoogle);
|
|
315
|
+
const [signer, metadata] = await handler.completeAuth(args.idToken);
|
|
316
|
+
const loginEmail = metadata.email;
|
|
317
|
+
this.shared.modules.logger.log('Created new id token signer:', signer.address);
|
|
318
|
+
return {
|
|
319
|
+
signer,
|
|
320
|
+
extra: {
|
|
321
|
+
signerKind: Kinds.LoginGoogle,
|
|
322
|
+
},
|
|
323
|
+
loginEmail,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
280
326
|
case 'google-pkce':
|
|
281
327
|
case 'apple': {
|
|
282
|
-
const handler = this.shared.handlers.get(
|
|
328
|
+
const handler = this.shared.handlers.get(getSignupHandlerKey(args.kind));
|
|
283
329
|
if (!handler) {
|
|
284
330
|
throw new Error('handler-not-registered');
|
|
285
331
|
}
|
|
@@ -289,14 +335,24 @@ export class Wallets {
|
|
|
289
335
|
return {
|
|
290
336
|
signer,
|
|
291
337
|
extra: {
|
|
292
|
-
signerKind:
|
|
338
|
+
signerKind: getSignerKindForSignup(args.kind),
|
|
293
339
|
},
|
|
294
340
|
loginEmail,
|
|
295
341
|
};
|
|
296
342
|
}
|
|
297
343
|
}
|
|
298
344
|
if (args.kind.startsWith('custom-')) {
|
|
299
|
-
|
|
345
|
+
if (isIdTokenArgs(args)) {
|
|
346
|
+
const handler = getIdTokenSignupHandler(this.shared, args.kind);
|
|
347
|
+
const [signer, metadata] = await handler.completeAuth(args.idToken);
|
|
348
|
+
return {
|
|
349
|
+
signer,
|
|
350
|
+
extra: {
|
|
351
|
+
signerKind: args.kind,
|
|
352
|
+
},
|
|
353
|
+
loginEmail: metadata.email,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
300
356
|
const handler = this.shared.handlers.get(args.kind);
|
|
301
357
|
if (!handler) {
|
|
302
358
|
throw new Error('handler-not-registered');
|
|
@@ -313,11 +369,14 @@ export class Wallets {
|
|
|
313
369
|
throw new Error('invalid-signup-kind');
|
|
314
370
|
}
|
|
315
371
|
async startSignUpWithRedirect(args) {
|
|
316
|
-
const kind = args.kind
|
|
372
|
+
const kind = getSignupHandlerKey(args.kind);
|
|
317
373
|
const handler = this.shared.handlers.get(kind);
|
|
318
374
|
if (!handler) {
|
|
319
375
|
throw new Error('handler-not-registered');
|
|
320
376
|
}
|
|
377
|
+
if (!(handler instanceof AuthCodeHandler)) {
|
|
378
|
+
throw new Error('handler-does-not-support-redirect');
|
|
379
|
+
}
|
|
321
380
|
return handler.commitAuth(args.target, true);
|
|
322
381
|
}
|
|
323
382
|
async completeRedirect(args) {
|
|
@@ -338,11 +397,14 @@ export class Wallets {
|
|
|
338
397
|
});
|
|
339
398
|
}
|
|
340
399
|
else {
|
|
341
|
-
const
|
|
342
|
-
const handler = this.shared.handlers.get(
|
|
400
|
+
const handlerKind = getSignupHandlerKey(commitment.kind);
|
|
401
|
+
const handler = this.shared.handlers.get(handlerKind);
|
|
343
402
|
if (!handler) {
|
|
344
403
|
throw new Error('handler-not-registered');
|
|
345
404
|
}
|
|
405
|
+
if (!(handler instanceof AuthCodeHandler)) {
|
|
406
|
+
throw new Error('handler-does-not-support-redirect');
|
|
407
|
+
}
|
|
346
408
|
await handler.completeAuth(commitment, args.code);
|
|
347
409
|
}
|
|
348
410
|
if (!commitment.target) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xsequence/wallet-wdk",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"jwt-decode": "^4.0.0",
|
|
31
31
|
"ox": "^0.9.17",
|
|
32
32
|
"uuid": "^13.0.0",
|
|
33
|
-
"@0xsequence/
|
|
34
|
-
"@0xsequence/
|
|
35
|
-
"@0xsequence/identity-instrument": "^3.0.
|
|
36
|
-
"@0xsequence/wallet-core": "^3.0.
|
|
37
|
-
"@0xsequence/wallet-primitives": "^3.0.
|
|
33
|
+
"@0xsequence/relayer": "^3.0.3",
|
|
34
|
+
"@0xsequence/guard": "^3.0.3",
|
|
35
|
+
"@0xsequence/identity-instrument": "^3.0.3",
|
|
36
|
+
"@0xsequence/wallet-core": "^3.0.3",
|
|
37
|
+
"@0xsequence/wallet-primitives": "^3.0.3"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsc",
|
|
@@ -6,6 +6,7 @@ import * as Identity from '@0xsequence/identity-instrument'
|
|
|
6
6
|
import { SignerUnavailable, SignerReady, SignerActionable, BaseSignatureRequest } from '../types/signature-request.js'
|
|
7
7
|
import { IdentitySigner } from '../../identity/signer.js'
|
|
8
8
|
import { IdentityHandler } from './identity.js'
|
|
9
|
+
import { Kinds } from '../types/signer.js'
|
|
9
10
|
import type { NavigationLike, WdkEnv } from '../../env.js'
|
|
10
11
|
|
|
11
12
|
export class AuthCodeHandler extends IdentityHandler implements Handler {
|
|
@@ -26,6 +27,11 @@ export class AuthCodeHandler extends IdentityHandler implements Handler {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
public get kind() {
|
|
30
|
+
if (this.signupKind === 'google-pkce') {
|
|
31
|
+
// Keep Google PKCE on the canonical kind so Google signers created before
|
|
32
|
+
// canonicalization still resolve as `login-google`.
|
|
33
|
+
return Kinds.LoginGoogle
|
|
34
|
+
}
|
|
29
35
|
return 'login-' + this.signupKind
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -81,6 +81,10 @@ export class IdentityHandler {
|
|
|
81
81
|
return new IdentitySigner(this.nitro, authKey, this.env.crypto)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
protected async clearAuthKeySigner(address: string): Promise<void> {
|
|
85
|
+
await this.authKeys.delBySigner(address)
|
|
86
|
+
}
|
|
87
|
+
|
|
84
88
|
private async getAuthKey(signer: string): Promise<Db.AuthKey | undefined> {
|
|
85
89
|
let authKey = await this.authKeys.getBySigner(signer)
|
|
86
90
|
if (!signer && !authKey) {
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { Address, Hex } from 'ox'
|
|
2
|
+
import { Signers } from '@0xsequence/wallet-core'
|
|
3
|
+
import { Handler } from './handler.js'
|
|
4
|
+
import * as Identity from '@0xsequence/identity-instrument'
|
|
5
|
+
import * as Db from '../../dbs/index.js'
|
|
6
|
+
import { Signatures } from '../signatures.js'
|
|
7
|
+
import { SignerActionable, SignerReady, SignerUnavailable, BaseSignatureRequest } from '../types/signature-request.js'
|
|
8
|
+
import { IdentitySigner } from '../../identity/signer.js'
|
|
9
|
+
import { IdentityHandler } from './identity.js'
|
|
10
|
+
import { Kinds } from '../types/signer.js'
|
|
11
|
+
import type { WdkEnv } from '../../env.js'
|
|
12
|
+
|
|
13
|
+
type RespondFn = (idToken: string) => Promise<void>
|
|
14
|
+
|
|
15
|
+
export type PromptIdTokenHandler = (kind: 'google-id-token' | `custom-${string}`, respond: RespondFn) => Promise<void>
|
|
16
|
+
|
|
17
|
+
export class IdTokenHandler extends IdentityHandler implements Handler {
|
|
18
|
+
private onPromptIdToken: undefined | PromptIdTokenHandler
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
public readonly signupKind: 'google-id-token' | `custom-${string}`,
|
|
22
|
+
public readonly issuer: string,
|
|
23
|
+
public readonly audience: string,
|
|
24
|
+
nitro: Identity.IdentityInstrument,
|
|
25
|
+
signatures: Signatures,
|
|
26
|
+
authKeys: Db.AuthKeys,
|
|
27
|
+
env?: WdkEnv,
|
|
28
|
+
) {
|
|
29
|
+
super(nitro, authKeys, signatures, Identity.IdentityType.OIDC, env)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public get kind() {
|
|
33
|
+
if (this.signupKind === 'google-id-token') {
|
|
34
|
+
return Kinds.LoginGoogle
|
|
35
|
+
}
|
|
36
|
+
return 'login-' + this.signupKind
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public registerUI(onPromptIdToken: PromptIdTokenHandler) {
|
|
40
|
+
this.onPromptIdToken = onPromptIdToken
|
|
41
|
+
return () => {
|
|
42
|
+
this.onPromptIdToken = undefined
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public unregisterUI() {
|
|
47
|
+
this.onPromptIdToken = undefined
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public async completeAuth(idToken: string): Promise<[IdentitySigner, { [key: string]: string }]> {
|
|
51
|
+
const challenge = new Identity.IdTokenChallenge(this.issuer, this.audience, idToken)
|
|
52
|
+
await this.nitroCommitVerifier(challenge)
|
|
53
|
+
const { signer: identitySigner, email } = await this.nitroCompleteAuth(challenge)
|
|
54
|
+
|
|
55
|
+
return [identitySigner, { email }]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public async getSigner(): Promise<{ signer: Signers.Signer & Signers.Witnessable; email: string }> {
|
|
59
|
+
const onPromptIdToken = this.onPromptIdToken
|
|
60
|
+
if (!onPromptIdToken) {
|
|
61
|
+
throw new Error('id-token-handler-ui-not-registered')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return await this.handleAuth(onPromptIdToken)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async status(
|
|
68
|
+
address: Address.Address,
|
|
69
|
+
_imageHash: Hex.Hex | undefined,
|
|
70
|
+
request: BaseSignatureRequest,
|
|
71
|
+
): Promise<SignerUnavailable | SignerReady | SignerActionable> {
|
|
72
|
+
const signer = await this.getAuthKeySigner(address)
|
|
73
|
+
if (signer) {
|
|
74
|
+
return {
|
|
75
|
+
address,
|
|
76
|
+
handler: this,
|
|
77
|
+
status: 'ready',
|
|
78
|
+
handle: async () => {
|
|
79
|
+
await this.sign(signer, request)
|
|
80
|
+
return true
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const onPromptIdToken = this.onPromptIdToken
|
|
86
|
+
if (!onPromptIdToken) {
|
|
87
|
+
return {
|
|
88
|
+
address,
|
|
89
|
+
handler: this,
|
|
90
|
+
reason: 'ui-not-registered',
|
|
91
|
+
status: 'unavailable',
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
address,
|
|
97
|
+
handler: this,
|
|
98
|
+
status: 'actionable',
|
|
99
|
+
message: 'request-id-token',
|
|
100
|
+
handle: async () => {
|
|
101
|
+
try {
|
|
102
|
+
const { signer } = await this.handleAuth(onPromptIdToken)
|
|
103
|
+
const signerAddress = (await signer.address) as Address.Address
|
|
104
|
+
if (!Address.isEqual(signerAddress, address)) {
|
|
105
|
+
// ID-token auth prompts are keyed by provider kind, not the requested signer address.
|
|
106
|
+
// For example, a user can pick a different Google account in the account picker and
|
|
107
|
+
// return a token for a different identity than this request expects.
|
|
108
|
+
await this.clearAuthKeySigner(signerAddress)
|
|
109
|
+
throw new Error('id-token-signer-mismatch')
|
|
110
|
+
}
|
|
111
|
+
return true
|
|
112
|
+
} catch {
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private handleAuth(
|
|
120
|
+
onPromptIdToken: PromptIdTokenHandler,
|
|
121
|
+
): Promise<{ signer: Signers.Signer & Signers.Witnessable; email: string }> {
|
|
122
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
123
|
+
return new Promise(async (resolve, reject) => {
|
|
124
|
+
try {
|
|
125
|
+
const respond: RespondFn = async (idToken) => {
|
|
126
|
+
try {
|
|
127
|
+
const [signer, metadata] = await this.completeAuth(idToken)
|
|
128
|
+
resolve({ signer, email: metadata.email || '' })
|
|
129
|
+
} catch (error) {
|
|
130
|
+
reject(error)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
await onPromptIdToken(this.signupKind, respond)
|
|
135
|
+
} catch (error) {
|
|
136
|
+
reject(error)
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -3,4 +3,5 @@ export { DevicesHandler } from './devices.js'
|
|
|
3
3
|
export { PasskeysHandler } from './passkeys.js'
|
|
4
4
|
export { OtpHandler } from './otp.js'
|
|
5
5
|
export { AuthCodePkceHandler } from './authcode-pkce.js'
|
|
6
|
+
export { IdTokenHandler } from './idtoken.js'
|
|
6
7
|
export { MnemonicHandler } from './mnemonic.js'
|
package/src/sequence/manager.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
AuthCodePkceHandler,
|
|
15
15
|
DevicesHandler,
|
|
16
16
|
Handler,
|
|
17
|
+
IdTokenHandler,
|
|
17
18
|
MnemonicHandler,
|
|
18
19
|
OtpHandler,
|
|
19
20
|
PasskeysHandler,
|
|
@@ -31,9 +32,25 @@ import { Wallets, WalletsInterface } from './wallets.js'
|
|
|
31
32
|
import { GuardHandler, PromptCodeHandler } from './handlers/guard.js'
|
|
32
33
|
import { PasskeyCredential } from '../dbs/index.js'
|
|
33
34
|
import { PromptMnemonicHandler } from './handlers/mnemonic.js'
|
|
35
|
+
import { PromptIdTokenHandler } from './handlers/idtoken.js'
|
|
34
36
|
import { PromptOtpHandler } from './handlers/otp.js'
|
|
35
37
|
import { defaultPasskeyProvider, type PasskeyProvider } from './passkeys-provider.js'
|
|
36
38
|
|
|
39
|
+
type CustomIdentityProvider =
|
|
40
|
+
| {
|
|
41
|
+
kind: `custom-${string}`
|
|
42
|
+
authMethod: 'id-token'
|
|
43
|
+
issuer: string
|
|
44
|
+
clientId: string
|
|
45
|
+
}
|
|
46
|
+
| {
|
|
47
|
+
kind: `custom-${string}`
|
|
48
|
+
authMethod: 'authcode' | 'authcode-pkce'
|
|
49
|
+
issuer: string
|
|
50
|
+
oauthUrl: string
|
|
51
|
+
clientId: string
|
|
52
|
+
}
|
|
53
|
+
|
|
37
54
|
export type ManagerOptions = {
|
|
38
55
|
verbose?: boolean
|
|
39
56
|
|
|
@@ -85,18 +102,13 @@ export type ManagerOptions = {
|
|
|
85
102
|
google?: {
|
|
86
103
|
enabled: boolean
|
|
87
104
|
clientId: string
|
|
105
|
+
authMethod?: 'authcode-pkce' | 'id-token'
|
|
88
106
|
}
|
|
89
107
|
apple?: {
|
|
90
108
|
enabled: boolean
|
|
91
109
|
clientId: string
|
|
92
110
|
}
|
|
93
|
-
customProviders?:
|
|
94
|
-
kind: `custom-${string}`
|
|
95
|
-
authMethod: 'id-token' | 'authcode' | 'authcode-pkce'
|
|
96
|
-
issuer: string
|
|
97
|
-
oauthUrl: string
|
|
98
|
-
clientId: string
|
|
99
|
-
}[]
|
|
111
|
+
customProviders?: CustomIdentityProvider[]
|
|
100
112
|
}
|
|
101
113
|
}
|
|
102
114
|
|
|
@@ -112,18 +124,13 @@ export type ResolvedIdentityOptions = {
|
|
|
112
124
|
google: {
|
|
113
125
|
enabled: boolean
|
|
114
126
|
clientId: string
|
|
127
|
+
authMethod: 'authcode-pkce' | 'id-token'
|
|
115
128
|
}
|
|
116
129
|
apple: {
|
|
117
130
|
enabled: boolean
|
|
118
131
|
clientId: string
|
|
119
132
|
}
|
|
120
|
-
customProviders?:
|
|
121
|
-
kind: `custom-${string}`
|
|
122
|
-
authMethod: 'id-token' | 'authcode' | 'authcode-pkce'
|
|
123
|
-
issuer: string
|
|
124
|
-
oauthUrl: string
|
|
125
|
-
clientId: string
|
|
126
|
-
}[]
|
|
133
|
+
customProviders?: CustomIdentityProvider[]
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
export type ResolvedManagerOptions = {
|
|
@@ -248,6 +255,7 @@ export const ManagerOptionsDefaults = {
|
|
|
248
255
|
google: {
|
|
249
256
|
enabled: false,
|
|
250
257
|
clientId: '',
|
|
258
|
+
authMethod: 'authcode-pkce' as const,
|
|
251
259
|
},
|
|
252
260
|
apple: {
|
|
253
261
|
enabled: false,
|
|
@@ -677,20 +685,35 @@ export class Manager {
|
|
|
677
685
|
shared.handlers.set(Kinds.LoginEmailOtp, this.otpHandler)
|
|
678
686
|
}
|
|
679
687
|
if (ops.identity.google?.enabled) {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
)
|
|
693
|
-
|
|
688
|
+
if (ops.identity.google.authMethod === 'id-token') {
|
|
689
|
+
shared.handlers.set(
|
|
690
|
+
Kinds.LoginGoogle,
|
|
691
|
+
new IdTokenHandler(
|
|
692
|
+
'google-id-token',
|
|
693
|
+
'https://accounts.google.com',
|
|
694
|
+
ops.identity.google.clientId,
|
|
695
|
+
identityInstrument,
|
|
696
|
+
modules.signatures,
|
|
697
|
+
shared.databases.authKeys,
|
|
698
|
+
shared.env,
|
|
699
|
+
),
|
|
700
|
+
)
|
|
701
|
+
} else {
|
|
702
|
+
shared.handlers.set(
|
|
703
|
+
Kinds.LoginGoogle,
|
|
704
|
+
new AuthCodePkceHandler(
|
|
705
|
+
'google-pkce',
|
|
706
|
+
'https://accounts.google.com',
|
|
707
|
+
'https://accounts.google.com/o/oauth2/v2/auth',
|
|
708
|
+
ops.identity.google.clientId,
|
|
709
|
+
identityInstrument,
|
|
710
|
+
modules.signatures,
|
|
711
|
+
shared.databases.authCommitments,
|
|
712
|
+
shared.databases.authKeys,
|
|
713
|
+
shared.env,
|
|
714
|
+
),
|
|
715
|
+
)
|
|
716
|
+
}
|
|
694
717
|
}
|
|
695
718
|
if (ops.identity.apple?.enabled) {
|
|
696
719
|
shared.handlers.set(
|
|
@@ -712,7 +735,19 @@ export class Manager {
|
|
|
712
735
|
for (const provider of ops.identity.customProviders) {
|
|
713
736
|
switch (provider.authMethod) {
|
|
714
737
|
case 'id-token':
|
|
715
|
-
|
|
738
|
+
shared.handlers.set(
|
|
739
|
+
provider.kind,
|
|
740
|
+
new IdTokenHandler(
|
|
741
|
+
provider.kind,
|
|
742
|
+
provider.issuer,
|
|
743
|
+
provider.clientId,
|
|
744
|
+
identityInstrument,
|
|
745
|
+
modules.signatures,
|
|
746
|
+
shared.databases.authKeys,
|
|
747
|
+
shared.env,
|
|
748
|
+
),
|
|
749
|
+
)
|
|
750
|
+
break
|
|
716
751
|
case 'authcode':
|
|
717
752
|
shared.handlers.set(
|
|
718
753
|
provider.kind,
|
|
@@ -770,6 +805,20 @@ export class Manager {
|
|
|
770
805
|
return this.otpHandler?.registerUI(onPromptOtp) || (() => {})
|
|
771
806
|
}
|
|
772
807
|
|
|
808
|
+
public registerIdTokenUI(onPromptIdToken: PromptIdTokenHandler) {
|
|
809
|
+
const unregisters: (() => void)[] = []
|
|
810
|
+
|
|
811
|
+
this.shared.handlers.forEach((handler) => {
|
|
812
|
+
if (handler instanceof IdTokenHandler) {
|
|
813
|
+
unregisters.push(handler.registerUI(onPromptIdToken))
|
|
814
|
+
}
|
|
815
|
+
})
|
|
816
|
+
|
|
817
|
+
return () => {
|
|
818
|
+
unregisters.forEach((unregister) => unregister())
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
773
822
|
public registerGuardUI(onPromptCode: PromptCodeHandler) {
|
|
774
823
|
return this.guardHandler?.registerUI(onPromptCode) || (() => {})
|
|
775
824
|
}
|
package/src/sequence/sessions.ts
CHANGED
|
@@ -9,7 +9,9 @@ import {
|
|
|
9
9
|
SessionConfig,
|
|
10
10
|
} from '@0xsequence/wallet-primitives'
|
|
11
11
|
import { Address, Bytes, Hash, Hex } from 'ox'
|
|
12
|
+
import { AuthCodeHandler } from './handlers/authcode.js'
|
|
12
13
|
import { AuthCodePkceHandler } from './handlers/authcode-pkce.js'
|
|
14
|
+
import { IdTokenHandler } from './handlers/idtoken.js'
|
|
13
15
|
import { IdentityHandler, identityTypeToHex } from './handlers/identity.js'
|
|
14
16
|
import { Handler } from './handlers/index.js'
|
|
15
17
|
import { ManagerOptionsDefaults, Shared } from './manager.js'
|
|
@@ -362,7 +364,11 @@ export class Sessions implements SessionsInterface {
|
|
|
362
364
|
let audienceHash: Hex.Hex = '0x'
|
|
363
365
|
if (handler instanceof IdentityHandler) {
|
|
364
366
|
identityType = handler.identityType
|
|
365
|
-
if (
|
|
367
|
+
if (
|
|
368
|
+
handler instanceof AuthCodeHandler ||
|
|
369
|
+
handler instanceof AuthCodePkceHandler ||
|
|
370
|
+
handler instanceof IdTokenHandler
|
|
371
|
+
) {
|
|
366
372
|
issuerHash = Hash.keccak256(Hex.fromString(handler.issuer))
|
|
367
373
|
audienceHash = Hash.keccak256(Hex.fromString(handler.audience))
|
|
368
374
|
}
|
package/src/sequence/signers.ts
CHANGED
|
@@ -12,6 +12,11 @@ function toKnownKind(kind: string): Kind {
|
|
|
12
12
|
return kind as Kind
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
if (kind === 'login-google-pkce') {
|
|
16
|
+
// Normalize legacy Google PKCE witnesses while the canonical signer kind is `login-google`.
|
|
17
|
+
return Kinds.LoginGoogle
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
if (Object.values(Kinds).includes(kind as (typeof Kinds)[keyof typeof Kinds])) {
|
|
16
21
|
return kind as Kind
|
|
17
22
|
}
|
|
@@ -5,7 +5,7 @@ export const Kinds = {
|
|
|
5
5
|
LoginPasskey: 'login-passkey',
|
|
6
6
|
LoginMnemonic: 'login-mnemonic', // Todo: do not name it login-mnemonic, just mnemonic
|
|
7
7
|
LoginEmailOtp: 'login-email-otp',
|
|
8
|
-
|
|
8
|
+
LoginGoogle: 'login-google',
|
|
9
9
|
LoginApple: 'login-apple',
|
|
10
10
|
Recovery: 'recovery-extension',
|
|
11
11
|
Guard: 'guard-extension',
|
|
@@ -36,7 +36,7 @@ export interface Wallet {
|
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* A string identifier for the authentication method used for this session.
|
|
39
|
-
* Examples: 'login-mnemonic', 'login-passkey', 'login-google
|
|
39
|
+
* Examples: 'login-mnemonic', 'login-passkey', 'login-google'.
|
|
40
40
|
* @property
|
|
41
41
|
*/
|
|
42
42
|
loginType: string
|