@seams/wallet-server 0.28.0 → 0.30.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 +19 -4
- package/artifact-manifest.json +23 -13
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/dist/esm/application-auth.js +2 -0
- package/dist/esm/auth/applicationAuth.js +85 -0
- package/dist/esm/auth/externalAuthService.js +58 -7
- package/dist/esm/auth/externalAuthStore.js +157 -21
- package/dist/esm/auth/externalOwnerOperations.js +82 -0
- package/dist/esm/cloud-host.js +4 -4
- package/dist/esm/core/nearRelayerAccountProvisioning.js +1 -1
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +2 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RecordedOwnerOperation.js +43 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +22 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +1 -1
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +1 -1
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +2 -2
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +2 -2
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpService.js +2 -2
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +9 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletExecutionAuthority.js +9 -16
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +43 -1
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetup.js +12 -0
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationSetupExecution.js +1 -0
- package/dist/esm/router/cloudflare/d1/registration/registrationCompletionWrite.js +1 -0
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +35 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodBoundary.js +1 -1
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +4 -3
- package/dist/esm/router/cloudflare.js +1785 -1489
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +2 -2
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +1 -1
- package/dist/esm/router/domains/passkeyCustody/walletCustodyRegistrationCommit.js +1 -1
- package/dist/esm/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.js +35 -1
- package/dist/esm/router/domains/walletRegistration/walletRegistrationReservation.js +17 -2
- package/dist/esm/router/domains/walletRegistration/walletRegistrationRoutes.js +9 -1
- package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +1 -1
- package/dist/esm/router/transport/fetch/routes/ecdsaOperationStepUpFactor.js +2 -2
- package/dist/esm/router/transport/fetch/routes/externalAuth.js +139 -32
- package/dist/esm/router/transport/fetch/routes/passkeyCustody.js +44 -304
- package/dist/esm/router/transport/fetch/routes/sessions.js +2 -2
- package/dist/esm/router/transport/fetch/routes/thresholdEd25519.js +2 -2
- package/dist/esm/router/transport/fetch/routes/walletRegistration.js +2 -2
- package/dist/esm/router/transport/fetch/walletOwnerOperationAuthorization.js +306 -0
- package/dist/esm/shared-ts/src/auth/externalAuth.js +87 -14
- package/dist/esm/shared-ts/src/authorization/index.js +1 -1
- package/dist/esm/shared-ts/src/authorization/{walletCustodyOperation.js → walletOwnerOperation.js} +4 -4
- package/dist/esm/shared-ts/src/wallet-recovery/index.js +3 -3
- package/dist/esm/wasm/evm_crypto/pkg/evm_crypto_bg.wasm +0 -0
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/esm/wasm/shamir3pass_runtime/pkg/shamir3pass_runtime_bg.wasm +0 -0
- package/dist/types/shared-ts/src/auth/externalAuth.d.ts +51 -8
- package/dist/types/shared-ts/src/authorization/index.d.ts +1 -1
- package/dist/types/shared-ts/src/authorization/walletOwnerOperation.d.ts +10 -0
- package/dist/types/shared-ts/src/utils/registrationEstablishedSession.d.ts +4 -0
- package/dist/types/shared-ts/src/utils/registrationIntent.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/walletManagementProtocol.d.ts +1 -1
- package/dist/types/wallet-server/src/application-auth.d.ts +3 -0
- package/dist/types/wallet-server/src/auth/applicationAuth.d.ts +29 -0
- package/dist/types/wallet-server/src/auth/externalAuthService.d.ts +29 -10
- package/dist/types/wallet-server/src/auth/externalAuthStore.d.ts +60 -6
- package/dist/types/wallet-server/src/auth/externalOwnerOperations.d.ts +18 -0
- package/dist/types/wallet-server/src/cloud-host.d.ts +1 -1
- package/dist/types/wallet-server/src/core/threeRouteRegistrationContracts.d.ts +12 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.d.ts +5 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RecordedOwnerOperation.d.ts +16 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationSetup.d.ts +2 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.d.ts +7 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +1 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbEd25519NormalSigningRoute.d.ts +2 -2
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbOperationStepUp.d.ts +1 -1
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationInputs.d.ts +1 -0
- package/dist/types/wallet-server/src/router/domains/walletRegistration/walletRegistrationReservation.d.ts +11 -6
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +11 -0
- package/dist/types/wallet-server/src/router/transport/fetch/walletOwnerOperationAuthorization.d.ts +23 -0
- package/migrations/d1-signer/0086_application_auth.sql +67 -0
- package/migrations/d1-signer/0087_registration_without_session.sql +43 -0
- package/package.json +7 -2
- package/dist/types/shared-ts/src/authorization/walletCustodyOperation.d.ts +0 -10
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { parseEmailOtpChallengeId, parseOrgId, parseProviderSubject, parseWalletId, parseWebAuthnCredentialIdB64u } from "../../../shared-ts/src/utils/domainIds.js";
|
|
2
|
+
import { normalizeOptionalTrimmedString } from "../../../shared-ts/src/utils/normalize.js";
|
|
3
|
+
import { alphabetizeStringify } from "../../../shared-ts/src/utils/digests.js";
|
|
4
|
+
import { sha256Utf8DigestB64u } from "../../../shared-ts/src/utils/canonicalPrimitives.js";
|
|
5
|
+
import { requireParsed } from "../../../shared-ts/src/passkey-custody/primitives.js";
|
|
6
|
+
import { computeWalletOwnerAdminChallengeDigest } from "../../../shared-ts/src/authorization/walletOwnerOperation.js";
|
|
7
|
+
import { buildVaultOperationRef, parseAuthFactorId, parseAuthorizationAuditEventId, parseAuthorizationEvidenceId, parseAuthorizationEvidenceSetId, parseAuthorizedOperationId, parseCapabilityId, parseCapabilityOperationId, parsePrincipalId, parseTenantId } from "../../../shared-ts/src/authorization/capabilityKinds.js";
|
|
8
|
+
import { buildDelegatedWalletAuthorityV1, buildFullOwnerPermissionsV1, sameDelegatedWalletAuthorityV1 } from "../../../shared-ts/src/authorization/delegatedAuthority.js";
|
|
9
|
+
import { buildCapabilityOperationEnvelope, computeCapabilityOperationFingerprintDigest } from "../../../shared-ts/src/authorization/operationFingerprint.js";
|
|
10
|
+
import { buildPasskeyWalletAuthAuthority, walletAuthAuthorityRef } from "../../../shared-ts/src/utils/walletAuthAuthority.js";
|
|
11
|
+
import { parseSessionOrigin, parseVerifiedOwnerProofId } from "../../../authorization/domain.js";
|
|
12
|
+
import { buildVerifiedWalletOperationEmailOtpFactorResult, buildVerifiedWalletOperationPasskeyFactorResult } from "../../../authorization/factorEvidence.js";
|
|
13
|
+
import { EMAIL_OTP_CHANNEL, WALLET_EMAIL_OTP_UNLOCK_OPERATION } from "../../../shared-ts/src/utils/emailOtpDomain.js";
|
|
14
|
+
import { parseWebAuthnAuthenticationCredential } from "../../auth/webAuthnCredentialCodecs.js";
|
|
15
|
+
import { emailOtpStatusCode, hashEmailOtpOperationBinding } from "../../domains/emailOtp/emailOtpSessionRouteHelpers.js";
|
|
16
|
+
import { toFetchRouteResponse } from "../../framework/routeResponses.js";
|
|
17
|
+
import { parseCustodyOwnerProof } from "./routes/walletCustodyRequestBoundary.js";
|
|
18
|
+
//#region src/router/transport/fetch/walletOwnerOperationAuthorization.ts
|
|
19
|
+
const CUSTODY_OPERATION_CAPABILITY_ID = "wallet-custody-admin";
|
|
20
|
+
const CUSTODY_PROOF_TTL_MS = 6e4;
|
|
21
|
+
function walletOwnerOperationAuthorizationId(operation, challenge) {
|
|
22
|
+
return requireParsed(parseAuthorizedOperationId(`wallet-custody:authorized:wallet-custody:${operation}:${challenge}`), "owner operation");
|
|
23
|
+
}
|
|
24
|
+
function hasFullOwnerAuthority(authority) {
|
|
25
|
+
return sameDelegatedWalletAuthorityV1(buildDelegatedWalletAuthorityV1({ permissions: authority.permissions }), buildDelegatedWalletAuthorityV1({ permissions: buildFullOwnerPermissionsV1() }));
|
|
26
|
+
}
|
|
27
|
+
async function custodyDigest(domain, value) {
|
|
28
|
+
return sha256Utf8DigestB64u(`${domain}|${alphabetizeStringify(value)}`);
|
|
29
|
+
}
|
|
30
|
+
async function buildWalletCustodyOperation(input) {
|
|
31
|
+
const tenantId = requireParsed(parseTenantId(input.tenantId), "authorization");
|
|
32
|
+
const principalId = requireParsed(parsePrincipalId(input.principalId), "authorization");
|
|
33
|
+
const capabilityId = requireParsed(parseCapabilityId(CUSTODY_OPERATION_CAPABILITY_ID), "authorization");
|
|
34
|
+
const operationRef = buildVaultOperationRef("vault.reveal");
|
|
35
|
+
const laneDigest = await custodyDigest("seams:wallet-custody:lane:v1", {
|
|
36
|
+
capabilityId,
|
|
37
|
+
operation: input.operation,
|
|
38
|
+
operationRef
|
|
39
|
+
});
|
|
40
|
+
const challengeDigest = await computeWalletOwnerAdminChallengeDigest({
|
|
41
|
+
walletId: input.walletId,
|
|
42
|
+
operation: input.operation,
|
|
43
|
+
payload: input.payload,
|
|
44
|
+
requestOrigin: input.requestOrigin
|
|
45
|
+
});
|
|
46
|
+
const intentDigest = challengeDigest;
|
|
47
|
+
const displayDigest = await custodyDigest("seams:wallet-custody:display:v1", {
|
|
48
|
+
walletId: input.walletId,
|
|
49
|
+
operation: input.operation
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
operation: buildCapabilityOperationEnvelope({
|
|
53
|
+
tenantId,
|
|
54
|
+
principalId,
|
|
55
|
+
capabilityId,
|
|
56
|
+
operationId: requireParsed(parseCapabilityOperationId(`wallet-custody:${input.operation}:${intentDigest}`), "authorization"),
|
|
57
|
+
operation: operationRef,
|
|
58
|
+
digests: {
|
|
59
|
+
laneDigest,
|
|
60
|
+
intentDigest,
|
|
61
|
+
displayDigest
|
|
62
|
+
}
|
|
63
|
+
}),
|
|
64
|
+
challengeDigest
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function authorizeWalletOwnerOperation(input) {
|
|
68
|
+
const requestOrigin = normalizeOptionalTrimmedString(input.ctx.request.headers.get("origin"));
|
|
69
|
+
if (!requestOrigin) return toCustodyAuthorizationFailure(400, "invalid_origin", "request Origin is required");
|
|
70
|
+
let origin;
|
|
71
|
+
let proof;
|
|
72
|
+
let walletId;
|
|
73
|
+
try {
|
|
74
|
+
origin = parseSessionOrigin(requestOrigin);
|
|
75
|
+
walletId = requireParsed(parseWalletId(input.walletId), "authorization");
|
|
76
|
+
proof = parseCustodyOwnerProof(input.factorProof);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
return toCustodyAuthorizationFailure(400, "invalid_owner_proof", error instanceof Error ? error.message : "owner proof is invalid");
|
|
79
|
+
}
|
|
80
|
+
if (proof.kind === "passkey" && proof.walletId !== input.walletId) return toCustodyAuthorizationFailure(403, "scope_mismatch", "owner proof wallet differs");
|
|
81
|
+
let principalId;
|
|
82
|
+
let factor;
|
|
83
|
+
let ownerAuthorityRef;
|
|
84
|
+
let ownerAuthority;
|
|
85
|
+
let operation;
|
|
86
|
+
let challengeDigest;
|
|
87
|
+
try {
|
|
88
|
+
principalId = proof.kind === "passkey" ? input.walletId : proof.provider_subject_id;
|
|
89
|
+
const built = await buildWalletCustodyOperation({
|
|
90
|
+
tenantId: input.ctx.service.authorizedOperations.tenantId,
|
|
91
|
+
principalId,
|
|
92
|
+
walletId: input.walletId,
|
|
93
|
+
operation: input.operation,
|
|
94
|
+
payload: input.payload,
|
|
95
|
+
requestOrigin
|
|
96
|
+
});
|
|
97
|
+
operation = built.operation;
|
|
98
|
+
challengeDigest = built.challengeDigest;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return toCustodyAuthorizationFailure(400, "invalid_owner_proof", error instanceof Error ? error.message : "owner proof binding is invalid");
|
|
101
|
+
}
|
|
102
|
+
const operationFingerprintDigest = await computeCapabilityOperationFingerprintDigest(operation);
|
|
103
|
+
const nowMs = Date.now();
|
|
104
|
+
if (proof.challenge_digest !== String(challengeDigest)) return toCustodyAuthorizationFailure(403, "scope_mismatch", "factor proof challenge does not match the requested operation");
|
|
105
|
+
if (proof.kind === "passkey") {
|
|
106
|
+
let authority;
|
|
107
|
+
try {
|
|
108
|
+
authority = buildPasskeyWalletAuthAuthority({
|
|
109
|
+
walletId,
|
|
110
|
+
rpId: proof.rpId,
|
|
111
|
+
credentialIdB64u: proof.credentialIdB64u
|
|
112
|
+
});
|
|
113
|
+
} catch (error) {
|
|
114
|
+
return toCustodyAuthorizationFailure(400, "invalid_owner_proof", error instanceof Error ? error.message : "passkey authority is invalid");
|
|
115
|
+
}
|
|
116
|
+
const active = await input.ctx.service.walletAuthMethods.resolveActivePasskeyAuthorityForVerifiedCredential({
|
|
117
|
+
walletId,
|
|
118
|
+
rpId: authority.verifier.rpId,
|
|
119
|
+
credentialIdB64u: authority.factor.credentialIdB64u
|
|
120
|
+
});
|
|
121
|
+
if (!active.ok) return toCustodyAuthorizationFailure(403, active.code, active.message);
|
|
122
|
+
if (!hasFullOwnerAuthority(active.walletAuthority)) return toCustodyAuthorizationFailure(403, "forbidden", "Full owner authority is required");
|
|
123
|
+
ownerAuthority = active.walletAuthority;
|
|
124
|
+
const credential = parseWebAuthnAuthenticationCredential(proof.webauthn_authentication);
|
|
125
|
+
if (!credential) return toCustodyAuthorizationFailure(400, "invalid_owner_proof", "passkey assertion is invalid");
|
|
126
|
+
if (String(credential.rawId || credential.id).trim() !== authority.factor.credentialIdB64u) return toCustodyAuthorizationFailure(401, "unauthorized", "passkey credential changed");
|
|
127
|
+
const verified = await input.ctx.service.webAuthn.verifyWebAuthnAuthenticationLite({
|
|
128
|
+
userId: input.walletId,
|
|
129
|
+
rpId: authority.verifier.rpId,
|
|
130
|
+
expectedChallenge: challengeDigest,
|
|
131
|
+
expected_origin: requestOrigin,
|
|
132
|
+
webauthn_authentication: credential
|
|
133
|
+
});
|
|
134
|
+
if (!verified.success || !verified.verified) return toCustodyAuthorizationFailure(401, verified.code || "not_verified", verified.message || "WebAuthn authentication verification failed");
|
|
135
|
+
ownerAuthorityRef = await walletAuthAuthorityRef({ authority: active.authority });
|
|
136
|
+
factor = buildVerifiedWalletOperationPasskeyFactorResult({
|
|
137
|
+
tenantId: operation.tenantId,
|
|
138
|
+
principalId: operation.principalId,
|
|
139
|
+
walletId,
|
|
140
|
+
authorityRef: ownerAuthorityRef,
|
|
141
|
+
requestOrigin: origin,
|
|
142
|
+
audience: origin,
|
|
143
|
+
factorId: requireParsed(parseAuthFactorId(`passkey:${authority.factor.credentialIdB64u}`), "authorization"),
|
|
144
|
+
credentialIdB64u: requireParsed(parseWebAuthnCredentialIdB64u(authority.factor.credentialIdB64u), "authorization"),
|
|
145
|
+
assertionDigest: await custodyDigest("seams:wallet-custody:assertion:v1", { credential }),
|
|
146
|
+
operation,
|
|
147
|
+
verifiedAtMs: nowMs,
|
|
148
|
+
expiresAtMs: nowMs + CUSTODY_PROOF_TTL_MS
|
|
149
|
+
});
|
|
150
|
+
} else {
|
|
151
|
+
const providerSubject = requireParsed(parseProviderSubject(proof.provider_subject_id), "authorization");
|
|
152
|
+
const orgId = requireParsed(parseOrgId(input.ctx.service.authorizedOperations.tenantId), "authorization");
|
|
153
|
+
const active = await input.ctx.service.walletAuthMethods.resolveActiveEmailOtpAuthorityForVerifiedSubject({
|
|
154
|
+
walletId: input.walletId,
|
|
155
|
+
providerUserId: proof.provider_subject_id
|
|
156
|
+
});
|
|
157
|
+
if (!active.ok) return toCustodyAuthorizationFailure(403, active.code, active.message);
|
|
158
|
+
const activeAuthorityRef = await walletAuthAuthorityRef({ authority: active.authority });
|
|
159
|
+
ownerAuthorityRef = activeAuthorityRef;
|
|
160
|
+
ownerAuthority = active.walletAuthority;
|
|
161
|
+
const ownerProofBindingDigest = await hashEmailOtpOperationBinding({
|
|
162
|
+
walletId: input.walletId,
|
|
163
|
+
providerUserId: proof.provider_subject_id,
|
|
164
|
+
orgId,
|
|
165
|
+
operation: `wallet_custody:${input.operation}`,
|
|
166
|
+
requestOrigin,
|
|
167
|
+
audience: requestOrigin,
|
|
168
|
+
authorityRef: activeAuthorityRef,
|
|
169
|
+
operationFingerprintDigest: challengeDigest
|
|
170
|
+
});
|
|
171
|
+
const verified = await input.ctx.service.emailOtp.verifyEmailOtpChallenge({
|
|
172
|
+
userId: proof.provider_subject_id,
|
|
173
|
+
walletId: input.walletId,
|
|
174
|
+
orgId,
|
|
175
|
+
challengeId: proof.challenge_id,
|
|
176
|
+
otpCode: proof.otp_code,
|
|
177
|
+
otpChannel: EMAIL_OTP_CHANNEL,
|
|
178
|
+
ownerProofBindingDigest,
|
|
179
|
+
operation: WALLET_EMAIL_OTP_UNLOCK_OPERATION
|
|
180
|
+
});
|
|
181
|
+
if (!verified.ok) return toCustodyAuthorizationFailure(verified.code === "invalid_body" ? 400 : 401, verified.code, verified.message);
|
|
182
|
+
const consumed = await input.ctx.service.emailOtp.consumeEmailOtpGrant({
|
|
183
|
+
subject: {
|
|
184
|
+
kind: "provider_identity",
|
|
185
|
+
orgId,
|
|
186
|
+
providerSubject,
|
|
187
|
+
walletId
|
|
188
|
+
},
|
|
189
|
+
loginGrant: verified.loginGrant,
|
|
190
|
+
otpChannel: EMAIL_OTP_CHANNEL
|
|
191
|
+
});
|
|
192
|
+
if (!consumed.ok) return toCustodyAuthorizationFailure(emailOtpStatusCode(consumed.code), consumed.code, consumed.message);
|
|
193
|
+
factor = buildVerifiedWalletOperationEmailOtpFactorResult({
|
|
194
|
+
tenantId: operation.tenantId,
|
|
195
|
+
principalId: operation.principalId,
|
|
196
|
+
walletId,
|
|
197
|
+
authorityRef: activeAuthorityRef,
|
|
198
|
+
requestOrigin: origin,
|
|
199
|
+
audience: origin,
|
|
200
|
+
factorId: requireParsed(parseAuthFactorId(`email_otp:${active.authority.factor.provider}:${proof.provider_subject_id}`), "authorization"),
|
|
201
|
+
operation,
|
|
202
|
+
challengeId: requireParsed(parseEmailOtpChallengeId(consumed.challengeId), "authorization"),
|
|
203
|
+
verificationReceiptDigest: await custodyDigest("seams:wallet-custody:otp-receipt:v1", {
|
|
204
|
+
challengeId: consumed.challengeId,
|
|
205
|
+
operationFingerprintDigest
|
|
206
|
+
}),
|
|
207
|
+
verifiedAtMs: nowMs,
|
|
208
|
+
expiresAtMs: Math.min(nowMs + CUSTODY_PROOF_TTL_MS, verified.grantExpiresAtMs)
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
const ownerProof = await input.ctx.service.authorizedOperations.buildVerifiedOwnerProof({
|
|
212
|
+
purpose: "operation",
|
|
213
|
+
proofId: parseVerifiedOwnerProofId(`wallet-custody:${operation.operationId}`),
|
|
214
|
+
factor
|
|
215
|
+
});
|
|
216
|
+
if (ownerProof.purpose !== "operation" || ownerProof.operation.operationFingerprintDigest !== operationFingerprintDigest) return toCustodyAuthorizationFailure(403, "owner_proof_rejected", "owner proof binding is invalid");
|
|
217
|
+
const existing = await input.ctx.service.authorizedOperations.readAuthorizedOperation({
|
|
218
|
+
tenantId: operation.tenantId,
|
|
219
|
+
operationFingerprintDigest
|
|
220
|
+
});
|
|
221
|
+
if (existing) {
|
|
222
|
+
if (existing.authorization.kind !== "verified_step_up" || existing.quota.kind !== "quota_neutral") return toCustodyAuthorizationFailure(403, "owner_proof_rejected", "Owner operation authorization differs");
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
response: authorizedOperationReplay(existing)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
const evidenceSet = await input.ctx.service.authorizedOperations.recordVerifiedWalletOperationFactorEvidenceSet({
|
|
229
|
+
operation,
|
|
230
|
+
evidenceId: requireParsed(parseAuthorizationEvidenceId(`wallet-custody:evidence:${operation.operationId}`), "authorization"),
|
|
231
|
+
evidenceSetId: requireParsed(parseAuthorizationEvidenceSetId(`wallet-custody:evidence-set:${operation.operationId}`), "authorization"),
|
|
232
|
+
factor
|
|
233
|
+
});
|
|
234
|
+
const admission = await input.ctx.service.authorizedOperations.admitAuthorizedOperation({ operation: {
|
|
235
|
+
tenantId: operation.tenantId,
|
|
236
|
+
authorizedOperationId: walletOwnerOperationAuthorizationId(input.operation, challengeDigest),
|
|
237
|
+
auditEventId: requireParsed(parseAuthorizationAuditEventId(`wallet-custody:audit:${operation.operationId}`), "authorization"),
|
|
238
|
+
operation,
|
|
239
|
+
authorization: {
|
|
240
|
+
kind: "verified_step_up",
|
|
241
|
+
evidenceSetDigest: evidenceSet.evidenceSetDigest
|
|
242
|
+
},
|
|
243
|
+
quota: { kind: "quota_neutral" },
|
|
244
|
+
claimedAtMs: nowMs
|
|
245
|
+
} });
|
|
246
|
+
switch (admission.kind) {
|
|
247
|
+
case "claimed": return {
|
|
248
|
+
ok: true,
|
|
249
|
+
operation: admission.operation,
|
|
250
|
+
ownerAuthority
|
|
251
|
+
};
|
|
252
|
+
case "replayed":
|
|
253
|
+
case "operation_in_progress": return {
|
|
254
|
+
ok: false,
|
|
255
|
+
response: authorizedOperationReplay(admission.operation)
|
|
256
|
+
};
|
|
257
|
+
case "authorization_grant_rejected":
|
|
258
|
+
case "verified_step_up_rejected":
|
|
259
|
+
case "wallet_session_quota_exhausted":
|
|
260
|
+
case "material_mismatch": return toCustodyAuthorizationFailure(403, "owner_proof_rejected", "owner proof was rejected");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function toCustodyAuthorizationFailure(status, code, message) {
|
|
264
|
+
return {
|
|
265
|
+
ok: false,
|
|
266
|
+
response: routeErrorResponse(status, code, message)
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function routeErrorResponse(status, code, message) {
|
|
270
|
+
return toFetchRouteResponse({
|
|
271
|
+
status,
|
|
272
|
+
body: {
|
|
273
|
+
ok: false,
|
|
274
|
+
code,
|
|
275
|
+
message
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
function authorizedOperationReplay(operation) {
|
|
280
|
+
if (operation.lifecycle !== "completed") return routeErrorResponse(409, "recovery_in_progress", "wallet recovery is still in progress");
|
|
281
|
+
return new Response(operation.response.bodyText, {
|
|
282
|
+
status: operation.response.status,
|
|
283
|
+
headers: { "content-type": operation.response.contentType }
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
async function completeWalletOwnerOperation(ctx, operation, status, body, result = "succeeded") {
|
|
287
|
+
const bodyText = JSON.stringify(body);
|
|
288
|
+
await ctx.service.authorizedOperations.completeAuthorizedOperation({
|
|
289
|
+
operation,
|
|
290
|
+
result,
|
|
291
|
+
response: {
|
|
292
|
+
status,
|
|
293
|
+
contentType: "application/json",
|
|
294
|
+
bodyText
|
|
295
|
+
},
|
|
296
|
+
completedAtMs: Date.now()
|
|
297
|
+
});
|
|
298
|
+
return toFetchRouteResponse({
|
|
299
|
+
status,
|
|
300
|
+
body
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
//#endregion
|
|
304
|
+
export { authorizeWalletOwnerOperation, completeWalletOwnerOperation, walletOwnerOperationAuthorizationId };
|
|
305
|
+
|
|
306
|
+
//# sourceMappingURL=walletOwnerOperationAuthorization.js.map
|
|
@@ -1,33 +1,106 @@
|
|
|
1
1
|
import { parseWalletId } from "../utils/domainIds.js";
|
|
2
2
|
import { requireCanonicalString, requireRecord } from "../utils/validation.js";
|
|
3
|
-
import { parseUnixMs } from "../passkey-custody/primitives.js";
|
|
3
|
+
import { parseEd25519PublicKeyB64u, parseUnixMs } from "../passkey-custody/primitives.js";
|
|
4
4
|
//#region ../shared-ts/src/auth/externalAuth.ts
|
|
5
5
|
const EXTERNAL_AUTH_PATH = "/wallet/external-auth";
|
|
6
|
+
function parseExternalAuthProvider(raw) {
|
|
7
|
+
const value = requireRecord(raw, "external authentication provider");
|
|
8
|
+
switch (value.kind) {
|
|
9
|
+
case "disabled": return { kind: "disabled" };
|
|
10
|
+
case "google": return {
|
|
11
|
+
kind: "google",
|
|
12
|
+
clientId: requireCanonicalString(value.clientId, "clientId")
|
|
13
|
+
};
|
|
14
|
+
case "application": {
|
|
15
|
+
const issuer = requireCanonicalString(value.issuer, "issuer");
|
|
16
|
+
const url = new URL(issuer);
|
|
17
|
+
if (url.protocol !== "https:" || url.origin !== issuer) throw new Error("Application issuer must be a canonical HTTPS origin");
|
|
18
|
+
return {
|
|
19
|
+
kind: "application",
|
|
20
|
+
issuer,
|
|
21
|
+
publicKeyB64u: parseEd25519PublicKeyB64u(value.publicKeyB64u, "publicKeyB64u")
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
default: throw new Error("Unsupported external authentication provider");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function externalAuthConfiguration(provider, revision) {
|
|
28
|
+
switch (provider.kind) {
|
|
29
|
+
case "disabled": return {
|
|
30
|
+
kind: "disabled",
|
|
31
|
+
revision
|
|
32
|
+
};
|
|
33
|
+
case "google": return {
|
|
34
|
+
kind: "google",
|
|
35
|
+
revision,
|
|
36
|
+
clientId: provider.clientId
|
|
37
|
+
};
|
|
38
|
+
case "application": return {
|
|
39
|
+
kind: "application",
|
|
40
|
+
revision,
|
|
41
|
+
issuer: provider.issuer,
|
|
42
|
+
publicKeyB64u: provider.publicKeyB64u
|
|
43
|
+
};
|
|
44
|
+
default: return assertNever(provider);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
6
47
|
function parseExternalAuthConfiguration(raw) {
|
|
7
48
|
const value = requireRecord(raw, "external authentication configuration");
|
|
8
49
|
if (typeof value.revision !== "number" || !Number.isSafeInteger(value.revision) || value.revision < 0) throw new Error("Invalid external authentication revision");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
50
|
+
return externalAuthConfiguration(parseExternalAuthProvider(value), value.revision);
|
|
51
|
+
}
|
|
52
|
+
function serializeExternalIdentity(identity) {
|
|
53
|
+
return JSON.stringify([
|
|
54
|
+
identity.provider,
|
|
55
|
+
identity.issuer,
|
|
56
|
+
identity.subject
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
function parseStoredExternalIdentity(serialized) {
|
|
60
|
+
const raw = JSON.parse(serialized);
|
|
61
|
+
if (!Array.isArray(raw) || raw.length !== 3) throw new Error("Invalid external identity");
|
|
62
|
+
const [provider, issuer, subject] = raw;
|
|
63
|
+
return parseExternalIdentity({
|
|
64
|
+
provider,
|
|
65
|
+
issuer,
|
|
66
|
+
subject
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function parseExternalIdentity(raw) {
|
|
70
|
+
const value = requireRecord(raw, "external identity");
|
|
71
|
+
const provider = value.provider;
|
|
72
|
+
const issuer = requireCanonicalString(value.issuer, "issuer");
|
|
73
|
+
const subject = requireCanonicalString(value.subject, "subject");
|
|
74
|
+
switch (provider) {
|
|
75
|
+
case "google":
|
|
76
|
+
if (issuer !== "https://accounts.google.com") throw new Error("Invalid Google issuer");
|
|
77
|
+
return {
|
|
78
|
+
provider,
|
|
79
|
+
issuer,
|
|
80
|
+
subject
|
|
81
|
+
};
|
|
82
|
+
case "application": return {
|
|
83
|
+
provider,
|
|
84
|
+
issuer,
|
|
85
|
+
subject
|
|
86
|
+
};
|
|
87
|
+
default: throw new Error("Invalid external identity provider");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function assertNever(value) {
|
|
91
|
+
throw new Error(`Unsupported external authentication provider: ${String(value)}`);
|
|
19
92
|
}
|
|
20
93
|
function parseExternalWalletAuthentication(value) {
|
|
21
94
|
const record = requireRecord(value, "external authentication");
|
|
22
95
|
const walletId = parseWalletId(record.walletId);
|
|
23
|
-
if (!walletId.ok || record.kind !== "external_authenticated" || record.provider !== "google" || record.permission !== "wallet_settings_read" || "authMethod" in record) throw new Error("External authentication is invalid");
|
|
96
|
+
if (!walletId.ok || record.kind !== "external_authenticated" || record.provider !== "google" && record.provider !== "application" || record.permission !== "wallet_settings_read" || "authMethod" in record) throw new Error("External authentication is invalid");
|
|
24
97
|
return {
|
|
25
98
|
kind: "external_authenticated",
|
|
26
99
|
walletId: walletId.value,
|
|
27
100
|
sessionId: requireCanonicalString(record.sessionId, "sessionId"),
|
|
28
101
|
associationId: requireCanonicalString(record.associationId, "associationId"),
|
|
29
102
|
environmentId: requireCanonicalString(record.environmentId, "environmentId"),
|
|
30
|
-
provider:
|
|
103
|
+
provider: record.provider,
|
|
31
104
|
permission: "wallet_settings_read",
|
|
32
105
|
expiresAtMs: parseUnixMs(record.expiresAtMs, "expiresAtMs")
|
|
33
106
|
};
|
|
@@ -40,6 +113,6 @@ function externalAuthFailure(code) {
|
|
|
40
113
|
};
|
|
41
114
|
}
|
|
42
115
|
//#endregion
|
|
43
|
-
export { EXTERNAL_AUTH_PATH, externalAuthFailure, parseExternalAuthConfiguration, parseExternalWalletAuthentication };
|
|
116
|
+
export { EXTERNAL_AUTH_PATH, externalAuthFailure, parseExternalAuthConfiguration, parseExternalAuthProvider, parseExternalWalletAuthentication, parseStoredExternalIdentity, serializeExternalIdentity };
|
|
44
117
|
|
|
45
118
|
//# sourceMappingURL=externalAuth.js.map
|
package/dist/esm/shared-ts/src/authorization/{walletCustodyOperation.js → walletOwnerOperation.js}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { alphabetizeStringify } from "../utils/digests.js";
|
|
2
2
|
import { sha256Utf8DigestB64u } from "../utils/canonicalPrimitives.js";
|
|
3
|
-
//#region ../shared-ts/src/authorization/
|
|
3
|
+
//#region ../shared-ts/src/authorization/walletOwnerOperation.ts
|
|
4
4
|
/** Public challenge digest for a single wallet-administration factor proof. */
|
|
5
|
-
async function
|
|
5
|
+
async function computeWalletOwnerAdminChallengeDigest(input) {
|
|
6
6
|
return sha256Utf8DigestB64u(`seams:wallet-custody:challenge:v1|${alphabetizeStringify({
|
|
7
7
|
walletId: input.walletId,
|
|
8
8
|
operation: input.operation,
|
|
@@ -11,6 +11,6 @@ async function computeWalletCustodyAdminChallengeDigest(input) {
|
|
|
11
11
|
})}`);
|
|
12
12
|
}
|
|
13
13
|
//#endregion
|
|
14
|
-
export {
|
|
14
|
+
export { computeWalletOwnerAdminChallengeDigest };
|
|
15
15
|
|
|
16
|
-
//# sourceMappingURL=
|
|
16
|
+
//# sourceMappingURL=walletOwnerOperation.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import "./recoveryCodeReservation.js";
|
|
2
1
|
import "../utils/emailOtpRecoveryKey.js";
|
|
2
|
+
import "./recoveryCodeLocator.js";
|
|
3
|
+
import "./recoveryCodeReservation.js";
|
|
3
4
|
import "./recoveryKeyId.js";
|
|
5
|
+
import "./walletRecoveryEcdsaPossession.js";
|
|
4
6
|
import "./backupAcknowledgement.js";
|
|
5
7
|
import "./recoveryCodes.js";
|
|
6
8
|
import "./walletRecoveryEnvelopeSet.js";
|
|
7
|
-
import "./recoveryCodeLocator.js";
|
|
8
|
-
import "./walletRecoveryEcdsaPossession.js";
|
|
9
9
|
import "./walletRecoveryRotation.js";
|
|
10
10
|
import "./walletRecoveryCommittedProjection.js";
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,16 +1,55 @@
|
|
|
1
1
|
import { type WalletId } from '../utils/domainIds';
|
|
2
|
+
import { type Ed25519PublicKeyB64u } from '../passkey-custody/primitives';
|
|
2
3
|
import type { ReadonlyExclusiveUnion } from '../utils/variant';
|
|
4
|
+
import { type DigestB64u } from '../utils/canonicalPrimitives';
|
|
3
5
|
export declare const EXTERNAL_AUTH_PATH = "/wallet/external-auth";
|
|
4
|
-
export type
|
|
6
|
+
export type ExternalAuthProvider = ReadonlyExclusiveUnion<{
|
|
5
7
|
kind: 'disabled';
|
|
6
|
-
revision: number;
|
|
7
8
|
} | {
|
|
8
9
|
kind: 'google';
|
|
9
|
-
revision: number;
|
|
10
10
|
clientId: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'application';
|
|
13
|
+
issuer: string;
|
|
14
|
+
publicKeyB64u: Ed25519PublicKeyB64u;
|
|
15
|
+
}>;
|
|
16
|
+
export type ExternalAuthConfiguration = ExternalAuthProvider & Readonly<{
|
|
17
|
+
revision: number;
|
|
18
|
+
}>;
|
|
19
|
+
export type ExternalIdentity = ReadonlyExclusiveUnion<{
|
|
20
|
+
provider: 'google';
|
|
21
|
+
issuer: 'https://accounts.google.com';
|
|
22
|
+
subject: string;
|
|
23
|
+
} | {
|
|
24
|
+
provider: 'application';
|
|
25
|
+
issuer: string;
|
|
26
|
+
subject: string;
|
|
27
|
+
}>;
|
|
28
|
+
export type ExternalIdentityProof = ReadonlyExclusiveUnion<{
|
|
29
|
+
kind: 'google';
|
|
30
|
+
idToken: string;
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'application';
|
|
33
|
+
assertion: string;
|
|
11
34
|
}>;
|
|
35
|
+
export declare function parseExternalAuthProvider(raw: unknown): ExternalAuthProvider;
|
|
12
36
|
export declare function parseExternalAuthConfiguration(raw: unknown): ExternalAuthConfiguration;
|
|
13
|
-
|
|
37
|
+
export declare function serializeExternalIdentity(identity: ExternalIdentity): string;
|
|
38
|
+
export declare function parseStoredExternalIdentity(serialized: string): ExternalIdentity;
|
|
39
|
+
export type ExternalOwnerChallenge = Readonly<{
|
|
40
|
+
walletId: WalletId;
|
|
41
|
+
attemptId: string;
|
|
42
|
+
identity: ExternalIdentity;
|
|
43
|
+
challengeB64u: DigestB64u;
|
|
44
|
+
expiresAtMs: number;
|
|
45
|
+
}> & ReadonlyExclusiveUnion<{
|
|
46
|
+
kind: 'associate';
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'unlink';
|
|
49
|
+
associationId: string;
|
|
50
|
+
}>;
|
|
51
|
+
export declare function parseExternalOwnerChallenge(raw: unknown): ExternalOwnerChallenge;
|
|
52
|
+
type ExternalAuthFailureCode = 'invalid_request' | 'invalid_credential' | 'access_denied' | 'expired' | 'superseded' | 'unavailable' | 'rate_limited' | 'cancelled';
|
|
14
53
|
export type ExternalAuthResult<T> = ReadonlyExclusiveUnion<{
|
|
15
54
|
ok: true;
|
|
16
55
|
value: T;
|
|
@@ -29,7 +68,9 @@ export type ExternalAuthenticateInput = ReadonlyExclusiveUnion<{
|
|
|
29
68
|
attemptId: string;
|
|
30
69
|
code: string;
|
|
31
70
|
}>;
|
|
32
|
-
export type
|
|
71
|
+
export type ExternalAuthPurpose = 'authenticate' | 'associate';
|
|
72
|
+
export type ExternalAuthAttempt<Purpose extends ExternalAuthPurpose = 'authenticate'> = Readonly<{
|
|
73
|
+
purpose: Purpose;
|
|
33
74
|
attemptId: string;
|
|
34
75
|
walletId: WalletId;
|
|
35
76
|
expiresAtMs: number;
|
|
@@ -41,9 +82,11 @@ export type ExternalAuthCommand = ReadonlyExclusiveUnion<{
|
|
|
41
82
|
action: 'prepare';
|
|
42
83
|
walletId: string;
|
|
43
84
|
} | {
|
|
44
|
-
action: '
|
|
85
|
+
action: 'prepare_association';
|
|
45
86
|
walletId: string;
|
|
46
|
-
|
|
87
|
+
} | {
|
|
88
|
+
action: 'associate';
|
|
89
|
+
input: ExternalAuthenticateInput;
|
|
47
90
|
} | {
|
|
48
91
|
action: 'unlink';
|
|
49
92
|
walletId: string;
|
|
@@ -56,7 +99,7 @@ export type ExternalWalletAuthentication = Readonly<{
|
|
|
56
99
|
sessionId: string;
|
|
57
100
|
associationId: string;
|
|
58
101
|
environmentId: string;
|
|
59
|
-
provider: '
|
|
102
|
+
provider: ExternalIdentity['provider'];
|
|
60
103
|
permission: 'wallet_settings_read';
|
|
61
104
|
expiresAtMs: number;
|
|
62
105
|
authMethod?: never;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './capabilityKinds';
|
|
2
2
|
export * from './delegatedAuthority';
|
|
3
3
|
export * from './operationFingerprint';
|
|
4
|
-
export * from './
|
|
4
|
+
export * from './walletOwnerOperation';
|
|
5
5
|
export * from './walletAuthority';
|
|
6
6
|
export * from './walletSessionIssuance';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type DigestB64u } from '../utils/canonicalPrimitives';
|
|
2
|
+
export type WalletOwnerAdminOperation = 'external_identity_associate' | 'external_identity_unlink' | 'credentials_list' | 'credential_label' | 'recovery_rotate' | 'recovery_read' | 'recovery_status' | 'recovery_backup_acknowledge';
|
|
3
|
+
/** Public challenge digest for a single wallet-administration factor proof. */
|
|
4
|
+
export declare function computeWalletOwnerAdminChallengeDigest(input: {
|
|
5
|
+
readonly walletId: string;
|
|
6
|
+
readonly operation: WalletOwnerAdminOperation;
|
|
7
|
+
readonly payload: Record<string, unknown>;
|
|
8
|
+
readonly requestOrigin: string;
|
|
9
|
+
}): Promise<DigestB64u>;
|
|
10
|
+
//# sourceMappingURL=walletOwnerOperation.d.ts.map
|
|
@@ -72,6 +72,10 @@ export type RegistrationEstablishedSessionV2 = {
|
|
|
72
72
|
readonly tokens: RegistrationEstablishedSessionProjectionTokensV2;
|
|
73
73
|
};
|
|
74
74
|
export type RegistrationEstablishedSessionResultV2 = {
|
|
75
|
+
readonly kind: 'owner_operations';
|
|
76
|
+
readonly walletId: WalletId;
|
|
77
|
+
readonly session?: never;
|
|
78
|
+
} | {
|
|
75
79
|
readonly kind: 'issued';
|
|
76
80
|
readonly session: RegistrationEstablishedSessionV2;
|
|
77
81
|
} | {
|
|
@@ -18,7 +18,9 @@ export type RuntimePolicyScopeLike = {
|
|
|
18
18
|
envId: string;
|
|
19
19
|
signingRootVersion?: string;
|
|
20
20
|
};
|
|
21
|
+
export type RegistrationCompletion = 'wallet_session' | 'owner_operations';
|
|
21
22
|
export type RegistrationIntentV1 = {
|
|
23
|
+
completion: RegistrationCompletion;
|
|
22
24
|
version: 'registration_intent_v1';
|
|
23
25
|
walletId: WalletId;
|
|
24
26
|
authMethod: RegistrationAuthMethodInput;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ExternalAuthConfiguration, ExternalAuthPurpose, ExternalAuthResult, ExternalIdentity } from '../../../shared-ts/src/auth/externalAuth';
|
|
2
|
+
import type { Variant } from '../../../shared-ts/src/utils/variant';
|
|
3
|
+
type ApplicationTrust = Variant<ExternalAuthConfiguration, 'kind', 'application'>;
|
|
4
|
+
/** Called only by the application's authenticated backend with its enrolled issuer key. */
|
|
5
|
+
export declare function createApplicationAuthAssertion(input: {
|
|
6
|
+
readonly privateKey: CryptoKey;
|
|
7
|
+
readonly issuer: string;
|
|
8
|
+
readonly subject: string;
|
|
9
|
+
readonly environmentId: string;
|
|
10
|
+
readonly walletId: string;
|
|
11
|
+
readonly attemptId: string;
|
|
12
|
+
readonly nowMs: number;
|
|
13
|
+
readonly sessionExpiresAtMs: number;
|
|
14
|
+
readonly purpose: ExternalAuthPurpose;
|
|
15
|
+
}): Promise<string>;
|
|
16
|
+
export declare function verifyApplicationAuthAssertion(input: {
|
|
17
|
+
readonly trust: ApplicationTrust;
|
|
18
|
+
readonly assertion: string;
|
|
19
|
+
readonly environmentId: string;
|
|
20
|
+
readonly walletId: string;
|
|
21
|
+
readonly attemptId: string;
|
|
22
|
+
readonly nowMs: number;
|
|
23
|
+
readonly purpose: ExternalAuthPurpose;
|
|
24
|
+
}): Promise<ExternalAuthResult<{
|
|
25
|
+
identity: Variant<ExternalIdentity, 'provider', 'application'>;
|
|
26
|
+
expiresAtMs: number;
|
|
27
|
+
}>>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=applicationAuth.d.ts.map
|