@seams/wallet-server 0.7.1 → 0.7.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/THIRD_PARTY_NOTICES.md +1 -105
- package/artifact-manifest.json +21 -21
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-a/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/local-tools/linux-x64/router_ab_local_init +0 -0
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/index_bg.wasm +0 -0
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/index_bg.wasm +0 -0
- package/dist/esm/authorization/service.js +8 -0
- package/dist/esm/authorization/vaultProxyUse.js +2 -6
- package/dist/esm/cloud-host.js +4 -4
- package/dist/esm/core/IdentityStore.js +23 -110
- package/dist/esm/core/SessionService.js +7 -30
- package/dist/esm/core/ThresholdService/routerAbNormalSigningPolicy.js +3 -10
- package/dist/esm/core/ThresholdService/stores/WalletSessionStore.js +21 -97
- package/dist/esm/core/ThresholdService/stores/exportReplayGuard.js +7 -0
- package/dist/esm/core/WalletStore.js +4 -6
- package/dist/esm/core/authService/bytes.js +1 -4
- package/dist/esm/core/authService/emailOtpChallengeOperations.js +2 -5
- package/dist/esm/core/authService/emailOtpChallengeProof.js +9 -40
- package/dist/esm/core/authService/emailOtpChallengeVerification.js +19 -90
- package/dist/esm/core/authService/emailOtpChallenges.js +10 -45
- package/dist/esm/core/authService/emailOtpDelivery.js +10 -45
- package/dist/esm/core/authService/emailOtpEnrollment.js +9 -40
- package/dist/esm/core/authService/emailOtpGrant.js +9 -40
- package/dist/esm/core/authService/emailOtpRegistrationEnrollment.js +9 -40
- package/dist/esm/core/authService/emailOtpSeal.js +5 -20
- package/dist/esm/core/authService/emailOtpUnlock.js +20 -110
- package/dist/esm/core/authService/googleEmailOtpRegistration.js +28 -115
- package/dist/esm/core/authService/identity.js +5 -20
- package/dist/esm/core/authService/nearPublicKeyMetadata.js +6 -25
- package/dist/esm/core/authService/oidcVerification.js +22 -34
- package/dist/esm/core/authService/rateLimits.js +2 -5
- package/dist/esm/core/authService/thresholdEcdsaKeyInventory.js +2 -1
- package/dist/esm/core/authService/webauthn.js +37 -191
- package/dist/esm/core/authService/webauthnVerificationOutcomes.js +5 -24
- package/dist/esm/core/d1EcdsaSignerRead.js +76 -0
- package/dist/esm/core/d1IdentityStore.js +16 -75
- package/dist/esm/core/d1TenantStore.js +1 -1
- package/dist/esm/core/d1WalletStore.js +15 -25
- package/dist/esm/core/deviceLinking/linkedDeviceEmailOtpGrant.js +1 -5
- package/dist/esm/core/deviceLinking/linkedDeviceSessionApproval.js +1 -3
- package/dist/esm/core/deviceLinking/linkedDeviceSessionRecord.js +2 -8
- package/dist/esm/core/deviceLinking/requestProof.js +13 -4
- package/dist/esm/core/ecdsaMaterialReadSnapshot.js +85 -0
- package/dist/esm/core/nearRelayerAccountProvisioning.js +2 -5
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +3 -6
- package/dist/esm/core/signingMaterial/ordinaryInactiveSignerMaterialReservation.js +2 -5
- package/dist/esm/core/storeBackends.js +1 -1
- package/dist/esm/core/thresholdEcdsaChainTarget.js +1 -3
- package/dist/esm/hosted-wallet-gateway.js +2 -2
- package/dist/esm/localHostedWalletGatewayHandler.js +13 -0
- package/dist/esm/localIntendedMaterialAdmissionFault.js +176 -0
- package/dist/esm/localIntendedPresignCancellation.js +44 -0
- package/dist/esm/router/auth/commonRouterUtils.js +24 -10
- package/dist/esm/router/auth/walletSessionFailure.js +2 -5
- package/dist/esm/router/auth/webAuthnCredentialCodecs.js +4 -15
- package/dist/esm/router/cloudflare/d1/auth/d1AuthorizedOperationRouteService.js +1 -0
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.js +2 -6
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +5 -27
- package/dist/esm/router/cloudflare/d1/auth/walletSessionCredentialReaders.js +76 -0
- package/dist/esm/router/cloudflare/d1/authorization/authorizedOperationStatements.js +28 -21
- package/dist/esm/router/cloudflare/d1/authorization/d1AuthorizationStore.js +209 -44
- package/dist/esm/router/cloudflare/d1/authorization/d1VaultProxyStore.js +8 -12
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +50 -8
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.js +1 -1
- package/dist/esm/router/cloudflare/d1/deviceLinking/index.js +3 -3
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeIssuer.js +12 -55
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpChallengeService.js +17 -80
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpDeliveryRuntime.js +6 -25
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.js +12 -47
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRecoveryService.js +24 -85
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpRegistrationEnrollmentFinalizer.js +7 -30
- package/dist/esm/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.js +5 -20
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpSessionResolver.js +23 -110
- package/dist/esm/router/cloudflare/d1/identity/d1IdentityService.js +9 -40
- package/dist/esm/router/cloudflare/d1/near/d1NearPublicKeyStore.js +3 -10
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcBoundary.js +18 -91
- package/dist/esm/router/cloudflare/d1/oidc/d1OidcVerificationService.js +6 -30
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyRouteService.js +4 -15
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletCustodyCommitStore.js +2 -7
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpRecords.js +9 -13
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1WalletRecoveryGoogleEmailOtpService.js +11 -50
- package/dist/esm/router/cloudflare/d1/registration/d1EvmFamilyEcdsaRegistrationBranch.js +5 -20
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.js +4 -7
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationCeremonyRecords.js +2 -1
- package/dist/esm/router/cloudflare/d1/registration/d1RegistrationIntentService.js +7 -30
- package/dist/esm/router/cloudflare/d1/registration/d1WalletRegistrationService.js +32 -22
- package/dist/esm/router/cloudflare/d1/registration/walletRegistrationSessionCommitReceipt.js +1 -4
- package/dist/esm/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.js +119 -25
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnAuthService.js +31 -168
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +6 -9
- package/dist/esm/router/cloudflare/durableObjects/thresholdStore.js +59 -66
- package/dist/esm/router/cloudflare/runtime/routerAbPrewarm.js +2 -2
- package/dist/esm/router/cloudflare/runtime/staticWalletConsoleBinding.js +5 -20
- package/dist/esm/router/cloudflare/runtime/tenantRootCreationGrant.js +2 -9
- package/dist/esm/router/cloudflare/runtime/walletControlOps.js +2 -1
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneCurveExecution.js +2 -1
- package/dist/esm/router/cloudflare/signingLanes/cloudflareLaneProtocolCommitter.js +2 -2
- package/dist/esm/router/cloudflare.js +2146 -1802
- package/dist/esm/router/domains/ed25519Yao/capabilityLifecycle/routerAbEd25519YaoProductRegistrationPersistence.js +5 -8
- package/dist/esm/router/domains/ed25519Yao/recovery/routerAbEd25519YaoRecoveryWalletSessionAuthorization.js +3 -6
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationIntentAuthorization.js +6 -25
- package/dist/esm/router/domains/ed25519Yao/registration/routerAbEd25519YaoRegistrationSideEffectBoundary.js +39 -55
- package/dist/esm/router/domains/emailOtp/emailOtpRouteHandlers.js +15 -62
- package/dist/esm/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.js +83 -74
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmission.js +1 -0
- package/dist/esm/router/domains/signingOperations/routerAbOperationStepUp.js +1 -0
- package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +1 -4
- package/dist/esm/router/domains/tenantRoot/tenantRootIdentityResolution.js +7 -13
- package/dist/esm/router/domains/walletUnlock/walletUnlockRouteHandlers.js +41 -200
- package/dist/esm/router/express.js +317 -699
- package/dist/esm/router/framework/http.js +5 -1
- package/dist/esm/router/framework/runtimeSnapshotConsumer.js +8 -35
- package/dist/esm/router/transport/fetch/createFetchRouter.js +3 -6
- package/dist/esm/router/transport/fetch/routes/auth.js +9 -41
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +5 -22
- package/dist/esm/router/transport/fetch/routes/nearPublicKeys.js +4 -16
- package/dist/esm/router/transport/fetch/routes/sessions.js +1 -0
- package/dist/esm/router/transport/fetch/routes/syncAccount.js +8 -36
- package/dist/esm/router/transport/fetch/routes/thresholdEcdsa.js +27 -79
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +4 -1
- package/dist/esm/router/transport/fetch/routes/webauthnAuthenticators.js +4 -16
- package/dist/esm/shared-ts/src/authorization/walletSignerActivationEquality.js +12 -0
- package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +2 -5
- package/dist/esm/shared-ts/src/device-linking/delegatedActivationPlan.js +1 -5
- package/dist/esm/shared-ts/src/device-linking/ed25519ExportRoot.js +12 -16
- package/dist/esm/shared-ts/src/device-linking/sourceContribution.js +5 -8
- package/dist/esm/shared-ts/src/passkey-custody/primitives.js +5 -1
- package/dist/esm/shared-ts/src/signing-lanes/ownerContinuity.js +4 -8
- package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentifier.js +12 -0
- package/dist/esm/shared-ts/src/tenant-root/tenantRootIdentity.js +2 -9
- package/dist/esm/shared-ts/src/tenant-root/tenantRootOperationRecord.js +1 -4
- package/dist/esm/shared-ts/src/utils/ecdsaKeyFactsInventory.js +2 -4
- package/dist/esm/shared-ts/src/utils/ecdsaServerTiming.js +0 -1
- package/dist/esm/shared-ts/src/utils/emailOtpDomain.js +3 -1
- package/dist/esm/shared-ts/src/utils/exactKeys.js +17 -0
- package/dist/esm/shared-ts/src/utils/failure.js +20 -0
- package/dist/esm/shared-ts/src/utils/registrationIntent.js +3 -12
- package/dist/esm/shared-ts/src/utils/registrationSignerPlan.js +2 -5
- package/dist/esm/shared-ts/src/utils/routerAbEcdsaDerivation.js +1 -1
- package/dist/esm/shared-ts/src/utils/routerAbEd25519Yao.js +1 -1
- package/dist/esm/shared-ts/src/utils/thresholdEcdsaChainTarget.js +9 -0
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -4
- package/dist/esm/threshold/session/signingSessionSeal/crypto/cipher.js +10 -32
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyBackends.js +3 -3
- package/dist/esm/threshold/session/signingSessionSeal/idempotencyRecords.js +3 -9
- package/dist/esm/threshold/session/signingSessionSeal/service.js +8 -35
- package/dist/esm/threshold/session/signingSessionSeal/transport/express.js +18 -94
- package/dist/esm/threshold/session/signingSessionSeal/transport/fetch.js +6 -30
- package/dist/esm/threshold/session/signingSessionSeal/transport/shared.js +5 -20
- 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/types/shared-ts/src/authorization/delegatedAuthority.d.ts +2 -1
- package/dist/types/shared-ts/src/authorization/walletSessionIssuance.d.ts +9 -2
- package/dist/types/shared-ts/src/authorization/walletSignerActivationEquality.d.ts +4 -0
- package/dist/types/shared-ts/src/device-linking/committedSignerPackages.d.ts +3 -4
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +5 -63
- package/dist/types/shared-ts/src/device-linking/sourceContribution.d.ts +2 -0
- package/dist/types/shared-ts/src/passkey-custody/custodyEnvelope.d.ts +5 -12
- package/dist/types/shared-ts/src/passkey-custody/primitives.d.ts +9 -0
- package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +11 -1
- package/dist/types/shared-ts/src/signing-lanes/ids.d.ts +1 -10
- package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +3 -5
- package/dist/types/shared-ts/src/tenant-root/tenantRootIdentifier.d.ts +3 -0
- package/dist/types/shared-ts/src/tenant-root/tenantRootOperationRecord.d.ts +2 -1
- package/dist/types/shared-ts/src/threshold/ecdsaDerivationRoleLocalBootstrap.d.ts +6 -0
- package/dist/types/shared-ts/src/threshold/signingRootScope.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/ecdsaKeyFactsInventory.d.ts +2 -11
- package/dist/types/shared-ts/src/utils/eip1559TxWasmJson.d.ts +16 -0
- package/dist/types/shared-ts/src/utils/emailOtpDomain.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/exactKeys.d.ts +11 -0
- package/dist/types/shared-ts/src/utils/failure.d.ts +12 -0
- package/dist/types/shared-ts/src/utils/jsonRpc.d.ts +3 -4
- package/dist/types/shared-ts/src/utils/nearRpcResults.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/registrationAuthMethodInput.d.ts +3 -8
- package/dist/types/shared-ts/src/utils/registrationSignerPlan.d.ts +7 -19
- package/dist/types/shared-ts/src/utils/routerAbEcdsaDerivation.d.ts +3 -1
- package/dist/types/shared-ts/src/utils/routerAbEd25519Yao.d.ts +1 -0
- package/dist/types/shared-ts/src/utils/routerAbEd25519YaoDigests.d.ts +3 -4
- package/dist/types/shared-ts/src/utils/routerAbNormalSigningIdentity.d.ts +30 -8
- package/dist/types/shared-ts/src/utils/routerApiKeyAuth.d.ts +2 -0
- package/dist/types/shared-ts/src/utils/signingSessionSeal.d.ts +10 -11
- package/dist/types/shared-ts/src/utils/thresholdEcdsaChainTarget.d.ts +25 -0
- package/dist/types/shared-ts/src/utils/variant.d.ts +18 -0
- package/dist/types/shared-ts/src/utils/walletAuthMethodRecord.d.ts +3 -6
- package/dist/types/shared-ts/src/utils/webauthnDeviceInfo.d.ts +4 -2
- package/dist/types/shared-ts/src/wallet-recovery/recoveryEnvelopes.d.ts +3 -16
- package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryPreparation.d.ts +15 -0
- package/dist/types/shared-ts/src/wallet-recovery/walletRecoveryTarget.d.ts +3 -4
- package/dist/types/wallet-server/src/authorization/domain.d.ts +13 -2
- package/dist/types/wallet-server/src/authorization/ecdsaWalletSessionAdmission.d.ts +27 -3
- package/dist/types/wallet-server/src/authorization/service.d.ts +19 -0
- package/dist/types/wallet-server/src/core/ThresholdService/stores/SessionStore.d.ts +2 -2
- package/dist/types/wallet-server/src/core/ThresholdService/stores/WalletSessionStore.d.ts +1 -1
- package/dist/types/wallet-server/src/core/ThresholdService/stores/exportReplayGuard.d.ts +3 -0
- package/dist/types/wallet-server/src/core/ThresholdService/validation.d.ts +8 -101
- package/dist/types/wallet-server/src/core/WebAuthnAuthenticatorStore.d.ts +8 -0
- package/dist/types/wallet-server/src/core/authService/bytes.d.ts +0 -1
- package/dist/types/wallet-server/src/core/authService/emailOtpChallenges.d.ts +2 -10
- package/dist/types/wallet-server/src/core/authService/emailOtpSeal.d.ts +1 -1
- package/dist/types/wallet-server/src/core/authService/emailOtpUnlock.d.ts +3 -10
- package/dist/types/wallet-server/src/core/d1EcdsaSignerRead.d.ts +39 -0
- package/dist/types/wallet-server/src/core/d1WalletStore.d.ts +10 -0
- package/dist/types/wallet-server/src/core/deviceLinking/linkedDeviceSessionRecord.d.ts +3 -4
- package/dist/types/wallet-server/src/core/ecdsaMaterialReadSnapshot.d.ts +19 -0
- package/dist/types/wallet-server/src/core/routerAbSigning/RouterAbNormalSigningRuntime.d.ts +3 -5
- package/dist/types/wallet-server/src/core/rpcClients/near/NearClient.d.ts +1 -2
- package/dist/types/wallet-server/src/core/signingLanes/WalletExecutionLaneProjection.d.ts +2 -11
- package/dist/types/wallet-server/src/core/signingLanes/signingWorkerLaneMaterialIdentity.d.ts +2 -19
- package/dist/types/wallet-server/src/core/thresholdEcdsaChainTarget.d.ts +3 -11
- package/dist/types/wallet-server/src/core/types.d.ts +2 -6
- package/dist/types/wallet-server/src/localIntendedMaterialAdmissionFault.d.ts +38 -0
- package/dist/types/wallet-server/src/localIntendedPresignCancellation.d.ts +4 -0
- package/dist/types/wallet-server/src/router/auth/authRequestValidation.d.ts +4 -9
- package/dist/types/wallet-server/src/router/auth/commonRouterUtils.d.ts +15 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthBoundary.d.ts +0 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/d1RouterApiAuthService.d.ts +1 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/auth/walletSessionCredentialReaders.d.ts +9 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/authorizedOperationStatements.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/authorization/d1AuthorizationStore.d.ts +10 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.d.ts +19 -2
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceSessionStore.d.ts +2 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/deviceLinking/d1LinkedDeviceTargetCredentialProvider.d.ts +5 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpEnrollmentStore.d.ts +2 -8
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRateLimitStore.d.ts +2 -9
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpRecords.d.ts +5 -5
- package/dist/types/wallet-server/src/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.d.ts +4 -14
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1RegistrationCeremonyRecordStore.d.ts +2 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/registration/d1WalletRegistrationService.d.ts +8 -6
- package/dist/types/wallet-server/src/router/cloudflare/d1/signingAdmission/d1RouterAbNormalSigningAdmissionStore.d.ts +14 -1
- package/dist/types/wallet-server/src/router/cloudflare/d1/webauthn/d1WebAuthnRecords.d.ts +10 -39
- package/dist/types/wallet-server/src/router/cloudflare/runtime/walletConsoleOps.d.ts +8 -34
- package/dist/types/wallet-server/src/router/domains/ecdsa/thresholdEcdsaRequestValidation.d.ts +3 -15
- package/dist/types/wallet-server/src/router/domains/ed25519Yao/session/routerAbEd25519YaoWalletSession.d.ts +9 -50
- package/dist/types/wallet-server/src/router/domains/passkeyCustody/walletRecoveryKeyManifest.d.ts +1 -13
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbEcdsaDerivationNormalSigningRoute.d.ts +8 -9
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbNormalSigningAdmission.d.ts +13 -0
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbOperationStepUp.d.ts +3 -4
- package/dist/types/wallet-server/src/router/domains/signingOperations/routerAbPrivateSigningWorker.d.ts +7 -16
- package/dist/types/wallet-server/src/router/domains/syncAccount/syncAccountRequestValidation.d.ts +2 -7
- package/dist/types/wallet-server/src/router/framework/apiCredentialPorts.d.ts +3 -1
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +25 -4
- package/dist/types/wallet-server/src/router/framework/http.d.ts +1 -0
- package/dist/types/wallet-server/src/router/framework/ror/normalize.d.ts +1 -9
- package/dist/types/wallet-server/src/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.d.ts +3 -6
- package/dist/types/wallet-server/src/router/transport/fetch/routes/syncAccountBootstrap.d.ts +3 -5
- package/dist/types/wallet-server/src/router/transport/fetch/routes/thresholdEcdsa.d.ts +0 -1
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/idempotencyRecords.d.ts +1 -2
- package/dist/types/wallet-server/src/threshold/session/signingSessionSeal/signingSessionSeal.types.d.ts +6 -8
- package/package.json +1 -1
- package/dist/esm/wasm/router_ab_ecdsa_signing_worker/pkg/router_ab_ecdsa_signing_worker_bg.wasm +0 -0
|
@@ -2,6 +2,7 @@ import { base64UrlDecode, base64UrlEncode } from "../../shared-ts/src/utils/base
|
|
|
2
2
|
import "../../shared-ts/src/utils/encoders.js";
|
|
3
3
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
4
4
|
import "../../shared-ts/src/utils/validation.js";
|
|
5
|
+
import { failedVerification, failure } from "../../shared-ts/src/utils/failure.js";
|
|
5
6
|
import { validateSecp256k1PublicKey33, verifySecp256k1RecoverableSignatureAgainstPublicKey33 } from "../ThresholdService/evmCryptoWasm.js";
|
|
6
7
|
import { errorMessage } from "../../shared-ts/src/utils/errors.js";
|
|
7
8
|
import { parseBoundaryWalletId } from "./webauthnWalletBinding.js";
|
|
@@ -60,27 +61,15 @@ async function createEmailOtpUnlockChallenge(input) {
|
|
|
60
61
|
try {
|
|
61
62
|
const walletId = parsedUnlockWalletId(input.request.walletId);
|
|
62
63
|
const orgId = normalizeOptionalTrimmedString(input.request.orgId) || void 0;
|
|
63
|
-
if (!normalizeOptionalTrimmedString(input.request.walletId)) return
|
|
64
|
-
|
|
65
|
-
code: "invalid_body",
|
|
66
|
-
message: "Missing walletId"
|
|
67
|
-
};
|
|
68
|
-
if (!walletId) return {
|
|
69
|
-
ok: false,
|
|
70
|
-
code: "invalid_body",
|
|
71
|
-
message: "Invalid walletId"
|
|
72
|
-
};
|
|
64
|
+
if (!normalizeOptionalTrimmedString(input.request.walletId)) return failure("invalid_body", "Missing walletId");
|
|
65
|
+
if (!walletId) return failure("invalid_body", "Invalid walletId");
|
|
73
66
|
const activeEnrollment = await input.readActiveEnrollment({
|
|
74
67
|
walletId,
|
|
75
68
|
orgId
|
|
76
69
|
});
|
|
77
70
|
if (!activeEnrollment.ok) return activeEnrollment;
|
|
78
71
|
const enrollment = activeEnrollment.enrollment;
|
|
79
|
-
if (typeof crypto === "undefined" || typeof crypto.getRandomValues !== "function") return
|
|
80
|
-
ok: false,
|
|
81
|
-
code: "unsupported",
|
|
82
|
-
message: "crypto.getRandomValues is unavailable in this runtime"
|
|
83
|
-
};
|
|
72
|
+
if (typeof crypto === "undefined" || typeof crypto.getRandomValues !== "function") return failure("unsupported", "crypto.getRandomValues is unavailable in this runtime");
|
|
84
73
|
const createdAtMs = Date.now();
|
|
85
74
|
const expiresAtMs = createdAtMs + clampedUnlockTtlMs(input.request.ttlMs ?? input.request.ttl_ms);
|
|
86
75
|
const challengeId = base64UrlEncode(crypto.getRandomValues(new Uint8Array(16)));
|
|
@@ -104,11 +93,7 @@ async function createEmailOtpUnlockChallenge(input) {
|
|
|
104
93
|
unlockKeyVersion: enrollment.unlockKeyVersion
|
|
105
94
|
};
|
|
106
95
|
} catch (e) {
|
|
107
|
-
return
|
|
108
|
-
ok: false,
|
|
109
|
-
code: "internal",
|
|
110
|
-
message: errorMessage(e) || "Failed to create Email OTP unlock challenge"
|
|
111
|
-
};
|
|
96
|
+
return failure("internal", errorMessage(e) || "Failed to create Email OTP unlock challenge");
|
|
112
97
|
}
|
|
113
98
|
}
|
|
114
99
|
async function verifyEmailOtpUnlockProof(input) {
|
|
@@ -116,61 +101,21 @@ async function verifyEmailOtpUnlockProof(input) {
|
|
|
116
101
|
const walletId = parsedUnlockWalletId(input.request.walletId);
|
|
117
102
|
const orgId = normalizeOptionalTrimmedString(input.request.orgId) || void 0;
|
|
118
103
|
const challengeId = normalizeOptionalTrimmedString(input.request.challengeId);
|
|
119
|
-
if (!normalizeOptionalTrimmedString(input.request.walletId)) return
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
code: "invalid_body",
|
|
123
|
-
message: "Missing walletId"
|
|
124
|
-
};
|
|
125
|
-
if (!walletId) return {
|
|
126
|
-
ok: false,
|
|
127
|
-
verified: false,
|
|
128
|
-
code: "invalid_body",
|
|
129
|
-
message: "Invalid walletId"
|
|
130
|
-
};
|
|
131
|
-
if (!challengeId) return {
|
|
132
|
-
ok: false,
|
|
133
|
-
verified: false,
|
|
134
|
-
code: "invalid_body",
|
|
135
|
-
message: "Missing challengeId"
|
|
136
|
-
};
|
|
104
|
+
if (!normalizeOptionalTrimmedString(input.request.walletId)) return failedVerification("invalid_body", "Missing walletId");
|
|
105
|
+
if (!walletId) return failedVerification("invalid_body", "Invalid walletId");
|
|
106
|
+
if (!challengeId) return failedVerification("invalid_body", "Missing challengeId");
|
|
137
107
|
const unlockProof = parseUnlockProof(input.request.unlockProof);
|
|
138
|
-
if (!unlockProof) return
|
|
139
|
-
ok: false,
|
|
140
|
-
verified: false,
|
|
141
|
-
code: "invalid_body",
|
|
142
|
-
message: "unlockProof is required"
|
|
143
|
-
};
|
|
108
|
+
if (!unlockProof) return failedVerification("invalid_body", "unlockProof is required");
|
|
144
109
|
const challengeRecord = await input.unlockChallengeStore.consume(challengeId);
|
|
145
|
-
if (!challengeRecord || Date.now() > challengeRecord.expiresAtMs) return
|
|
146
|
-
|
|
147
|
-
verified: false,
|
|
148
|
-
code: "challenge_expired_or_invalid",
|
|
149
|
-
message: "Email OTP unlock challenge expired or invalid"
|
|
150
|
-
};
|
|
151
|
-
if (challengeRecord.walletId !== walletId) return {
|
|
152
|
-
ok: false,
|
|
153
|
-
verified: false,
|
|
154
|
-
code: "challenge_binding_mismatch",
|
|
155
|
-
message: "Email OTP unlock challenge is not valid for this walletId"
|
|
156
|
-
};
|
|
110
|
+
if (!challengeRecord || Date.now() > challengeRecord.expiresAtMs) return failedVerification("challenge_expired_or_invalid", "Email OTP unlock challenge expired or invalid");
|
|
111
|
+
if (challengeRecord.walletId !== walletId) return failedVerification("challenge_binding_mismatch", "Email OTP unlock challenge is not valid for this walletId");
|
|
157
112
|
const activeEnrollment = await input.readActiveEnrollment({
|
|
158
113
|
walletId,
|
|
159
114
|
orgId
|
|
160
115
|
});
|
|
161
|
-
if (!activeEnrollment.ok) return
|
|
162
|
-
ok: false,
|
|
163
|
-
verified: false,
|
|
164
|
-
code: activeEnrollment.code,
|
|
165
|
-
message: activeEnrollment.message
|
|
166
|
-
};
|
|
116
|
+
if (!activeEnrollment.ok) return failedVerification(activeEnrollment.code, activeEnrollment.message);
|
|
167
117
|
const enrollment = activeEnrollment.enrollment;
|
|
168
|
-
if (challengeRecord.userId !== enrollment.providerUserId || challengeRecord.orgId !== enrollment.orgId) return
|
|
169
|
-
ok: false,
|
|
170
|
-
verified: false,
|
|
171
|
-
code: "challenge_binding_mismatch",
|
|
172
|
-
message: "Email OTP unlock challenge is not valid for this enrollment"
|
|
173
|
-
};
|
|
118
|
+
if (challengeRecord.userId !== enrollment.providerUserId || challengeRecord.orgId !== enrollment.orgId) return failedVerification("challenge_binding_mismatch", "Email OTP unlock challenge is not valid for this enrollment");
|
|
174
119
|
const publicKeyDecode = decodeBase64UrlField({
|
|
175
120
|
value: unlockProof.publicKey,
|
|
176
121
|
missingMessage: "unlockProof.publicKey is required",
|
|
@@ -178,21 +123,11 @@ async function verifyEmailOtpUnlockProof(input) {
|
|
|
178
123
|
expectedLength: 33,
|
|
179
124
|
expectedLengthMessage: "unlockProof.publicKey must decode to 33 bytes"
|
|
180
125
|
});
|
|
181
|
-
if (!publicKeyDecode.ok) return
|
|
182
|
-
ok: false,
|
|
183
|
-
verified: false,
|
|
184
|
-
code: "invalid_body",
|
|
185
|
-
message: publicKeyDecode.message
|
|
186
|
-
};
|
|
126
|
+
if (!publicKeyDecode.ok) return failedVerification("invalid_body", publicKeyDecode.message);
|
|
187
127
|
try {
|
|
188
128
|
await validateSecp256k1PublicKey33(publicKeyDecode.bytes);
|
|
189
129
|
} catch {
|
|
190
|
-
return
|
|
191
|
-
ok: false,
|
|
192
|
-
verified: false,
|
|
193
|
-
code: "invalid_body",
|
|
194
|
-
message: "unlockProof.publicKey is not a valid secp256k1 public key"
|
|
195
|
-
};
|
|
130
|
+
return failedVerification("invalid_body", "unlockProof.publicKey is not a valid secp256k1 public key");
|
|
196
131
|
}
|
|
197
132
|
const signatureDecode = decodeBase64UrlField({
|
|
198
133
|
value: unlockProof.signatureB64u,
|
|
@@ -201,18 +136,8 @@ async function verifyEmailOtpUnlockProof(input) {
|
|
|
201
136
|
expectedLength: 65,
|
|
202
137
|
expectedLengthMessage: "unlockProof.signature must decode to 65 bytes"
|
|
203
138
|
});
|
|
204
|
-
if (!signatureDecode.ok) return
|
|
205
|
-
|
|
206
|
-
verified: false,
|
|
207
|
-
code: "invalid_body",
|
|
208
|
-
message: signatureDecode.message
|
|
209
|
-
};
|
|
210
|
-
if (!byteArraysEqual(base64UrlDecode(enrollment.clientUnlockPublicKeyB64u), publicKeyDecode.bytes)) return {
|
|
211
|
-
ok: false,
|
|
212
|
-
verified: false,
|
|
213
|
-
code: "invalid_unlock_proof",
|
|
214
|
-
message: "unlockProof.publicKey does not match the enrolled clientUnlockPublicKeyB64u"
|
|
215
|
-
};
|
|
139
|
+
if (!signatureDecode.ok) return failedVerification("invalid_body", signatureDecode.message);
|
|
140
|
+
if (!byteArraysEqual(base64UrlDecode(enrollment.clientUnlockPublicKeyB64u), publicKeyDecode.bytes)) return failedVerification("invalid_unlock_proof", "unlockProof.publicKey does not match the enrolled clientUnlockPublicKeyB64u");
|
|
216
141
|
const challengeDigestDecode = decodeBase64UrlField({
|
|
217
142
|
value: challengeRecord.challengeB64u,
|
|
218
143
|
missingMessage: "Stored unlock challenge digest was invalid",
|
|
@@ -220,21 +145,11 @@ async function verifyEmailOtpUnlockProof(input) {
|
|
|
220
145
|
expectedLength: 32,
|
|
221
146
|
expectedLengthMessage: "Stored unlock challenge digest must decode to 32 bytes"
|
|
222
147
|
});
|
|
223
|
-
if (!challengeDigestDecode.ok) return
|
|
224
|
-
ok: false,
|
|
225
|
-
verified: false,
|
|
226
|
-
code: "internal",
|
|
227
|
-
message: challengeDigestDecode.message
|
|
228
|
-
};
|
|
148
|
+
if (!challengeDigestDecode.ok) return failedVerification("internal", challengeDigestDecode.message);
|
|
229
149
|
try {
|
|
230
150
|
await verifySecp256k1RecoverableSignatureAgainstPublicKey33(challengeDigestDecode.bytes, signatureDecode.bytes, publicKeyDecode.bytes);
|
|
231
151
|
} catch {
|
|
232
|
-
return
|
|
233
|
-
ok: false,
|
|
234
|
-
verified: false,
|
|
235
|
-
code: "invalid_unlock_proof",
|
|
236
|
-
message: "unlockProof.signature did not verify against unlockProof.publicKey"
|
|
237
|
-
};
|
|
152
|
+
return failedVerification("invalid_unlock_proof", "unlockProof.signature did not verify against unlockProof.publicKey");
|
|
238
153
|
}
|
|
239
154
|
const nowMs = Date.now();
|
|
240
155
|
await input.putAuthStateForEnrollment(enrollment, { lastEmailOtpLoginAtMs: nowMs });
|
|
@@ -250,12 +165,7 @@ async function verifyEmailOtpUnlockProof(input) {
|
|
|
250
165
|
unlockKeyVersion: enrollment.unlockKeyVersion
|
|
251
166
|
};
|
|
252
167
|
} catch (e) {
|
|
253
|
-
return
|
|
254
|
-
ok: false,
|
|
255
|
-
verified: false,
|
|
256
|
-
code: "internal",
|
|
257
|
-
message: errorMessage(e) || "Failed to verify Email OTP unlock proof"
|
|
258
|
-
};
|
|
168
|
+
return failedVerification("internal", errorMessage(e) || "Failed to verify Email OTP unlock proof");
|
|
259
169
|
}
|
|
260
170
|
}
|
|
261
171
|
//#endregion
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { parseGoogleProviderSubject, parseOrgId, parseVerifiedGoogleEmail } from "../../shared-ts/src/utils/domainIds.js";
|
|
2
2
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
3
3
|
import "../../shared-ts/src/utils/validation.js";
|
|
4
|
+
import { failure } from "../../shared-ts/src/utils/failure.js";
|
|
4
5
|
import { GOOGLE_EMAIL_OTP_STALE_IDENTITY_MESSAGE } from "./googleEmailOtpErrors.js";
|
|
5
|
-
import {
|
|
6
|
+
import { randomBase64Url } from "./bytes.js";
|
|
6
7
|
import { readActiveEmailOtpEnrollmentWithStore } from "./emailOtpEnrollment.js";
|
|
7
8
|
//#region src/core/authService/googleEmailOtpRegistration.ts
|
|
8
9
|
async function cleanupGoogleEmailOtpRegistrationAttemptsWithStore(input) {
|
|
@@ -11,23 +12,11 @@ async function cleanupGoogleEmailOtpRegistrationAttemptsWithStore(input) {
|
|
|
11
12
|
async function consumeGoogleEmailOtpRegistrationAttemptRateLimitWithDeps(input) {
|
|
12
13
|
if (normalizeOptionalTrimmedString(input.request.accountMode)?.toLowerCase() !== "register") return { ok: true };
|
|
13
14
|
const providerSubject = parseGoogleProviderSubject(input.request.providerSubject);
|
|
14
|
-
if (!providerSubject.ok) return
|
|
15
|
-
ok: false,
|
|
16
|
-
code: "invalid_body",
|
|
17
|
-
message: providerSubject.error.message
|
|
18
|
-
};
|
|
15
|
+
if (!providerSubject.ok) return failure("invalid_body", providerSubject.error.message);
|
|
19
16
|
const email = parseVerifiedGoogleEmail(input.request.email);
|
|
20
|
-
if (!email.ok) return
|
|
21
|
-
ok: false,
|
|
22
|
-
code: "invalid_body",
|
|
23
|
-
message: email.error.message
|
|
24
|
-
};
|
|
17
|
+
if (!email.ok) return failure("invalid_body", email.error.message);
|
|
25
18
|
const orgId = parseOrgId(input.request.runtimePolicyScope?.orgId);
|
|
26
|
-
if (!orgId.ok) return
|
|
27
|
-
ok: false,
|
|
28
|
-
code: "invalid_body",
|
|
29
|
-
message: orgId.error.message
|
|
30
|
-
};
|
|
19
|
+
if (!orgId.ok) return failure("invalid_body", orgId.error.message);
|
|
31
20
|
const restartOffer = isTruthyBoundaryFlag(input.request.restartRegistrationOffer);
|
|
32
21
|
return await input.consumeRateLimit({
|
|
33
22
|
scope: "googleRegistrationAttempt",
|
|
@@ -79,34 +68,18 @@ async function completeGoogleEmailOtpRegistrationAttemptWithStore(input) {
|
|
|
79
68
|
if (!registrationAttemptId) return { ok: true };
|
|
80
69
|
const walletId = normalizeOptionalTrimmedString(input.walletId);
|
|
81
70
|
const attempt = await input.registrationAttemptStore.get(registrationAttemptId);
|
|
82
|
-
if (!attempt) return
|
|
83
|
-
ok: false,
|
|
84
|
-
code: "registration_incomplete",
|
|
85
|
-
message: "Google Email OTP registration attempt expired or was not found"
|
|
86
|
-
};
|
|
71
|
+
if (!attempt) return failure("registration_incomplete", "Google Email OTP registration attempt expired or was not found");
|
|
87
72
|
if (attempt.expiresAtMs <= input.nowMs) {
|
|
88
73
|
await input.registrationAttemptStore.put({
|
|
89
74
|
...attempt,
|
|
90
75
|
state: "expired",
|
|
91
76
|
updatedAtMs: input.nowMs
|
|
92
77
|
});
|
|
93
|
-
return
|
|
94
|
-
ok: false,
|
|
95
|
-
code: "registration_incomplete",
|
|
96
|
-
message: "Google Email OTP registration attempt expired"
|
|
97
|
-
};
|
|
78
|
+
return failure("registration_incomplete", "Google Email OTP registration attempt expired");
|
|
98
79
|
}
|
|
99
|
-
if (walletId !== attempt.walletId) return
|
|
100
|
-
ok: false,
|
|
101
|
-
code: "wallet_identity_mismatch",
|
|
102
|
-
message: "registrationAttemptId does not match walletId"
|
|
103
|
-
};
|
|
80
|
+
if (walletId !== attempt.walletId) return failure("wallet_identity_mismatch", "registrationAttemptId does not match walletId");
|
|
104
81
|
if (attempt.state === "active") return { ok: true };
|
|
105
|
-
if (attempt.state !== "started" && attempt.state !== "key_finalized") return
|
|
106
|
-
ok: false,
|
|
107
|
-
code: "registration_incomplete",
|
|
108
|
-
message: "Google Email OTP registration attempt is no longer active"
|
|
109
|
-
};
|
|
82
|
+
if (attempt.state !== "started" && attempt.state !== "key_finalized") return failure("registration_incomplete", "Google Email OTP registration attempt is no longer active");
|
|
110
83
|
const linked = await input.identityStore.linkSubjectToUserId({
|
|
111
84
|
userId: attempt.walletId,
|
|
112
85
|
subject: `wallet:${attempt.providerSubject}`,
|
|
@@ -119,11 +92,7 @@ async function completeGoogleEmailOtpRegistrationAttemptWithStore(input) {
|
|
|
119
92
|
failureCode: linked.code,
|
|
120
93
|
updatedAtMs: input.nowMs
|
|
121
94
|
});
|
|
122
|
-
return
|
|
123
|
-
ok: false,
|
|
124
|
-
code: linked.code,
|
|
125
|
-
message: linked.message
|
|
126
|
-
};
|
|
95
|
+
return failure(linked.code, linked.message);
|
|
127
96
|
}
|
|
128
97
|
await input.registrationAttemptStore.put({
|
|
129
98
|
...attempt,
|
|
@@ -137,52 +106,24 @@ async function validateGoogleEmailOtpRegistrationCandidateWalletWithStore(input)
|
|
|
137
106
|
const walletId = normalizeOptionalTrimmedString(input.walletId);
|
|
138
107
|
const ownerProofBindingDigest = normalizeOptionalTrimmedString(input.ownerProofBindingDigest);
|
|
139
108
|
const providerSubject = normalizeOptionalTrimmedString(input.providerSubject);
|
|
140
|
-
if (!registrationAttemptId || !walletId || !ownerProofBindingDigest || !providerSubject) return
|
|
141
|
-
ok: false,
|
|
142
|
-
code: "invalid_body",
|
|
143
|
-
message: "Google Email OTP registration candidate validation requires signed session scope"
|
|
144
|
-
};
|
|
109
|
+
if (!registrationAttemptId || !walletId || !ownerProofBindingDigest || !providerSubject) return failure("invalid_body", "Google Email OTP registration candidate validation requires signed session scope");
|
|
145
110
|
const attempt = await input.registrationAttemptStore.get(registrationAttemptId);
|
|
146
|
-
if (!attempt) return
|
|
147
|
-
ok: false,
|
|
148
|
-
code: "registration_attempt_missing",
|
|
149
|
-
message: "Google Email OTP registration attempt expired or was not found"
|
|
150
|
-
};
|
|
111
|
+
if (!attempt) return failure("registration_attempt_missing", "Google Email OTP registration attempt expired or was not found");
|
|
151
112
|
if (attempt.expiresAtMs <= input.nowMs) {
|
|
152
113
|
await input.registrationAttemptStore.put({
|
|
153
114
|
...attempt,
|
|
154
115
|
state: "expired",
|
|
155
116
|
updatedAtMs: input.nowMs
|
|
156
117
|
});
|
|
157
|
-
return
|
|
158
|
-
ok: false,
|
|
159
|
-
code: "registration_attempt_expired",
|
|
160
|
-
message: "Google Email OTP registration attempt expired"
|
|
161
|
-
};
|
|
118
|
+
return failure("registration_attempt_expired", "Google Email OTP registration attempt expired");
|
|
162
119
|
}
|
|
163
|
-
if (attempt.providerSubject !== providerSubject) return
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
message: "Email OTP registration attempt does not match the provider subject"
|
|
167
|
-
};
|
|
168
|
-
if (attempt.ownerProofBindingDigest !== ownerProofBindingDigest) return {
|
|
169
|
-
ok: false,
|
|
170
|
-
code: "owner_proof_binding_mismatch",
|
|
171
|
-
message: "Google Email OTP registration attempt does not match the owner proof binding"
|
|
172
|
-
};
|
|
173
|
-
if (attempt.state !== "started" && attempt.state !== "key_finalized") return {
|
|
174
|
-
ok: false,
|
|
175
|
-
code: "registration_incomplete",
|
|
176
|
-
message: "Google Email OTP registration attempt is no longer active"
|
|
177
|
-
};
|
|
120
|
+
if (attempt.providerSubject !== providerSubject) return failure("challenge_subject_mismatch", "Email OTP registration attempt does not match the provider subject");
|
|
121
|
+
if (attempt.ownerProofBindingDigest !== ownerProofBindingDigest) return failure("owner_proof_binding_mismatch", "Google Email OTP registration attempt does not match the owner proof binding");
|
|
122
|
+
if (attempt.state !== "started" && attempt.state !== "key_finalized") return failure("registration_incomplete", "Google Email OTP registration attempt is no longer active");
|
|
178
123
|
if (!findGoogleEmailOtpOfferCandidateByWalletId({
|
|
179
124
|
candidates: attempt.offerCandidates,
|
|
180
125
|
walletId
|
|
181
|
-
})) return
|
|
182
|
-
ok: false,
|
|
183
|
-
code: "wallet_identity_mismatch",
|
|
184
|
-
message: "walletId is not an active Google Email OTP registration candidate"
|
|
185
|
-
};
|
|
126
|
+
})) return failure("wallet_identity_mismatch", "walletId is not an active Google Email OTP registration candidate");
|
|
186
127
|
return { ok: true };
|
|
187
128
|
}
|
|
188
129
|
async function recordGoogleEmailOtpRegistrationAttemptPublicKeyWithStore(input) {
|
|
@@ -191,33 +132,17 @@ async function recordGoogleEmailOtpRegistrationAttemptPublicKeyWithStore(input)
|
|
|
191
132
|
const walletId = normalizeOptionalTrimmedString(input.walletId);
|
|
192
133
|
const finalizedPublicKey = normalizeOptionalTrimmedString(input.finalizedPublicKey);
|
|
193
134
|
const attempt = await input.registrationAttemptStore.get(registrationAttemptId);
|
|
194
|
-
if (!attempt) return
|
|
195
|
-
ok: false,
|
|
196
|
-
code: "registration_incomplete",
|
|
197
|
-
message: "Google Email OTP registration attempt expired or was not found"
|
|
198
|
-
};
|
|
135
|
+
if (!attempt) return failure("registration_incomplete", "Google Email OTP registration attempt expired or was not found");
|
|
199
136
|
if (attempt.expiresAtMs <= input.nowMs) {
|
|
200
137
|
await input.registrationAttemptStore.put({
|
|
201
138
|
...attempt,
|
|
202
139
|
state: "expired",
|
|
203
140
|
updatedAtMs: input.nowMs
|
|
204
141
|
});
|
|
205
|
-
return
|
|
206
|
-
ok: false,
|
|
207
|
-
code: "registration_incomplete",
|
|
208
|
-
message: "Google Email OTP registration attempt expired"
|
|
209
|
-
};
|
|
142
|
+
return failure("registration_incomplete", "Google Email OTP registration attempt expired");
|
|
210
143
|
}
|
|
211
|
-
if (walletId !== attempt.walletId) return
|
|
212
|
-
|
|
213
|
-
code: "wallet_identity_mismatch",
|
|
214
|
-
message: "registrationAttemptId does not match walletId"
|
|
215
|
-
};
|
|
216
|
-
if (attempt.state !== "started" && attempt.state !== "key_finalized" && attempt.state !== "active") return {
|
|
217
|
-
ok: false,
|
|
218
|
-
code: "registration_incomplete",
|
|
219
|
-
message: "Google Email OTP registration attempt is no longer active"
|
|
220
|
-
};
|
|
144
|
+
if (walletId !== attempt.walletId) return failure("wallet_identity_mismatch", "registrationAttemptId does not match walletId");
|
|
145
|
+
if (attempt.state !== "started" && attempt.state !== "key_finalized" && attempt.state !== "active") return failure("registration_incomplete", "Google Email OTP registration attempt is no longer active");
|
|
221
146
|
if (attempt.state === "started") {
|
|
222
147
|
if (!finalizedPublicKey) await input.registrationAttemptStore.put({
|
|
223
148
|
...attempt,
|
|
@@ -253,17 +178,9 @@ async function failGoogleEmailOtpRegistrationAttemptWithStore(input) {
|
|
|
253
178
|
});
|
|
254
179
|
}
|
|
255
180
|
async function cleanupGoogleEmailOtpDevRegistrationStateWithStores(input) {
|
|
256
|
-
if (input.isProductionEnvironment) return
|
|
257
|
-
ok: false,
|
|
258
|
-
code: "not_found",
|
|
259
|
-
message: "Google Email OTP dev cleanup is not available"
|
|
260
|
-
};
|
|
181
|
+
if (input.isProductionEnvironment) return failure("not_found", "Google Email OTP dev cleanup is not available");
|
|
261
182
|
const providerSubject = normalizeOptionalTrimmedString(input.providerSubject);
|
|
262
|
-
if (!providerSubject || !providerSubject.startsWith("google:")) return
|
|
263
|
-
ok: false,
|
|
264
|
-
code: "invalid_body",
|
|
265
|
-
message: "Missing Google provider subject"
|
|
266
|
-
};
|
|
183
|
+
if (!providerSubject || !providerSubject.startsWith("google:")) return failure("invalid_body", "Missing Google provider subject");
|
|
267
184
|
const requestedWalletId = normalizeOptionalTrimmedString(input.walletId);
|
|
268
185
|
const requestedOrgId = normalizeOptionalTrimmedString(input.orgId);
|
|
269
186
|
const nowMsRaw = typeof input.nowMs === "number" ? input.nowMs : Number(input.nowMs);
|
|
@@ -473,7 +390,7 @@ async function resolveRegistrationForExistingEnrollment(input) {
|
|
|
473
390
|
async function createGoogleEmailOtpRegistrationOffer(input) {
|
|
474
391
|
const nowMs = Date.now();
|
|
475
392
|
const authProvider = "google_oidc";
|
|
476
|
-
const walletIdDerivationNonce =
|
|
393
|
+
const walletIdDerivationNonce = randomBase64Url(18);
|
|
477
394
|
const offerCandidates = [];
|
|
478
395
|
for (let attempt = 0; attempt < 30 && offerCandidates.length < 5; attempt += 1) {
|
|
479
396
|
const candidate = await input.deriveHostedWalletId({
|
|
@@ -491,7 +408,7 @@ async function createGoogleEmailOtpRegistrationOffer(input) {
|
|
|
491
408
|
if (await input.walletEnrollmentStore.get(candidate) || inUseByLiveAttempt) continue;
|
|
492
409
|
if (hasDifferentWalletIdentityLink(await input.identityStore.listSubjectsByUserId(candidate), `wallet:${input.request.providerSubject}`)) continue;
|
|
493
410
|
offerCandidates.push({
|
|
494
|
-
candidateId:
|
|
411
|
+
candidateId: randomBase64Url(18),
|
|
495
412
|
walletId: candidate,
|
|
496
413
|
collisionCounter: attempt
|
|
497
414
|
});
|
|
@@ -507,7 +424,7 @@ async function createGoogleEmailOtpRegistrationOffer(input) {
|
|
|
507
424
|
};
|
|
508
425
|
const nonEmptyOfferCandidates = [selectedCandidate, ...remainingOfferCandidates];
|
|
509
426
|
const walletId = selectedCandidate.walletId;
|
|
510
|
-
const offerId =
|
|
427
|
+
const offerId = randomBase64Url(18);
|
|
511
428
|
return registrationAttemptStartedResponse({
|
|
512
429
|
attempt: await createGoogleEmailOtpRegistrationAttempt({
|
|
513
430
|
registrationAttemptStore: input.registrationAttemptStore,
|
|
@@ -535,7 +452,7 @@ async function createGoogleEmailOtpRegistrationAttempt(input) {
|
|
|
535
452
|
});
|
|
536
453
|
const attempt = {
|
|
537
454
|
version: "google_email_otp_registration_attempt_v1",
|
|
538
|
-
attemptId:
|
|
455
|
+
attemptId: randomBase64Url(18),
|
|
539
456
|
providerSubject: input.providerSubject,
|
|
540
457
|
email: input.email,
|
|
541
458
|
walletId: input.walletId,
|
|
@@ -604,11 +521,7 @@ async function repairGoogleEmailOtpWalletLink(input) {
|
|
|
604
521
|
subject: `wallet:${input.providerSubject}`,
|
|
605
522
|
allowMoveIfSoleIdentity: true
|
|
606
523
|
});
|
|
607
|
-
if (!linked.ok) return
|
|
608
|
-
ok: false,
|
|
609
|
-
code: linked.code,
|
|
610
|
-
message: linked.message
|
|
611
|
-
};
|
|
524
|
+
if (!linked.ok) return failure(linked.code, linked.message);
|
|
612
525
|
return { ok: true };
|
|
613
526
|
}
|
|
614
527
|
function isGoogleEmailOtpEnrollmentLookupMiss(code) {
|
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
2
2
|
import "../../shared-ts/src/utils/validation.js";
|
|
3
|
+
import { failure } from "../../shared-ts/src/utils/failure.js";
|
|
3
4
|
import { errorMessage } from "../../shared-ts/src/utils/errors.js";
|
|
4
5
|
//#region src/core/authService/identity.ts
|
|
5
6
|
async function listIdentitiesWithStore(input) {
|
|
6
7
|
try {
|
|
7
8
|
const userId = normalizeOptionalTrimmedString(input.userId);
|
|
8
|
-
if (!userId) return
|
|
9
|
-
ok: false,
|
|
10
|
-
code: "invalid_args",
|
|
11
|
-
message: "Missing userId"
|
|
12
|
-
};
|
|
9
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
13
10
|
return {
|
|
14
11
|
ok: true,
|
|
15
12
|
subjects: await input.store.listSubjectsByUserId(userId)
|
|
16
13
|
};
|
|
17
14
|
} catch (e) {
|
|
18
|
-
return
|
|
19
|
-
ok: false,
|
|
20
|
-
code: "internal",
|
|
21
|
-
message: errorMessage(e) || "Failed to list identities"
|
|
22
|
-
};
|
|
15
|
+
return failure("internal", errorMessage(e) || "Failed to list identities");
|
|
23
16
|
}
|
|
24
17
|
}
|
|
25
18
|
async function linkIdentityWithStore(input) {
|
|
@@ -30,11 +23,7 @@ async function linkIdentityWithStore(input) {
|
|
|
30
23
|
allowMoveIfSoleIdentity: input.allowMoveIfSoleIdentity
|
|
31
24
|
});
|
|
32
25
|
} catch (e) {
|
|
33
|
-
return
|
|
34
|
-
ok: false,
|
|
35
|
-
code: "internal",
|
|
36
|
-
message: errorMessage(e) || "Failed to link identity"
|
|
37
|
-
};
|
|
26
|
+
return failure("internal", errorMessage(e) || "Failed to link identity");
|
|
38
27
|
}
|
|
39
28
|
}
|
|
40
29
|
async function unlinkIdentityWithStore(input) {
|
|
@@ -44,11 +33,7 @@ async function unlinkIdentityWithStore(input) {
|
|
|
44
33
|
subject: input.subject
|
|
45
34
|
});
|
|
46
35
|
} catch (e) {
|
|
47
|
-
return
|
|
48
|
-
ok: false,
|
|
49
|
-
code: "internal",
|
|
50
|
-
message: errorMessage(e) || "Failed to unlink identity"
|
|
51
|
-
};
|
|
36
|
+
return failure("internal", errorMessage(e) || "Failed to unlink identity");
|
|
52
37
|
}
|
|
53
38
|
}
|
|
54
39
|
//#endregion
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { parseWebAuthnRpId } from "../../shared-ts/src/utils/domainIds.js";
|
|
2
2
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
3
3
|
import "../../shared-ts/src/utils/validation.js";
|
|
4
|
+
import { failure } from "../../shared-ts/src/utils/failure.js";
|
|
4
5
|
import { errorMessage } from "../../shared-ts/src/utils/errors.js";
|
|
5
6
|
//#region src/core/authService/nearPublicKeyMetadata.ts
|
|
6
7
|
function optionalPositiveInteger(input) {
|
|
@@ -60,20 +61,12 @@ function nearPublicKeyListEntry(record) {
|
|
|
60
61
|
async function recordNearPublicKeyMetadataWithStore(input) {
|
|
61
62
|
const userId = normalizeOptionalTrimmedString(input.userId);
|
|
62
63
|
const publicKey = normalizeOptionalTrimmedString(input.publicKey);
|
|
63
|
-
if (!userId || !publicKey) return
|
|
64
|
-
ok: false,
|
|
65
|
-
code: "invalid_args",
|
|
66
|
-
message: "userId and publicKey are required"
|
|
67
|
-
};
|
|
64
|
+
if (!userId || !publicKey) return failure("invalid_args", "userId and publicKey are required");
|
|
68
65
|
const authBinding = nearPublicKeyAuthBinding({
|
|
69
66
|
credentialIdB64u: normalizeOptionalTrimmedString(input.credentialIdB64u),
|
|
70
67
|
rpIdRaw: normalizeOptionalTrimmedString(input.rpId)
|
|
71
68
|
});
|
|
72
|
-
if (!authBinding.ok) return
|
|
73
|
-
ok: false,
|
|
74
|
-
code: "invalid_args",
|
|
75
|
-
message: authBinding.message
|
|
76
|
-
};
|
|
69
|
+
if (!authBinding.ok) return failure("invalid_args", authBinding.message);
|
|
77
70
|
const record = nearPublicKeyRecord({
|
|
78
71
|
userId,
|
|
79
72
|
publicKey,
|
|
@@ -91,21 +84,13 @@ async function recordNearPublicKeyMetadataWithStore(input) {
|
|
|
91
84
|
const source = normalizeOptionalTrimmedString(input.source) || "near-public-key-metadata";
|
|
92
85
|
const message = errorMessage(error) || "Failed to persist NEAR public key metadata";
|
|
93
86
|
input.logger.warn(`[AuthService] ${source} failed for ${userId}`, error);
|
|
94
|
-
return
|
|
95
|
-
ok: false,
|
|
96
|
-
code: "internal",
|
|
97
|
-
message
|
|
98
|
-
};
|
|
87
|
+
return failure("internal", message);
|
|
99
88
|
}
|
|
100
89
|
}
|
|
101
90
|
async function listNearPublicKeysForUserWithStore(input) {
|
|
102
91
|
try {
|
|
103
92
|
const userId = String(input.userId || "").trim();
|
|
104
|
-
if (!userId) return
|
|
105
|
-
ok: false,
|
|
106
|
-
code: "invalid_args",
|
|
107
|
-
message: "Missing userId"
|
|
108
|
-
};
|
|
93
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
109
94
|
const records = await input.store.listByUserId(userId);
|
|
110
95
|
const keys = [];
|
|
111
96
|
for (const record of records || []) keys.push(nearPublicKeyListEntry(record));
|
|
@@ -114,11 +99,7 @@ async function listNearPublicKeysForUserWithStore(input) {
|
|
|
114
99
|
keys
|
|
115
100
|
};
|
|
116
101
|
} catch (e) {
|
|
117
|
-
return
|
|
118
|
-
ok: false,
|
|
119
|
-
code: "internal",
|
|
120
|
-
message: errorMessage(e) || "Failed to list keys"
|
|
121
|
-
};
|
|
102
|
+
return failure("internal", errorMessage(e) || "Failed to list keys");
|
|
122
103
|
}
|
|
123
104
|
}
|
|
124
105
|
//#endregion
|