@zerodev/wallet-core 0.0.1-alpha.17 → 0.0.1-alpha.19
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/dist/_cjs/actions/auth/getOAuthLoginUrl.js +18 -0
- package/dist/_cjs/actions/auth/getOAuthLoginUrl.js.map +1 -0
- package/dist/_cjs/actions/auth/getWhoami.js +2 -2
- package/dist/_cjs/actions/auth/getWhoami.js.map +1 -1
- package/dist/_cjs/actions/auth/index.js +3 -1
- package/dist/_cjs/actions/auth/index.js.map +1 -1
- package/dist/_cjs/actions/auth/loginWithStamp.js +5 -5
- package/dist/_cjs/actions/auth/loginWithStamp.js.map +1 -1
- package/dist/_cjs/actions/auth/registerWithOTP.js.map +1 -1
- package/dist/_cjs/actions/index.js +2 -1
- package/dist/_cjs/actions/index.js.map +1 -1
- package/dist/_cjs/actions/wallet/signingUtils.js +2 -2
- package/dist/_cjs/actions/wallet/signingUtils.js.map +1 -1
- package/dist/_cjs/client/authProxy.js +1 -1
- package/dist/_cjs/client/authProxy.js.map +1 -1
- package/dist/_cjs/client/createClient.js +5 -5
- package/dist/_cjs/client/createClient.js.map +1 -1
- package/dist/_cjs/client/decorators/client.js +1 -0
- package/dist/_cjs/client/decorators/client.js.map +1 -1
- package/dist/_cjs/client/transports/createTransport.js +5 -5
- package/dist/_cjs/client/transports/createTransport.js.map +1 -1
- package/dist/_cjs/client/transports/rest.js +5 -5
- package/dist/_cjs/client/transports/rest.js.map +1 -1
- package/dist/_cjs/constants.js +2 -1
- package/dist/_cjs/constants.js.map +1 -1
- package/dist/_cjs/core/createZeroDevWallet.js +38 -64
- package/dist/_cjs/core/createZeroDevWallet.js.map +1 -1
- package/dist/_cjs/index.js.map +1 -1
- package/dist/_cjs/stampers/indexedDbStamper.js +17 -2
- package/dist/_cjs/stampers/indexedDbStamper.js.map +1 -1
- package/dist/_cjs/stampers/webauthnStamper.js +23 -3
- package/dist/_cjs/stampers/webauthnStamper.js.map +1 -1
- package/dist/_cjs/utils/encryptOtpAttempt.js +57 -0
- package/dist/_cjs/utils/encryptOtpAttempt.js.map +1 -0
- package/dist/_cjs/utils/exportPrivateKey.js +1 -1
- package/dist/_cjs/utils/exportPrivateKey.js.map +1 -1
- package/dist/_cjs/utils/exportWallet.js +2 -6
- package/dist/_cjs/utils/exportWallet.js.map +1 -1
- package/dist/_cjs/utils/hpke.js +78 -0
- package/dist/_cjs/utils/hpke.js.map +1 -0
- package/dist/_cjs/utils/utils.js +5 -6
- package/dist/_cjs/utils/utils.js.map +1 -1
- package/dist/_esm/actions/auth/getOAuthLoginUrl.js +23 -0
- package/dist/_esm/actions/auth/getOAuthLoginUrl.js.map +1 -0
- package/dist/_esm/actions/auth/getWhoami.js +2 -2
- package/dist/_esm/actions/auth/getWhoami.js.map +1 -1
- package/dist/_esm/actions/auth/index.js +1 -0
- package/dist/_esm/actions/auth/index.js.map +1 -1
- package/dist/_esm/actions/auth/loginWithStamp.js +5 -5
- package/dist/_esm/actions/auth/loginWithStamp.js.map +1 -1
- package/dist/_esm/actions/auth/registerWithOTP.js.map +1 -1
- package/dist/_esm/actions/index.js +1 -1
- package/dist/_esm/actions/index.js.map +1 -1
- package/dist/_esm/actions/wallet/signingUtils.js +2 -2
- package/dist/_esm/actions/wallet/signingUtils.js.map +1 -1
- package/dist/_esm/client/authProxy.js +9 -4
- package/dist/_esm/client/authProxy.js.map +1 -1
- package/dist/_esm/client/createClient.js +5 -5
- package/dist/_esm/client/createClient.js.map +1 -1
- package/dist/_esm/client/decorators/client.js +2 -1
- package/dist/_esm/client/decorators/client.js.map +1 -1
- package/dist/_esm/client/transports/createTransport.js +5 -5
- package/dist/_esm/client/transports/createTransport.js.map +1 -1
- package/dist/_esm/client/transports/rest.js +5 -5
- package/dist/_esm/client/transports/rest.js.map +1 -1
- package/dist/_esm/constants.js +6 -0
- package/dist/_esm/constants.js.map +1 -1
- package/dist/_esm/core/createZeroDevWallet.js +42 -66
- package/dist/_esm/core/createZeroDevWallet.js.map +1 -1
- package/dist/_esm/index.js.map +1 -1
- package/dist/_esm/stampers/indexedDbStamper.js +17 -2
- package/dist/_esm/stampers/indexedDbStamper.js.map +1 -1
- package/dist/_esm/stampers/webauthnStamper.js +23 -4
- package/dist/_esm/stampers/webauthnStamper.js.map +1 -1
- package/dist/_esm/utils/encryptOtpAttempt.js +81 -0
- package/dist/_esm/utils/encryptOtpAttempt.js.map +1 -0
- package/dist/_esm/utils/exportPrivateKey.js +1 -1
- package/dist/_esm/utils/exportPrivateKey.js.map +1 -1
- package/dist/_esm/utils/exportWallet.js +2 -6
- package/dist/_esm/utils/exportWallet.js.map +1 -1
- package/dist/_esm/utils/hpke.js +119 -0
- package/dist/_esm/utils/hpke.js.map +1 -0
- package/dist/_esm/utils/utils.js +5 -6
- package/dist/_esm/utils/utils.js.map +1 -1
- package/dist/_types/actions/auth/getOAuthLoginUrl.d.ts +30 -0
- package/dist/_types/actions/auth/getOAuthLoginUrl.d.ts.map +1 -0
- package/dist/_types/actions/auth/index.d.ts +1 -0
- package/dist/_types/actions/auth/index.d.ts.map +1 -1
- package/dist/_types/actions/auth/loginWithStamp.d.ts +2 -1
- package/dist/_types/actions/auth/loginWithStamp.d.ts.map +1 -1
- package/dist/_types/actions/auth/registerWithOTP.d.ts +6 -0
- package/dist/_types/actions/auth/registerWithOTP.d.ts.map +1 -1
- package/dist/_types/actions/index.d.ts +1 -1
- package/dist/_types/actions/index.d.ts.map +1 -1
- package/dist/_types/client/authProxy.d.ts +13 -7
- package/dist/_types/client/authProxy.d.ts.map +1 -1
- package/dist/_types/client/decorators/client.d.ts +7 -1
- package/dist/_types/client/decorators/client.d.ts.map +1 -1
- package/dist/_types/client/transports/rest.d.ts +5 -4
- package/dist/_types/client/transports/rest.d.ts.map +1 -1
- package/dist/_types/client/types.d.ts +9 -9
- package/dist/_types/client/types.d.ts.map +1 -1
- package/dist/_types/constants.d.ts +1 -0
- package/dist/_types/constants.d.ts.map +1 -1
- package/dist/_types/core/createZeroDevWallet.d.ts +13 -0
- package/dist/_types/core/createZeroDevWallet.d.ts.map +1 -1
- package/dist/_types/index.d.ts +1 -1
- package/dist/_types/index.d.ts.map +1 -1
- package/dist/_types/stampers/index.d.ts +1 -1
- package/dist/_types/stampers/index.d.ts.map +1 -1
- package/dist/_types/stampers/indexedDbStamper.d.ts +2 -2
- package/dist/_types/stampers/indexedDbStamper.d.ts.map +1 -1
- package/dist/_types/stampers/types.d.ts +31 -5
- package/dist/_types/stampers/types.d.ts.map +1 -1
- package/dist/_types/stampers/webauthnStamper.d.ts +2 -2
- package/dist/_types/stampers/webauthnStamper.d.ts.map +1 -1
- package/dist/_types/types/session.d.ts +2 -3
- package/dist/_types/types/session.d.ts.map +1 -1
- package/dist/_types/utils/buildClientSignature.d.ts +3 -3
- package/dist/_types/utils/buildClientSignature.d.ts.map +1 -1
- package/dist/_types/utils/encryptOtpAttempt.d.ts +40 -0
- package/dist/_types/utils/encryptOtpAttempt.d.ts.map +1 -0
- package/dist/_types/utils/exportWallet.d.ts.map +1 -1
- package/dist/_types/utils/hpke.d.ts +38 -0
- package/dist/_types/utils/hpke.d.ts.map +1 -0
- package/dist/_types/utils/utils.d.ts.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -1
- package/src/actions/auth/getOAuthLoginUrl.ts +48 -0
- package/src/actions/auth/getWhoami.ts +2 -2
- package/src/actions/auth/index.ts +5 -0
- package/src/actions/auth/loginWithStamp.ts +7 -6
- package/src/actions/auth/registerWithOTP.ts +6 -0
- package/src/actions/index.ts +3 -0
- package/src/actions/wallet/signingUtils.ts +2 -2
- package/src/client/authProxy.ts +14 -8
- package/src/client/createClient.ts +6 -6
- package/src/client/decorators/client.ts +13 -0
- package/src/client/transports/createTransport.ts +5 -5
- package/src/client/transports/rest.ts +11 -10
- package/src/client/types.ts +9 -9
- package/src/constants.ts +8 -0
- package/src/core/createZeroDevWallet.ts +58 -81
- package/src/index.ts +5 -2
- package/src/stampers/index.ts +2 -2
- package/src/stampers/indexedDbStamper.ts +24 -4
- package/src/stampers/types.ts +33 -5
- package/src/stampers/webauthnStamper.ts +27 -6
- package/src/types/session.ts +2 -3
- package/src/utils/buildClientSignature.ts +3 -3
- package/src/utils/encryptOtpAttempt.ts +142 -0
- package/src/utils/exportPrivateKey.ts +1 -1
- package/src/utils/exportWallet.ts +2 -6
- package/src/utils/hpke.ts +219 -0
- package/src/utils/utils.ts +5 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zerodev/wallet-core",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.19",
|
|
4
4
|
"description": "ZeroDev Wallet SDK built on Turnkey",
|
|
5
5
|
"main": "./dist/_cjs/index.js",
|
|
6
6
|
"module": "./dist/_esm/index.js",
|
|
@@ -49,6 +49,9 @@
|
|
|
49
49
|
],
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"dependencies": {
|
|
52
|
+
"@noble/ciphers": "^2.2.0",
|
|
53
|
+
"@noble/curves": "^2.2.0",
|
|
54
|
+
"@noble/hashes": "^2.2.0",
|
|
52
55
|
"@turnkey/http": "^3.12.1",
|
|
53
56
|
"@turnkey/iframe-stamper": "^2.5.0",
|
|
54
57
|
"@turnkey/indexed-db-stamper": "^1.1.1",
|
|
@@ -59,6 +62,7 @@
|
|
|
59
62
|
"viem": "^2.38.0"
|
|
60
63
|
},
|
|
61
64
|
"devDependencies": {
|
|
65
|
+
"@hpke/core": "^1.9.0",
|
|
62
66
|
"@types/node": "^20.0.0",
|
|
63
67
|
"typescript": "5.9.3"
|
|
64
68
|
},
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Client } from '../../client/types.js'
|
|
2
|
+
|
|
3
|
+
export type GetOAuthLoginUrlParameters = {
|
|
4
|
+
/** OAuth provider — currently only `'google'` is supported. */
|
|
5
|
+
provider: 'google'
|
|
6
|
+
/** The project ID for the request. */
|
|
7
|
+
projectId: string
|
|
8
|
+
/**
|
|
9
|
+
* The session public key (compressed P-256 hex, lowercase, with or
|
|
10
|
+
* without `0x` prefix). The backend embeds `sha256(utf8(hex))` as the
|
|
11
|
+
* OIDC `nonce` so the SDK can verify the URL was minted for this key.
|
|
12
|
+
*/
|
|
13
|
+
publicKey: string
|
|
14
|
+
/**
|
|
15
|
+
* Where the popup should land after the OAuth round-trip
|
|
16
|
+
* (e.g. `https://app.example.com/dashboard?oauth_success=true`).
|
|
17
|
+
* Must be on the project's whitelist.
|
|
18
|
+
*/
|
|
19
|
+
returnTo: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type GetOAuthLoginUrlReturnType = string
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Fetches the Google OAuth authorization URL from the backend.
|
|
26
|
+
*
|
|
27
|
+
* The SDK must verify the returned URL's `nonce` against
|
|
28
|
+
* `sha256(utf8(publicKey))` (and the host is `accounts.google.com`)
|
|
29
|
+
* before opening it in a popup — the backend is not a trusted party.
|
|
30
|
+
* See audit finding TOB-KMS-1.
|
|
31
|
+
*/
|
|
32
|
+
export async function getOAuthLoginUrl(
|
|
33
|
+
client: Client,
|
|
34
|
+
params: GetOAuthLoginUrlParameters,
|
|
35
|
+
): Promise<GetOAuthLoginUrlReturnType> {
|
|
36
|
+
if (params.provider !== 'google') {
|
|
37
|
+
throw new Error(`Unsupported OAuth provider: ${params.provider}`)
|
|
38
|
+
}
|
|
39
|
+
const query = new URLSearchParams({
|
|
40
|
+
project_id: params.projectId,
|
|
41
|
+
pub_key: params.publicKey.replace(/^0x/, '').toLowerCase(),
|
|
42
|
+
return_to: params.returnTo,
|
|
43
|
+
})
|
|
44
|
+
return await client.request<string>({
|
|
45
|
+
path: `oauth/google/login-url?${query.toString()}`,
|
|
46
|
+
method: 'GET',
|
|
47
|
+
})
|
|
48
|
+
}
|
|
@@ -51,7 +51,7 @@ export async function getWhoami(
|
|
|
51
51
|
// Step 1: Inner stamp over the payload (for Turnkey verification)
|
|
52
52
|
const innerBody = { organizationId }
|
|
53
53
|
const innerBodyString = canonicalizeEx(innerBody)
|
|
54
|
-
const innerStamp = await client.
|
|
54
|
+
const innerStamp = await client.apiKeyStamper.stamp(innerBodyString)
|
|
55
55
|
|
|
56
56
|
// Step 2: Build full body with inner stamp embedded
|
|
57
57
|
const fullBody = {
|
|
@@ -64,7 +64,7 @@ export async function getWhoami(
|
|
|
64
64
|
|
|
65
65
|
// Step 3: Outer stamp over full body (for KMS middleware)
|
|
66
66
|
const fullBodyString = canonicalizeEx(fullBody)
|
|
67
|
-
const outerStamp = await client.
|
|
67
|
+
const outerStamp = await client.apiKeyStamper.stamp(fullBodyString)
|
|
68
68
|
|
|
69
69
|
return await client.request({
|
|
70
70
|
path: `${projectId}/whoami`,
|
|
@@ -23,6 +23,11 @@ export {
|
|
|
23
23
|
type GetAuthProxyConfigIdReturnType,
|
|
24
24
|
getAuthProxyConfigId,
|
|
25
25
|
} from './getAuthProxyConfigId.js'
|
|
26
|
+
export {
|
|
27
|
+
type GetOAuthLoginUrlParameters,
|
|
28
|
+
type GetOAuthLoginUrlReturnType,
|
|
29
|
+
getOAuthLoginUrl,
|
|
30
|
+
} from './getOAuthLoginUrl.js'
|
|
26
31
|
export {
|
|
27
32
|
type GetWhoamiParameters,
|
|
28
33
|
type GetWhoamiReturnType,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canonicalizeEx } from 'json-canonicalize'
|
|
2
2
|
import type { Client } from '../../client/types.js'
|
|
3
3
|
import type { Stamp } from '../../stampers/types.js'
|
|
4
|
+
import type { StamperType } from '../../types/session.js'
|
|
4
5
|
|
|
5
6
|
export type EmailCustomization = {
|
|
6
7
|
/** A template for the URL to be used in a magic link button, e.g. `https://dapp.xyz/%s`. The auth bundle will be interpolated into the `%s`. */
|
|
@@ -15,7 +16,7 @@ export type LoginWithStampParameters = {
|
|
|
15
16
|
/** The encoded public key for the request */
|
|
16
17
|
targetPublicKey: string
|
|
17
18
|
/** The stamper type for the request */
|
|
18
|
-
stampWith?:
|
|
19
|
+
stampWith?: StamperType
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export type LoginWithStampReturnType = {
|
|
@@ -58,12 +59,12 @@ export async function loginWithStamp(
|
|
|
58
59
|
type: 'ACTIVITY_TYPE_STAMP_LOGIN',
|
|
59
60
|
})
|
|
60
61
|
let stamp: Stamp
|
|
61
|
-
if (stampWith === '
|
|
62
|
-
stamp = await client.
|
|
63
|
-
} else if (stampWith === '
|
|
64
|
-
stamp = await client.
|
|
62
|
+
if (stampWith === 'apiKey') {
|
|
63
|
+
stamp = await client.apiKeyStamper.stamp(stampPayload)
|
|
64
|
+
} else if (stampWith === 'passkey') {
|
|
65
|
+
stamp = await client.passkeyStamper.stamp(stampPayload)
|
|
65
66
|
} else {
|
|
66
|
-
stamp = await client.
|
|
67
|
+
stamp = await client.apiKeyStamper.stamp(stampPayload)
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
return client.request({
|
|
@@ -31,6 +31,12 @@ export type RegisterWithOTPParameters = {
|
|
|
31
31
|
export type RegisterWithOTPReturnType = {
|
|
32
32
|
/** The OTP ID needed for verification */
|
|
33
33
|
otpId: string
|
|
34
|
+
/**
|
|
35
|
+
* Signed encryption target bundle issued by the TLS Fetcher enclave for
|
|
36
|
+
* this OTP session. Passed verbatim to the verify step so the SDK can
|
|
37
|
+
* HPKE-encrypt the OTP attempt to the enclave's ephemeral target key.
|
|
38
|
+
*/
|
|
39
|
+
otpEncryptionTargetBundle: string
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
/**
|
package/src/actions/index.ts
CHANGED
|
@@ -12,10 +12,13 @@ export {
|
|
|
12
12
|
type GetAuthenticatorsParameters,
|
|
13
13
|
type GetAuthenticatorsReturnType,
|
|
14
14
|
type GetAuthProxyConfigIdReturnType,
|
|
15
|
+
type GetOAuthLoginUrlParameters,
|
|
16
|
+
type GetOAuthLoginUrlReturnType,
|
|
15
17
|
type GetWhoamiParameters,
|
|
16
18
|
type GetWhoamiReturnType,
|
|
17
19
|
getAuthenticators,
|
|
18
20
|
getAuthProxyConfigId,
|
|
21
|
+
getOAuthLoginUrl,
|
|
19
22
|
getWhoami,
|
|
20
23
|
type LoginWithOTPParameters,
|
|
21
24
|
type LoginWithOTPReturnType,
|
|
@@ -47,7 +47,7 @@ export async function sendSigningRequest(
|
|
|
47
47
|
|
|
48
48
|
// Inner stamp over the Turnkey payload (for Turnkey verification)
|
|
49
49
|
const innerBodyString = canonicalizeEx(turnkeyPayload)
|
|
50
|
-
const innerStamp = await client.
|
|
50
|
+
const innerStamp = await client.apiKeyStamper.stamp(innerBodyString)
|
|
51
51
|
|
|
52
52
|
// Build full body with inner stamp embedded
|
|
53
53
|
const fullBody = {
|
|
@@ -61,7 +61,7 @@ export async function sendSigningRequest(
|
|
|
61
61
|
|
|
62
62
|
// Outer stamp over full body (for KMS middleware)
|
|
63
63
|
const fullBodyString = canonicalizeEx(fullBody)
|
|
64
|
-
const outerStamp = await client.
|
|
64
|
+
const outerStamp = await client.apiKeyStamper.stamp(fullBodyString)
|
|
65
65
|
|
|
66
66
|
const { signature } = await client.request({
|
|
67
67
|
path: `${projectId}/${path}`,
|
package/src/client/authProxy.ts
CHANGED
|
@@ -10,10 +10,11 @@ export type AuthProxyClientConfig = {
|
|
|
10
10
|
export type AuthProxyVerifyOtpRequest = {
|
|
11
11
|
/** The OTP ID from registration */
|
|
12
12
|
otpId: string
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
/**
|
|
14
|
+
* HPKE-sealed bundle containing `{otp_code, public_key}` encrypted to the
|
|
15
|
+
* enclave's per-session target key. Produced by `encryptOtpAttempt`.
|
|
16
|
+
*/
|
|
17
|
+
encryptedOtpBundle: string
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export type AuthProxyVerifyOtpResponse = {
|
|
@@ -62,15 +63,20 @@ export function createAuthProxyClient(config: AuthProxyClientConfig) {
|
|
|
62
63
|
|
|
63
64
|
return {
|
|
64
65
|
/**
|
|
65
|
-
* Verifies an OTP
|
|
66
|
+
* Verifies an OTP attempt with Turnkey's Auth Proxy.
|
|
66
67
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
68
|
+
* The `encryptedOtpBundle` is HPKE-sealed `{otp_code, public_key}` JSON
|
|
69
|
+
* (see `encryptOtpAttempt`). The auth proxy forwards the ciphertext to
|
|
70
|
+
* the TLS Fetcher enclave, which decrypts it, verifies the OTP code, and
|
|
71
|
+
* returns a `verificationToken` bound to the embedded public key.
|
|
72
|
+
*
|
|
73
|
+
* Pass the returned `verificationToken` to `/auth/login/otp` along with
|
|
74
|
+
* a client signature to complete the login.
|
|
69
75
|
*/
|
|
70
76
|
async verifyOtp(
|
|
71
77
|
params: AuthProxyVerifyOtpRequest,
|
|
72
78
|
): Promise<AuthProxyVerifyOtpResponse> {
|
|
73
|
-
return request<AuthProxyVerifyOtpResponse>('/v1/
|
|
79
|
+
return request<AuthProxyVerifyOtpResponse>('/v1/otp_verify_v2', params)
|
|
74
80
|
},
|
|
75
81
|
}
|
|
76
82
|
}
|
|
@@ -16,8 +16,8 @@ export function createBaseClient<
|
|
|
16
16
|
>(config: ClientConfig): Client<extended> {
|
|
17
17
|
const {
|
|
18
18
|
transport,
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
apiKeyStamper,
|
|
20
|
+
passkeyStamper,
|
|
21
21
|
organizationId,
|
|
22
22
|
key = 'zeroDevWallet',
|
|
23
23
|
name = 'ZeroDev Wallet Client',
|
|
@@ -29,8 +29,8 @@ export function createBaseClient<
|
|
|
29
29
|
request,
|
|
30
30
|
value,
|
|
31
31
|
} = transport({
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
apiKeyStamper,
|
|
33
|
+
passkeyStamper,
|
|
34
34
|
})
|
|
35
35
|
const transportInstance = { ...transportConfig, ...value }
|
|
36
36
|
|
|
@@ -39,8 +39,8 @@ export function createBaseClient<
|
|
|
39
39
|
const client = {
|
|
40
40
|
transport: transportInstance,
|
|
41
41
|
request,
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
apiKeyStamper,
|
|
43
|
+
passkeyStamper,
|
|
44
44
|
organizationId,
|
|
45
45
|
key,
|
|
46
46
|
name,
|
|
@@ -13,12 +13,15 @@ import {
|
|
|
13
13
|
type GetAuthenticatorsParameters,
|
|
14
14
|
type GetAuthenticatorsReturnType,
|
|
15
15
|
type GetAuthProxyConfigIdReturnType,
|
|
16
|
+
type GetOAuthLoginUrlParameters,
|
|
17
|
+
type GetOAuthLoginUrlReturnType,
|
|
16
18
|
type GetUserWalletParameters,
|
|
17
19
|
type GetUserWalletReturnType,
|
|
18
20
|
type GetWhoamiParameters,
|
|
19
21
|
type GetWhoamiReturnType,
|
|
20
22
|
getAuthenticators,
|
|
21
23
|
getAuthProxyConfigId,
|
|
24
|
+
getOAuthLoginUrl,
|
|
22
25
|
getUserWallet,
|
|
23
26
|
getWhoami,
|
|
24
27
|
type LoginWithOTPParameters,
|
|
@@ -153,6 +156,15 @@ export type ZeroDevWalletActions = {
|
|
|
153
156
|
* Gets the auth proxy config ID from the backend
|
|
154
157
|
*/
|
|
155
158
|
getAuthProxyConfigId: () => Promise<GetAuthProxyConfigIdReturnType>
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Fetches the Google OAuth authorization URL from the backend.
|
|
162
|
+
* The caller must verify the URL's `nonce` against `sha256(utf8(publicKey))`
|
|
163
|
+
* before opening it (audit finding TOB-KMS-1).
|
|
164
|
+
*/
|
|
165
|
+
getOAuthLoginUrl: (
|
|
166
|
+
params: GetOAuthLoginUrlParameters,
|
|
167
|
+
) => Promise<GetOAuthLoginUrlReturnType>
|
|
156
168
|
}
|
|
157
169
|
|
|
158
170
|
/**
|
|
@@ -197,5 +209,6 @@ export function zeroDevWalletActions(client: Client): ZeroDevWalletActions {
|
|
|
197
209
|
registerWithOTP: (params) => registerWithOTP(client, params),
|
|
198
210
|
loginWithOTP: (params) => loginWithOTP(client, params),
|
|
199
211
|
getAuthProxyConfigId: () => getAuthProxyConfigId(client),
|
|
212
|
+
getOAuthLoginUrl: (params) => getOAuthLoginUrl(client, params),
|
|
200
213
|
}
|
|
201
214
|
}
|
|
@@ -26,14 +26,14 @@ export function zeroDevWalletTransport(
|
|
|
26
26
|
name = 'ZeroDev Wallet Transport',
|
|
27
27
|
} = options
|
|
28
28
|
|
|
29
|
-
return ({
|
|
29
|
+
return ({ apiKeyStamper, passkeyStamper }) => {
|
|
30
30
|
// Create REST transport with stamper
|
|
31
31
|
const transport = rest(baseUrl, {
|
|
32
32
|
timeoutMs,
|
|
33
33
|
key,
|
|
34
34
|
name,
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
apiKeyStamper,
|
|
36
|
+
passkeyStamper,
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
return {
|
|
@@ -46,8 +46,8 @@ export function zeroDevWalletTransport(
|
|
|
46
46
|
},
|
|
47
47
|
request: transport.request,
|
|
48
48
|
value: {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
apiKeyStamper,
|
|
50
|
+
passkeyStamper,
|
|
51
51
|
},
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canonicalizeEx } from 'json-canonicalize'
|
|
2
2
|
import { RestRequestError, RestTimeoutError } from '../../errors/request.js'
|
|
3
|
-
import type {
|
|
3
|
+
import type { ApiKeyStamper, PasskeyStamper } from '../../stampers/types.js'
|
|
4
|
+
import type { StamperType } from '../../types/session.js'
|
|
4
5
|
|
|
5
6
|
export type RestRequestArgs = {
|
|
6
7
|
path: string
|
|
@@ -8,7 +9,7 @@ export type RestRequestArgs = {
|
|
|
8
9
|
body?: any
|
|
9
10
|
headers?: Record<string, string>
|
|
10
11
|
stamp?: boolean
|
|
11
|
-
stampWith?:
|
|
12
|
+
stampWith?: StamperType
|
|
12
13
|
stampPostion?: 'body' | 'headers'
|
|
13
14
|
/** Include credentials (cookies) in the request */
|
|
14
15
|
credentials?: RequestCredentials
|
|
@@ -32,8 +33,8 @@ export type RestTransportConfig = {
|
|
|
32
33
|
timeoutMs?: number
|
|
33
34
|
key?: string
|
|
34
35
|
name?: string
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
apiKeyStamper: ApiKeyStamper
|
|
37
|
+
passkeyStamper: PasskeyStamper
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export function rest(url: string, cfg: RestTransportConfig): RestTransport {
|
|
@@ -56,13 +57,13 @@ export function rest(url: string, cfg: RestTransportConfig): RestTransport {
|
|
|
56
57
|
|
|
57
58
|
// Handle stamping if requested
|
|
58
59
|
if (args.stamp) {
|
|
59
|
-
let stamper:
|
|
60
|
-
if (args.stampWith === '
|
|
61
|
-
stamper = cfg.
|
|
62
|
-
} else if (args.stampWith === '
|
|
63
|
-
stamper = cfg.
|
|
60
|
+
let stamper: ApiKeyStamper | PasskeyStamper
|
|
61
|
+
if (args.stampWith === 'apiKey') {
|
|
62
|
+
stamper = cfg.apiKeyStamper
|
|
63
|
+
} else if (args.stampWith === 'passkey') {
|
|
64
|
+
stamper = cfg.passkeyStamper
|
|
64
65
|
} else {
|
|
65
|
-
stamper = cfg.
|
|
66
|
+
stamper = cfg.apiKeyStamper
|
|
66
67
|
}
|
|
67
68
|
const { body, apiUrl } = args.body
|
|
68
69
|
const bodyString = canonicalizeEx(body ?? args.body)
|
package/src/client/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiKeyStamper, PasskeyStamper } from '../stampers/types.js'
|
|
2
2
|
import type { RestRequestFn } from './transports/rest.js'
|
|
3
3
|
|
|
4
4
|
export type TransportConfig = {
|
|
@@ -17,8 +17,8 @@ export type TransportConfig = {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export type Transport = (options: {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
apiKeyStamper: ApiKeyStamper
|
|
21
|
+
passkeyStamper: PasskeyStamper
|
|
22
22
|
}) => {
|
|
23
23
|
config: TransportConfig
|
|
24
24
|
request: RestRequestFn
|
|
@@ -27,8 +27,8 @@ export type Transport = (options: {
|
|
|
27
27
|
|
|
28
28
|
export type ClientConfig = {
|
|
29
29
|
transport: Transport
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
apiKeyStamper: ApiKeyStamper
|
|
31
|
+
passkeyStamper: PasskeyStamper
|
|
32
32
|
organizationId?: string
|
|
33
33
|
key?: string
|
|
34
34
|
name?: string
|
|
@@ -39,10 +39,10 @@ export type Client<extended extends Extended | undefined = undefined> = {
|
|
|
39
39
|
transport: TransportConfig & Record<string, unknown>
|
|
40
40
|
/** Request function from transport */
|
|
41
41
|
request: RestRequestFn
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
|
|
42
|
+
/** API Key Stamper for authenticated requests */
|
|
43
|
+
apiKeyStamper: ApiKeyStamper
|
|
44
|
+
/** Passkey Stamper for authenticated requests */
|
|
45
|
+
passkeyStamper: PasskeyStamper
|
|
46
46
|
/** Organization ID */
|
|
47
47
|
organizationId?: string
|
|
48
48
|
/** A key for the client */
|
package/src/constants.ts
CHANGED
|
@@ -3,3 +3,11 @@ export const DEFAULT_IFRAME_CONTAINER_ID = 'turnkey-auth-iframe-container-id'
|
|
|
3
3
|
export const DEFAULT_IFRAME_ELEMENT_ID = 'turnkey-default-iframe-element-id'
|
|
4
4
|
export const DEFAULT_ORGANIZATION_ID = '0d98e826-dd8f-44ca-a585-3afcd27d4002'
|
|
5
5
|
export const KMS_SERVER_URL = 'https://kms.staging.zerodev.app'
|
|
6
|
+
|
|
7
|
+
// Pinned ECDSA P-256 public key (uncompressed, 65 bytes hex) of Turnkey's
|
|
8
|
+
// TLS Fetcher Sign enclave. Used to verify the signature on the OTP encryption
|
|
9
|
+
// target bundle returned by /auth/init/otp before HPKE-encrypting the OTP
|
|
10
|
+
// attempt. The bundle's `dataSignature` is verified against this key, so a
|
|
11
|
+
// compromised proxy cannot substitute its own ephemeral key.
|
|
12
|
+
export const TURNKEY_TLS_FETCHER_SIGN_PUBLIC_KEY =
|
|
13
|
+
'046b4f88421f76b6ba418afc2ea1d8ced671337d7db6b80478a60d8531bf8f17fa9a512f0fef96fc0c9b4cd9dff70b34992e520ce04c79d931f6ff6296b547d201'
|