Skip to content

Commit 849566b

Browse files
authored
wdk: account federation (#980)
* wdk: account federation * wdk: address review comments; refactor auth commitments * wdk: update tests * fix test
1 parent ac996d4 commit 849566b

11 files changed

Lines changed: 409 additions & 91 deletions

File tree

packages/wallet/wdk/src/dbs/auth-commitments.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ import { IDBPDatabase, IDBPTransaction } from 'idb'
33

44
const TABLE_NAME = 'auth-commitments'
55

6+
export type CommitAuthArgs =
7+
| { type: 'auth'; state?: string }
8+
| { type: 'reauth'; state: string; signer: string }
9+
| { type: 'add-signer'; wallet: string; state?: string }
10+
611
export type AuthCommitment = {
712
id: string
813
kind: 'google-pkce' | 'apple' | `custom-${string}`
914
metadata: { [key: string]: string }
1015
verifier?: string
1116
challenge?: string
1217
target: string
13-
isSignUp: boolean
14-
signer?: string
15-
}
18+
} & ({ type: 'auth' } | { type: 'reauth'; signer: string } | { type: 'add-signer'; wallet: string })
1619

1720
export class AuthCommitments extends Generic<AuthCommitment, 'id'> {
1821
constructor(dbName: string = 'sequence-auth-commitments') {

packages/wallet/wdk/src/dbs/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type { AuthCommitment } from './auth-commitments.js'
1+
export type { AuthCommitment, CommitAuthArgs } from './auth-commitments.js'
22
export { AuthCommitments } from './auth-commitments.js'
33

44
export type { AuthKey } from './auth-keys.js'

packages/wallet/wdk/src/sequence/handlers/authcode-pkce.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as Identity from '@0xsequence/identity-instrument'
66
import { IdentitySigner } from '../../identity/signer.js'
77
import { AuthCodeHandler } from './authcode.js'
88
import type { WdkEnv } from '../../env.js'
9+
import type { CommitAuthArgs } from '../../dbs/auth-commitments.js'
910

1011
export class AuthCodePkceHandler extends AuthCodeHandler implements Handler {
1112
constructor(
@@ -22,25 +23,30 @@ export class AuthCodePkceHandler extends AuthCodeHandler implements Handler {
2223
super(signupKind, issuer, oauthUrl, audience, nitro, signatures, commitments, authKeys, env)
2324
}
2425

25-
public async commitAuth(target: string, isSignUp: boolean, state?: string, signer?: string) {
26+
public async commitAuth(target: string, args: CommitAuthArgs) {
2627
let challenge = new Identity.AuthCodePkceChallenge(this.issuer, this.audience, this.redirectUri)
27-
if (signer) {
28-
challenge = challenge.withSigner({ address: signer, keyType: Identity.KeyType.Ethereum_Secp256k1 })
28+
if (args.type === 'reauth') {
29+
challenge = challenge.withSigner({ address: args.signer, keyType: Identity.KeyType.Ethereum_Secp256k1 })
2930
}
3031
const { verifier, loginHint, challenge: codeChallenge } = await this.nitroCommitVerifier(challenge)
31-
if (!state) {
32-
state = Hex.fromBytes(Bytes.random(32))
33-
}
32+
const state = args.state ?? Hex.fromBytes(Bytes.random(32))
3433

35-
await this.commitments.set({
34+
const base = {
3635
id: state,
37-
kind: this.signupKind,
36+
kind: this.signupKind as Db.AuthCommitment['kind'],
3837
verifier,
3938
challenge: codeChallenge,
4039
target,
4140
metadata: {},
42-
isSignUp,
43-
})
41+
}
42+
43+
if (args.type === 'reauth') {
44+
await this.commitments.set({ ...base, type: 'reauth', signer: args.signer })
45+
} else if (args.type === 'add-signer') {
46+
await this.commitments.set({ ...base, type: 'add-signer', wallet: args.wallet })
47+
} else {
48+
await this.commitments.set({ ...base, type: 'auth' })
49+
}
4450

4551
const searchParams = this.serializeQuery({
4652
code_challenge: codeChallenge,

packages/wallet/wdk/src/sequence/handlers/authcode.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { IdentitySigner } from '../../identity/signer.js'
88
import { IdentityHandler } from './identity.js'
99
import { Kinds } from '../types/signer.js'
1010
import type { NavigationLike, WdkEnv } from '../../env.js'
11+
import type { CommitAuthArgs } from '../../dbs/auth-commitments.js'
1112

1213
export class AuthCodeHandler extends IdentityHandler implements Handler {
1314
protected redirectUri: string = ''
@@ -39,19 +40,23 @@ export class AuthCodeHandler extends IdentityHandler implements Handler {
3940
this.redirectUri = redirectUri
4041
}
4142

42-
public async commitAuth(target: string, isSignUp: boolean, state?: string, signer?: string) {
43-
if (!state) {
44-
state = Hex.fromBytes(Bytes.random(32))
45-
}
43+
public async commitAuth(target: string, args: CommitAuthArgs) {
44+
const state = args.state ?? Hex.fromBytes(Bytes.random(32))
4645

47-
await this.commitments.set({
46+
const base = {
4847
id: state,
49-
kind: this.signupKind,
50-
signer,
48+
kind: this.signupKind as Db.AuthCommitment['kind'],
5149
target,
5250
metadata: {},
53-
isSignUp,
54-
})
51+
}
52+
53+
if (args.type === 'reauth') {
54+
await this.commitments.set({ ...base, type: 'reauth', signer: args.signer })
55+
} else if (args.type === 'add-signer') {
56+
await this.commitments.set({ ...base, type: 'add-signer', wallet: args.wallet })
57+
} else {
58+
await this.commitments.set({ ...base, type: 'auth' })
59+
}
5560

5661
const searchParams = this.serializeQuery({
5762
client_id: this.audience,
@@ -69,7 +74,7 @@ export class AuthCodeHandler extends IdentityHandler implements Handler {
6974
code: string,
7075
): Promise<[IdentitySigner, { [key: string]: string }]> {
7176
let challenge = new Identity.AuthCodeChallenge(this.issuer, this.audience, this.redirectUri, code)
72-
if (commitment.signer) {
77+
if (commitment.type === 'reauth') {
7378
challenge = challenge.withSigner({ address: commitment.signer, keyType: Identity.KeyType.Ethereum_Secp256k1 })
7479
}
7580
await this.nitroCommitVerifier(challenge)
@@ -103,7 +108,11 @@ export class AuthCodeHandler extends IdentityHandler implements Handler {
103108
message: 'request-redirect',
104109
handle: async () => {
105110
const navigation = this.getNavigation()
106-
const url = await this.commitAuth(navigation.getPathname(), false, request.id, address)
111+
const url = await this.commitAuth(navigation.getPathname(), {
112+
type: 'reauth',
113+
state: request.id,
114+
signer: address,
115+
})
107116
navigation.redirect(url)
108117
return true
109118
},

packages/wallet/wdk/src/sequence/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ export { Sessions } from './sessions.js'
99
export { Signatures } from './signatures.js'
1010
export type {
1111
StartSignUpWithRedirectArgs,
12+
StartAddLoginSignerWithRedirectArgs,
1213
CommonSignupArgs,
1314
PasskeySignupArgs,
1415
MnemonicSignupArgs,
1516
EmailOtpSignupArgs,
1617
CompleteRedirectArgs,
1718
SignupArgs,
19+
AddLoginSignerArgs,
20+
RemoveLoginSignerArgs,
1821
LoginToWalletArgs,
1922
LoginToMnemonicArgs,
2023
LoginToPasskeyArgs,

packages/wallet/wdk/src/sequence/types/signature-request.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export type ActionToPayload = {
1313
[Actions.Recovery]: Payload.Recovery<Payload.Calls>
1414
[Actions.AddRecoverySigner]: Payload.ConfigUpdate
1515
[Actions.RemoveRecoverySigner]: Payload.ConfigUpdate
16+
[Actions.AddLoginSigner]: Payload.ConfigUpdate
17+
[Actions.RemoveLoginSigner]: Payload.ConfigUpdate
1618
[Actions.SessionImplicitAuthorize]: Payload.SessionImplicitAuthorize
1719
}
1820

@@ -26,6 +28,8 @@ export const Actions = {
2628
Recovery: 'recovery',
2729
AddRecoverySigner: 'add-recovery-signer',
2830
RemoveRecoverySigner: 'remove-recovery-signer',
31+
AddLoginSigner: 'add-login-signer',
32+
RemoveLoginSigner: 'remove-login-signer',
2933
SessionImplicitAuthorize: 'session-implicit-authorize',
3034
} as const
3135

0 commit comments

Comments
 (0)