@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 } from "../../shared-ts/src/utils/base64.js";
|
|
|
2
2
|
import "../../shared-ts/src/utils/encoders.js";
|
|
3
3
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
4
4
|
import { isPlainObject } from "../../shared-ts/src/utils/validation.js";
|
|
5
|
+
import { failedVerification } from "../../shared-ts/src/utils/failure.js";
|
|
5
6
|
import { errorMessage } from "../../shared-ts/src/utils/errors.js";
|
|
6
7
|
import { parseCacheControlMaxAgeSec, parseJwtAud, parseJwtSegmentJson } from "./webauthnOidcHelpers.js";
|
|
7
8
|
import { toArrayBufferCopy } from "./portableCrypto.js";
|
|
@@ -12,25 +13,17 @@ function createGoogleJwksState() {
|
|
|
12
13
|
fetchPromise: null
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
|
-
function jwtError(code, message) {
|
|
16
|
-
return {
|
|
17
|
-
ok: false,
|
|
18
|
-
verified: false,
|
|
19
|
-
code,
|
|
20
|
-
message
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
16
|
function requireWebCrypto() {
|
|
24
17
|
return typeof crypto !== "undefined" && Boolean(crypto.subtle);
|
|
25
18
|
}
|
|
26
19
|
function parseJwtParts(input) {
|
|
27
20
|
const parts = input.token.split(".");
|
|
28
|
-
if (parts.length !== 3) return
|
|
21
|
+
if (parts.length !== 3) return failedVerification("invalid_body", `${input.tokenName} must be a JWT (3 segments)`);
|
|
29
22
|
const [headerB64u, payloadB64u, signatureB64u] = parts;
|
|
30
23
|
const header = parseJwtSegmentJson(headerB64u);
|
|
31
|
-
if (!header) return
|
|
24
|
+
if (!header) return failedVerification("invalid_body", `Invalid ${input.tokenName} header encoding`);
|
|
32
25
|
const payload = parseJwtSegmentJson(payloadB64u);
|
|
33
|
-
if (!payload) return
|
|
26
|
+
if (!payload) return failedVerification("invalid_body", `Invalid ${input.tokenName} payload encoding`);
|
|
34
27
|
return {
|
|
35
28
|
ok: true,
|
|
36
29
|
value: {
|
|
@@ -106,26 +99,26 @@ async function verifyJwtSignature(input) {
|
|
|
106
99
|
try {
|
|
107
100
|
signatureBytes = base64UrlDecode(input.parts.signatureB64u);
|
|
108
101
|
} catch {
|
|
109
|
-
return
|
|
102
|
+
return failedVerification("invalid_body", `Invalid ${input.tokenName} signature encoding`);
|
|
110
103
|
}
|
|
111
104
|
const dataBytes = new TextEncoder().encode(`${input.parts.headerB64u}.${input.parts.payloadB64u}`);
|
|
112
105
|
const key = await crypto.subtle.importKey("jwk", input.jwk, {
|
|
113
106
|
name: "RSASSA-PKCS1-v1_5",
|
|
114
107
|
hash: "SHA-256"
|
|
115
108
|
}, false, ["verify"]);
|
|
116
|
-
if (!await crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5" }, key, toArrayBufferCopy(signatureBytes), toArrayBufferCopy(dataBytes))) return
|
|
109
|
+
if (!await crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5" }, key, toArrayBufferCopy(signatureBytes), toArrayBufferCopy(dataBytes))) return failedVerification("invalid_signature", `Invalid ${input.tokenName} signature`);
|
|
117
110
|
return { ok: true };
|
|
118
111
|
}
|
|
119
112
|
function verifyGoogleTimeClaims(payload) {
|
|
120
113
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
121
114
|
const exp = Number(payload.exp);
|
|
122
|
-
if (!Number.isFinite(exp) || exp <= 0) return
|
|
123
|
-
if (nowSec >= exp) return
|
|
115
|
+
if (!Number.isFinite(exp) || exp <= 0) return failedVerification("invalid_claims", "Invalid Google id_token exp");
|
|
116
|
+
if (nowSec >= exp) return failedVerification("expired", "Google id_token is expired");
|
|
124
117
|
const nbfRaw = payload.nbf;
|
|
125
118
|
if (nbfRaw !== void 0) {
|
|
126
119
|
const nbf = Number(nbfRaw);
|
|
127
|
-
if (!Number.isFinite(nbf)) return
|
|
128
|
-
if (nowSec < nbf) return
|
|
120
|
+
if (!Number.isFinite(nbf)) return failedVerification("invalid_claims", "Invalid Google id_token nbf");
|
|
121
|
+
if (nowSec < nbf) return failedVerification("not_yet_valid", "Google id_token is not yet valid");
|
|
129
122
|
}
|
|
130
123
|
return { ok: true };
|
|
131
124
|
}
|
|
@@ -179,10 +172,10 @@ function buildGoogleLoginFacadeSuccess(input) {
|
|
|
179
172
|
return result;
|
|
180
173
|
}
|
|
181
174
|
async function verifyGoogleIdToken(input) {
|
|
182
|
-
if (!input.config?.clientIds?.length) return
|
|
175
|
+
if (!input.config?.clientIds?.length) return failedVerification("not_configured", "Google OIDC is not configured on this server");
|
|
183
176
|
const idToken = normalizeOptionalTrimmedString(input.request.idToken ?? input.request.id_token);
|
|
184
|
-
if (!idToken) return
|
|
185
|
-
if (!requireWebCrypto()) return
|
|
177
|
+
if (!idToken) return failedVerification("invalid_body", "id_token is required");
|
|
178
|
+
if (!requireWebCrypto()) return failedVerification("unsupported", "WebCrypto (crypto.subtle) is unavailable in this runtime");
|
|
186
179
|
const parts = parseJwtParts({
|
|
187
180
|
token: idToken,
|
|
188
181
|
tokenName: "id_token"
|
|
@@ -190,10 +183,10 @@ async function verifyGoogleIdToken(input) {
|
|
|
190
183
|
if (!parts.ok) return parts;
|
|
191
184
|
const kid = normalizeOptionalTrimmedString(parts.value.header.kid);
|
|
192
185
|
const alg = normalizeOptionalTrimmedString(parts.value.header.alg);
|
|
193
|
-
if (!kid) return
|
|
194
|
-
if (alg !== "RS256") return
|
|
186
|
+
if (!kid) return failedVerification("invalid_body", "id_token header.kid is required");
|
|
187
|
+
if (alg !== "RS256") return failedVerification("invalid_body", "id_token header.alg must be RS256");
|
|
195
188
|
const jwk = (await getGoogleJwks(input.jwksState)).keysByKid.get(kid);
|
|
196
|
-
if (!jwk) return
|
|
189
|
+
if (!jwk) return failedVerification("unknown_kid", "Unknown Google key id (kid)");
|
|
197
190
|
const signature = await verifyJwtSignature({
|
|
198
191
|
jwk,
|
|
199
192
|
parts: parts.value,
|
|
@@ -201,19 +194,19 @@ async function verifyGoogleIdToken(input) {
|
|
|
201
194
|
});
|
|
202
195
|
if (!signature.ok) return signature;
|
|
203
196
|
const iss = normalizeOptionalTrimmedString(parts.value.payload.iss);
|
|
204
|
-
if (iss !== "https://accounts.google.com" && iss !== "accounts.google.com") return
|
|
197
|
+
if (iss !== "https://accounts.google.com" && iss !== "accounts.google.com") return failedVerification("invalid_issuer", "Invalid Google id_token issuer");
|
|
205
198
|
const time = verifyGoogleTimeClaims(parts.value.payload);
|
|
206
199
|
if (!time.ok) return time;
|
|
207
200
|
const aud = parseJwtAud(parts.value.payload.aud);
|
|
208
|
-
if (!aud.length) return
|
|
201
|
+
if (!aud.length) return failedVerification("invalid_claims", "Missing Google id_token aud");
|
|
209
202
|
const allowedAudSet = new Set(input.config.clientIds);
|
|
210
|
-
if (!aud.some((value) => allowedAudSet.has(value))) return
|
|
203
|
+
if (!aud.some((value) => allowedAudSet.has(value))) return failedVerification("invalid_audience", "Google id_token audience mismatch");
|
|
211
204
|
const sub = normalizeOptionalTrimmedString(parts.value.payload.sub);
|
|
212
|
-
if (!sub) return
|
|
205
|
+
if (!sub) return failedVerification("invalid_claims", "Missing Google id_token sub");
|
|
213
206
|
const hostedDomain = normalizeOptionalTrimmedString(parts.value.payload.hd);
|
|
214
207
|
if (input.config.hostedDomains?.length) {
|
|
215
208
|
const allowHd = new Set(input.config.hostedDomains.map((d) => d.toLowerCase()));
|
|
216
|
-
if (!hostedDomain || !allowHd.has(hostedDomain.toLowerCase())) return
|
|
209
|
+
if (!hostedDomain || !allowHd.has(hostedDomain.toLowerCase())) return failedVerification("invalid_hosted_domain", "Google hosted domain is not allowed");
|
|
217
210
|
}
|
|
218
211
|
const email = normalizeOptionalTrimmedString(parts.value.payload.email);
|
|
219
212
|
const name = normalizeOptionalTrimmedString(parts.value.payload.name);
|
|
@@ -247,12 +240,7 @@ async function verifyGoogleLoginWithIdentityStore(input) {
|
|
|
247
240
|
})
|
|
248
241
|
});
|
|
249
242
|
} catch (e) {
|
|
250
|
-
return
|
|
251
|
-
ok: false,
|
|
252
|
-
verified: false,
|
|
253
|
-
code: "internal",
|
|
254
|
-
message: errorMessage(e) || "Google OIDC verification failed"
|
|
255
|
-
};
|
|
243
|
+
return failedVerification("internal", errorMessage(e) || "Google OIDC verification failed");
|
|
256
244
|
}
|
|
257
245
|
}
|
|
258
246
|
//#endregion
|
|
@@ -1,5 +1,6 @@
|
|
|
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 { readAuthServiceConfigValue } from "./configValues.js";
|
|
4
5
|
import { resolveSigningSessionSealRateLimitFromEnv } from "../../threshold/session/signingSessionSeal/guards/backends.js";
|
|
5
6
|
import "../../threshold/session/signingSessionSeal/index.js";
|
|
@@ -51,11 +52,7 @@ function createEmailOtpRateLimiter(input) {
|
|
|
51
52
|
}).limiter;
|
|
52
53
|
}
|
|
53
54
|
function consumedRateLimitError(message, consumed) {
|
|
54
|
-
const result =
|
|
55
|
-
ok: false,
|
|
56
|
-
code: "rate_limited",
|
|
57
|
-
message
|
|
58
|
-
};
|
|
55
|
+
const result = failure("rate_limited", message);
|
|
59
56
|
if (typeof consumed.retryAfterMs === "number") result.retryAfterMs = consumed.retryAfterMs;
|
|
60
57
|
if (typeof consumed.resetAtMs === "number") result.resetAtMs = consumed.resetAtMs;
|
|
61
58
|
return result;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
2
2
|
import { isPlainObject } from "../../shared-ts/src/utils/validation.js";
|
|
3
|
-
import {
|
|
3
|
+
import { thresholdEcdsaChainTargetKey } from "../../shared-ts/src/utils/thresholdEcdsaChainTarget.js";
|
|
4
|
+
import { thresholdEcdsaChainTargetFromValue } from "../thresholdEcdsaChainTarget.js";
|
|
4
5
|
import { walletIdFromString } from "../../shared-ts/src/utils/registrationIds.js";
|
|
5
6
|
//#region src/core/authService/thresholdEcdsaKeyInventory.ts
|
|
6
7
|
function incrementCount(bucket, reason) {
|
|
@@ -4,6 +4,7 @@ import "../../shared-ts/src/utils/encoders.js";
|
|
|
4
4
|
import { normalizeOptionalTrimmedString } from "../../shared-ts/src/utils/normalize.js";
|
|
5
5
|
import "../../shared-ts/src/utils/validation.js";
|
|
6
6
|
import { unknownWebAuthnAuthenticatorDeviceInfo } from "../../shared-ts/src/utils/webauthnDeviceInfo.js";
|
|
7
|
+
import { failedVerification, failure } from "../../shared-ts/src/utils/failure.js";
|
|
7
8
|
import { walletIdFromString } from "../../shared-ts/src/utils/registrationIds.js";
|
|
8
9
|
import { errorMessage } from "../../shared-ts/src/utils/errors.js";
|
|
9
10
|
import { decodeBase64UrlOrBase64, isHostWithinRpId, loadSimpleWebAuthnServer, originHostnameOrEmpty, parseClientDataJsonBase64url } from "./webauthnOidcHelpers.js";
|
|
@@ -28,11 +29,7 @@ function normalizeWebAuthnTtlMs(raw) {
|
|
|
28
29
|
}
|
|
29
30
|
function ensureCryptoRandomValues() {
|
|
30
31
|
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") return true;
|
|
31
|
-
return
|
|
32
|
-
ok: false,
|
|
33
|
-
code: "unsupported",
|
|
34
|
-
message: "crypto.getRandomValues is unavailable in this runtime"
|
|
35
|
-
};
|
|
32
|
+
return failure("unsupported", "crypto.getRandomValues is unavailable in this runtime");
|
|
36
33
|
}
|
|
37
34
|
function randomWebAuthnB64u(byteLength) {
|
|
38
35
|
return base64UrlEncode(crypto.getRandomValues(new Uint8Array(byteLength)));
|
|
@@ -40,22 +37,14 @@ function randomWebAuthnB64u(byteLength) {
|
|
|
40
37
|
function credentialRawIdB64u(credential) {
|
|
41
38
|
const credentialId = credential.id.trim();
|
|
42
39
|
const chosen = credential.rawId.trim() || credentialId;
|
|
43
|
-
if (!chosen) return
|
|
44
|
-
ok: false,
|
|
45
|
-
code: "invalid_body",
|
|
46
|
-
message: "Missing webauthn_authentication.id/rawId"
|
|
47
|
-
};
|
|
40
|
+
if (!chosen) return failure("invalid_body", "Missing webauthn_authentication.id/rawId");
|
|
48
41
|
try {
|
|
49
42
|
return {
|
|
50
43
|
ok: true,
|
|
51
44
|
credentialIdB64u: base64UrlEncode(decodeBase64UrlOrBase64(chosen, "webauthn_authentication.rawId"))
|
|
52
45
|
};
|
|
53
46
|
} catch (e) {
|
|
54
|
-
return
|
|
55
|
-
ok: false,
|
|
56
|
-
code: "invalid_body",
|
|
57
|
-
message: errorMessage(e) || "Invalid credential rawId"
|
|
58
|
-
};
|
|
47
|
+
return failure("invalid_body", errorMessage(e) || "Invalid credential rawId");
|
|
59
48
|
}
|
|
60
49
|
}
|
|
61
50
|
function credentialPublicKeyBytes(record) {
|
|
@@ -65,11 +54,7 @@ function credentialPublicKeyBytes(record) {
|
|
|
65
54
|
bytes: decodeBase64UrlOrBase64(record.credentialPublicKeyB64u, "authenticator.credentialPublicKeyB64u")
|
|
66
55
|
};
|
|
67
56
|
} catch (e) {
|
|
68
|
-
return {
|
|
69
|
-
ok: false,
|
|
70
|
-
code: "internal",
|
|
71
|
-
message: `Stored credential public key is invalid: ${errorMessage(e) || "decode failed"}`
|
|
72
|
-
};
|
|
57
|
+
return failure("internal", `Stored credential public key is invalid: ${errorMessage(e) || "decode failed"}`);
|
|
73
58
|
}
|
|
74
59
|
}
|
|
75
60
|
function credentialVerificationInput(input) {
|
|
@@ -105,32 +90,16 @@ async function persistAuthenticatorCounter(input) {
|
|
|
105
90
|
}));
|
|
106
91
|
return { ok: true };
|
|
107
92
|
} catch (e) {
|
|
108
|
-
return {
|
|
109
|
-
ok: false,
|
|
110
|
-
code: "internal",
|
|
111
|
-
message: `Failed to persist authenticator counter: ${errorMessage(e) || "store error"}`
|
|
112
|
-
};
|
|
93
|
+
return failure("internal", `Failed to persist authenticator counter: ${errorMessage(e) || "store error"}`);
|
|
113
94
|
}
|
|
114
95
|
}
|
|
115
96
|
function parseWebAuthnClientDataForRegistration(input) {
|
|
116
97
|
const response = readNestedRecord(input.credential, "response");
|
|
117
98
|
const clientData = parseClientDataJsonBase64url(response ? readStringField(response, "clientDataJSON") : "");
|
|
118
|
-
if (clientData.type !== "webauthn.create") return
|
|
119
|
-
|
|
120
|
-
code: "invalid_body",
|
|
121
|
-
message: "Invalid webauthn_registration.clientDataJSON.type (expected webauthn.create)"
|
|
122
|
-
};
|
|
123
|
-
if (clientData.challenge !== input.expectedChallenge) return {
|
|
124
|
-
ok: false,
|
|
125
|
-
code: "challenge_mismatch",
|
|
126
|
-
message: "Registration challenge mismatch"
|
|
127
|
-
};
|
|
99
|
+
if (clientData.type !== "webauthn.create") return failure("invalid_body", "Invalid webauthn_registration.clientDataJSON.type (expected webauthn.create)");
|
|
100
|
+
if (clientData.challenge !== input.expectedChallenge) return failure("challenge_mismatch", "Registration challenge mismatch");
|
|
128
101
|
const originHost = originHostnameOrEmpty(clientData.origin);
|
|
129
|
-
if (!isHostWithinRpId(originHost, input.rpId)) return
|
|
130
|
-
ok: false,
|
|
131
|
-
code: "invalid_origin",
|
|
132
|
-
message: "WebAuthn origin is not within rpId"
|
|
133
|
-
};
|
|
102
|
+
if (!isHostWithinRpId(originHost, input.rpId)) return failure("invalid_origin", "WebAuthn origin is not within rpId");
|
|
134
103
|
return {
|
|
135
104
|
ok: true,
|
|
136
105
|
originHost
|
|
@@ -176,11 +145,7 @@ async function linkNearSubjectForWebAuthnLogin(input) {
|
|
|
176
145
|
}
|
|
177
146
|
async function verifyWebAuthnRegistrationCredentialForIntent(input) {
|
|
178
147
|
const credential = readRecord(input.webauthnRegistration);
|
|
179
|
-
if (!credential) return
|
|
180
|
-
ok: false,
|
|
181
|
-
code: "invalid_body",
|
|
182
|
-
message: "Missing webauthn_registration"
|
|
183
|
-
};
|
|
148
|
+
if (!credential) return failure("invalid_body", "Missing webauthn_registration");
|
|
184
149
|
const parsedClientData = parseWebAuthnClientDataForRegistration({
|
|
185
150
|
credential,
|
|
186
151
|
expectedChallenge: input.expectedChallenge,
|
|
@@ -188,17 +153,9 @@ async function verifyWebAuthnRegistrationCredentialForIntent(input) {
|
|
|
188
153
|
});
|
|
189
154
|
if (!parsedClientData.ok) return parsedClientData;
|
|
190
155
|
const expectedOrigin = normalizeOptionalTrimmedString(input.expectedOrigin);
|
|
191
|
-
if (!expectedOrigin) return
|
|
192
|
-
ok: false,
|
|
193
|
-
code: "invalid_body",
|
|
194
|
-
message: "expected_origin is required for WebAuthn registration verification"
|
|
195
|
-
};
|
|
156
|
+
if (!expectedOrigin) return failure("invalid_body", "expected_origin is required for WebAuthn registration verification");
|
|
196
157
|
const verifyRegistrationResponse = (await loadSimpleWebAuthnServer()).verifyRegistrationResponse;
|
|
197
|
-
if (typeof verifyRegistrationResponse !== "function") return
|
|
198
|
-
ok: false,
|
|
199
|
-
code: "unsupported",
|
|
200
|
-
message: "WebAuthn registration verifier is unavailable in this runtime"
|
|
201
|
-
};
|
|
158
|
+
if (typeof verifyRegistrationResponse !== "function") return failure("unsupported", "WebAuthn registration verifier is unavailable in this runtime");
|
|
202
159
|
const registration = await verifyRegistrationResponse({
|
|
203
160
|
response: credential,
|
|
204
161
|
expectedChallenge: input.expectedChallenge,
|
|
@@ -206,19 +163,11 @@ async function verifyWebAuthnRegistrationCredentialForIntent(input) {
|
|
|
206
163
|
expectedRPID: input.rpId,
|
|
207
164
|
requireUserVerification: false
|
|
208
165
|
});
|
|
209
|
-
if (!registration.verified) return
|
|
210
|
-
ok: false,
|
|
211
|
-
code: "not_verified",
|
|
212
|
-
message: "Registration verification failed"
|
|
213
|
-
};
|
|
166
|
+
if (!registration.verified) return failure("not_verified", "Registration verification failed");
|
|
214
167
|
const verifiedCredential = registration.registrationInfo?.credential;
|
|
215
168
|
const credentialIdB64u = String(verifiedCredential?.id || "").trim();
|
|
216
169
|
const credentialPublicKey = verifiedCredential?.publicKey;
|
|
217
|
-
if (!credentialIdB64u || !credentialPublicKey) return
|
|
218
|
-
ok: false,
|
|
219
|
-
code: "internal",
|
|
220
|
-
message: "Registration verification did not return credential public key material"
|
|
221
|
-
};
|
|
170
|
+
if (!credentialIdB64u || !credentialPublicKey) return failure("internal", "Registration verification did not return credential public key material");
|
|
222
171
|
return {
|
|
223
172
|
ok: true,
|
|
224
173
|
credential: {
|
|
@@ -364,16 +313,8 @@ async function listWebAuthnAuthenticatorsForUserWithStores(input) {
|
|
|
364
313
|
try {
|
|
365
314
|
const userId = String(input.userId || "").trim();
|
|
366
315
|
const rpId = String(input.rpId || "").trim();
|
|
367
|
-
if (!userId) return
|
|
368
|
-
|
|
369
|
-
code: "invalid_args",
|
|
370
|
-
message: "Missing userId"
|
|
371
|
-
};
|
|
372
|
-
if (!input.authenticatorStore.list) return {
|
|
373
|
-
ok: false,
|
|
374
|
-
code: "not_supported",
|
|
375
|
-
message: "Authenticator listing is not supported by this store"
|
|
376
|
-
};
|
|
316
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
317
|
+
if (!input.authenticatorStore.list) return failure("not_supported", "Authenticator listing is not supported by this store");
|
|
377
318
|
const bindingList = await listCredentialBindingsForUser({
|
|
378
319
|
bindingStore: input.credentialBindingStore,
|
|
379
320
|
userId,
|
|
@@ -400,33 +341,17 @@ async function listWebAuthnAuthenticatorsForUserWithStores(input) {
|
|
|
400
341
|
authenticators: merged
|
|
401
342
|
};
|
|
402
343
|
} catch (e) {
|
|
403
|
-
return
|
|
404
|
-
ok: false,
|
|
405
|
-
code: "internal",
|
|
406
|
-
message: errorMessage(e) || "Failed to list authenticators"
|
|
407
|
-
};
|
|
344
|
+
return failure("internal", errorMessage(e) || "Failed to list authenticators");
|
|
408
345
|
}
|
|
409
346
|
}
|
|
410
347
|
async function createWebAuthnLoginOptionsWithStore(input) {
|
|
411
348
|
try {
|
|
412
349
|
const userIdRaw = String(input.request.userId ?? input.request.user_id ?? "").trim();
|
|
413
350
|
const rpId = String(input.request.rpId ?? input.request.rp_id ?? "").trim();
|
|
414
|
-
if (!userIdRaw) return
|
|
415
|
-
ok: false,
|
|
416
|
-
code: "invalid_body",
|
|
417
|
-
message: "Missing userId"
|
|
418
|
-
};
|
|
351
|
+
if (!userIdRaw) return failure("invalid_body", "Missing userId");
|
|
419
352
|
const userId = parseBoundaryWalletId(userIdRaw);
|
|
420
|
-
if (!userId) return
|
|
421
|
-
|
|
422
|
-
code: "invalid_body",
|
|
423
|
-
message: "Invalid userId"
|
|
424
|
-
};
|
|
425
|
-
if (!rpId) return {
|
|
426
|
-
ok: false,
|
|
427
|
-
code: "invalid_body",
|
|
428
|
-
message: "Missing rpId"
|
|
429
|
-
};
|
|
353
|
+
if (!userId) return failure("invalid_body", "Invalid userId");
|
|
354
|
+
if (!rpId) return failure("invalid_body", "Missing rpId");
|
|
430
355
|
const randomAvailable = ensureCryptoRandomValues();
|
|
431
356
|
if (randomAvailable !== true) return randomAvailable;
|
|
432
357
|
const ttlMsClamped = normalizeWebAuthnTtlMs(input.request.ttlMs ?? input.request.ttl_ms);
|
|
@@ -450,28 +375,16 @@ async function createWebAuthnLoginOptionsWithStore(input) {
|
|
|
450
375
|
expiresAtMs
|
|
451
376
|
};
|
|
452
377
|
} catch (e) {
|
|
453
|
-
return
|
|
454
|
-
ok: false,
|
|
455
|
-
code: "internal",
|
|
456
|
-
message: errorMessage(e) || "Failed to create login options"
|
|
457
|
-
};
|
|
378
|
+
return failure("internal", errorMessage(e) || "Failed to create login options");
|
|
458
379
|
}
|
|
459
380
|
}
|
|
460
381
|
async function createWebAuthnSyncAccountOptionsWithStores(input) {
|
|
461
382
|
try {
|
|
462
383
|
const rpId = String(input.request.rp_id || "").trim();
|
|
463
|
-
if (!rpId) return
|
|
464
|
-
ok: false,
|
|
465
|
-
code: "invalid_body",
|
|
466
|
-
message: "Missing rp_id"
|
|
467
|
-
};
|
|
384
|
+
if (!rpId) return failure("invalid_body", "Missing rp_id");
|
|
468
385
|
const expectedUserIdRaw = normalizeOptionalTrimmedString(input.request.account_id);
|
|
469
386
|
const expectedUserId = expectedUserIdRaw ? parseBoundaryWalletId(expectedUserIdRaw) : null;
|
|
470
|
-
if (expectedUserIdRaw && !expectedUserId) return
|
|
471
|
-
ok: false,
|
|
472
|
-
code: "invalid_body",
|
|
473
|
-
message: "Invalid wallet account_id"
|
|
474
|
-
};
|
|
387
|
+
if (expectedUserIdRaw && !expectedUserId) return failure("invalid_body", "Invalid wallet account_id");
|
|
475
388
|
const randomAvailable = ensureCryptoRandomValues();
|
|
476
389
|
if (randomAvailable !== true) return randomAvailable;
|
|
477
390
|
const ttlMsClamped = normalizeWebAuthnTtlMs(input.request.ttlMs ?? input.request.ttl_ms);
|
|
@@ -528,47 +441,24 @@ async function createWebAuthnSyncAccountOptionsWithStores(input) {
|
|
|
528
441
|
if (walletBinding) result.walletBinding = walletBinding;
|
|
529
442
|
return result;
|
|
530
443
|
} catch (e) {
|
|
531
|
-
return
|
|
532
|
-
ok: false,
|
|
533
|
-
code: "internal",
|
|
534
|
-
message: errorMessage(e) || "Failed to create sync account options"
|
|
535
|
-
};
|
|
444
|
+
return failure("internal", errorMessage(e) || "Failed to create sync account options");
|
|
536
445
|
}
|
|
537
446
|
}
|
|
538
447
|
async function verifyWebAuthnSyncAccountWithStores(input) {
|
|
539
448
|
try {
|
|
540
449
|
const request = input.request;
|
|
541
450
|
const challengeId = String(request.challengeId ?? request.challenge_id ?? "").trim();
|
|
542
|
-
if (!challengeId) return
|
|
543
|
-
ok: false,
|
|
544
|
-
code: "invalid_body",
|
|
545
|
-
message: "Missing challengeId"
|
|
546
|
-
};
|
|
451
|
+
if (!challengeId) return failure("invalid_body", "Missing challengeId");
|
|
547
452
|
const challenge = await input.syncChallengeStore.consume(challengeId);
|
|
548
|
-
if (!challenge) return
|
|
549
|
-
ok: false,
|
|
550
|
-
verified: false,
|
|
551
|
-
code: "challenge_expired_or_invalid",
|
|
552
|
-
message: "Sync challenge expired or invalid"
|
|
553
|
-
};
|
|
453
|
+
if (!challenge) return failedVerification("challenge_expired_or_invalid", "Sync challenge expired or invalid");
|
|
554
454
|
const credential = request.webauthn_authentication;
|
|
555
455
|
const credentialId = credentialRawIdB64u(credential);
|
|
556
|
-
if (!credentialId.ok) return
|
|
557
|
-
ok: false,
|
|
558
|
-
verified: false,
|
|
559
|
-
code: credentialId.code,
|
|
560
|
-
message: credentialId.message
|
|
561
|
-
};
|
|
456
|
+
if (!credentialId.ok) return failedVerification(credentialId.code, credentialId.message);
|
|
562
457
|
const syncBinding = webAuthnSyncCredentialBinding(await input.credentialBindingStore.get(challenge.rpId, credentialId.credentialIdB64u), challenge);
|
|
563
458
|
if (!syncBinding.ok) return syncBinding;
|
|
564
459
|
const binding = syncBinding.binding;
|
|
565
460
|
const expectedOrigin = normalizeOptionalTrimmedString(request.expected_origin);
|
|
566
|
-
if (!expectedOrigin) return
|
|
567
|
-
ok: false,
|
|
568
|
-
verified: false,
|
|
569
|
-
code: "invalid_body",
|
|
570
|
-
message: "expected_origin is required for WebAuthn authentication verification"
|
|
571
|
-
};
|
|
461
|
+
if (!expectedOrigin) return failedVerification("invalid_body", "expected_origin is required for WebAuthn authentication verification");
|
|
572
462
|
const verificationFailure = webAuthnAuthenticationFailure(await verifyWebAuthnAuthenticationLiteWithStore({
|
|
573
463
|
userId: binding.userId,
|
|
574
464
|
rpId: requireWebAuthnRpId(binding.rpId, "sync credential binding rpId"),
|
|
@@ -580,30 +470,15 @@ async function verifyWebAuthnSyncAccountWithStores(input) {
|
|
|
580
470
|
}));
|
|
581
471
|
if (verificationFailure) return verificationFailure;
|
|
582
472
|
const auth = await input.authenticatorStore.get(binding.userId, credentialId.credentialIdB64u);
|
|
583
|
-
if (!auth) return
|
|
584
|
-
ok: false,
|
|
585
|
-
verified: false,
|
|
586
|
-
code: "unknown_credential",
|
|
587
|
-
message: "Credential is not registered for user"
|
|
588
|
-
};
|
|
473
|
+
if (!auth) return failedVerification("unknown_credential", "Credential is not registered for user");
|
|
589
474
|
const walletBinding = resolvedEd25519WalletBindingFromCredentialBinding({ binding });
|
|
590
475
|
const bindingPublicKey = binding.publicKey;
|
|
591
|
-
if (!walletBinding || !bindingPublicKey) return
|
|
592
|
-
ok: false,
|
|
593
|
-
verified: false,
|
|
594
|
-
code: "ed25519_not_provisioned",
|
|
595
|
-
message: "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed"
|
|
596
|
-
};
|
|
476
|
+
if (!walletBinding || !bindingPublicKey) return failedVerification("ed25519_not_provisioned", "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed");
|
|
597
477
|
const ed25519Signer = await input.walletStore.getEd25519SignerBySlot({
|
|
598
478
|
walletId: walletIdFromString(walletBinding.walletId),
|
|
599
479
|
signerSlot: walletBinding.signerSlot
|
|
600
480
|
});
|
|
601
|
-
if (!ed25519Signer) return
|
|
602
|
-
ok: false,
|
|
603
|
-
verified: false,
|
|
604
|
-
code: "ed25519_not_provisioned",
|
|
605
|
-
message: "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed"
|
|
606
|
-
};
|
|
481
|
+
if (!ed25519Signer) return failedVerification("ed25519_not_provisioned", "Wallet has no Ed25519 signer yet; NEAR provisioning has not completed");
|
|
607
482
|
const walletBindingAuthorityScope = passkeyThresholdEd25519AuthorityScope(requireWebAuthnRpId(walletBinding.rpId, "sync credential binding rpId"));
|
|
608
483
|
const thresholdEd25519 = binding.relayerKeyId ? {
|
|
609
484
|
relayerKeyId: binding.relayerKeyId,
|
|
@@ -633,43 +508,19 @@ async function verifyWebAuthnSyncAccountWithStores(input) {
|
|
|
633
508
|
...thresholdEd25519 ? { thresholdEd25519 } : {}
|
|
634
509
|
};
|
|
635
510
|
} catch (e) {
|
|
636
|
-
return
|
|
637
|
-
ok: false,
|
|
638
|
-
verified: false,
|
|
639
|
-
code: "internal",
|
|
640
|
-
message: errorMessage(e) || "Sync verification failed"
|
|
641
|
-
};
|
|
511
|
+
return failedVerification("internal", errorMessage(e) || "Sync verification failed");
|
|
642
512
|
}
|
|
643
513
|
}
|
|
644
514
|
async function verifyWebAuthnLoginWithStores(input) {
|
|
645
515
|
try {
|
|
646
516
|
const challengeId = String(input.request.challengeId ?? input.request.challenge_id ?? "").trim();
|
|
647
|
-
if (!challengeId) return
|
|
648
|
-
ok: false,
|
|
649
|
-
code: "invalid_body",
|
|
650
|
-
message: "Missing challengeId"
|
|
651
|
-
};
|
|
517
|
+
if (!challengeId) return failure("invalid_body", "Missing challengeId");
|
|
652
518
|
const record = await input.loginChallengeStore.consume(challengeId);
|
|
653
|
-
if (!record) return
|
|
654
|
-
ok: false,
|
|
655
|
-
verified: false,
|
|
656
|
-
code: "challenge_expired_or_invalid",
|
|
657
|
-
message: "Login challenge expired or invalid"
|
|
658
|
-
};
|
|
519
|
+
if (!record) return failedVerification("challenge_expired_or_invalid", "Login challenge expired or invalid");
|
|
659
520
|
const expectedOrigin = normalizeOptionalTrimmedString(input.request.expected_origin);
|
|
660
|
-
if (!expectedOrigin) return
|
|
661
|
-
ok: false,
|
|
662
|
-
verified: false,
|
|
663
|
-
code: "invalid_body",
|
|
664
|
-
message: "expected_origin is required for WebAuthn authentication verification"
|
|
665
|
-
};
|
|
521
|
+
if (!expectedOrigin) return failedVerification("invalid_body", "expected_origin is required for WebAuthn authentication verification");
|
|
666
522
|
const credential = parseWebAuthnAuthenticationCredential(input.request.webauthn_authentication);
|
|
667
|
-
if (!credential) return
|
|
668
|
-
ok: false,
|
|
669
|
-
verified: false,
|
|
670
|
-
code: "invalid_body",
|
|
671
|
-
message: "Missing webauthn_authentication"
|
|
672
|
-
};
|
|
523
|
+
if (!credential) return failedVerification("invalid_body", "Missing webauthn_authentication");
|
|
673
524
|
const verificationFailure = webAuthnAuthenticationFailure(await verifyWebAuthnAuthenticationLiteWithStore({
|
|
674
525
|
userId: record.userId,
|
|
675
526
|
rpId: requireWebAuthnRpId(record.rpId, "login challenge rpId"),
|
|
@@ -697,12 +548,7 @@ async function verifyWebAuthnLoginWithStores(input) {
|
|
|
697
548
|
ed25519: loginSigner.ed25519
|
|
698
549
|
};
|
|
699
550
|
} catch (e) {
|
|
700
|
-
return
|
|
701
|
-
ok: false,
|
|
702
|
-
verified: false,
|
|
703
|
-
code: "internal",
|
|
704
|
-
message: errorMessage(e) || "Login verification failed"
|
|
705
|
-
};
|
|
551
|
+
return failedVerification("internal", errorMessage(e) || "Login verification failed");
|
|
706
552
|
}
|
|
707
553
|
}
|
|
708
554
|
//#endregion
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
import { failedVerification } from "../../shared-ts/src/utils/failure.js";
|
|
1
2
|
//#region src/core/authService/webauthnVerificationOutcomes.ts
|
|
2
3
|
/** The failure a login or sync returns when its assertion did not verify; null when it did. */
|
|
3
4
|
function webAuthnAuthenticationFailure(verification) {
|
|
4
|
-
if (!verification.success || !verification.verified) return
|
|
5
|
-
ok: false,
|
|
6
|
-
verified: false,
|
|
7
|
-
code: verification.code || "not_verified",
|
|
8
|
-
message: verification.message || "Authentication verification failed"
|
|
9
|
-
};
|
|
5
|
+
if (!verification.success || !verification.verified) return failedVerification(verification.code || "not_verified", verification.message || "Authentication verification failed");
|
|
10
6
|
return null;
|
|
11
7
|
}
|
|
12
8
|
/**
|
|
@@ -16,12 +12,7 @@ function webAuthnAuthenticationFailure(verification) {
|
|
|
16
12
|
function webAuthnLoginEd25519(binding, walletBinding) {
|
|
17
13
|
const firstParticipantId = binding?.participantIds?.[0];
|
|
18
14
|
const secondParticipantId = binding?.participantIds?.[1];
|
|
19
|
-
if (!binding) return
|
|
20
|
-
ok: false,
|
|
21
|
-
verified: false,
|
|
22
|
-
code: "unknown_credential",
|
|
23
|
-
message: "Credential has no wallet binding"
|
|
24
|
-
};
|
|
15
|
+
if (!binding) return failedVerification("unknown_credential", "Credential has no wallet binding");
|
|
25
16
|
return {
|
|
26
17
|
ok: true,
|
|
27
18
|
ed25519: walletBinding && binding.publicKey && binding.relayerKeyId && firstParticipantId !== void 0 && secondParticipantId !== void 0 ? {
|
|
@@ -37,18 +28,8 @@ function webAuthnLoginEd25519(binding, walletBinding) {
|
|
|
37
28
|
}
|
|
38
29
|
/** The sync credential's binding, if it exists and belongs to the account the challenge expects. */
|
|
39
30
|
function webAuthnSyncCredentialBinding(binding, challenge) {
|
|
40
|
-
if (!binding) return
|
|
41
|
-
|
|
42
|
-
verified: false,
|
|
43
|
-
code: "unknown_credential",
|
|
44
|
-
message: "Credential is not registered on this relay"
|
|
45
|
-
};
|
|
46
|
-
if (challenge.expectedUserId && binding.userId !== challenge.expectedUserId) return {
|
|
47
|
-
ok: false,
|
|
48
|
-
verified: false,
|
|
49
|
-
code: "unknown_credential",
|
|
50
|
-
message: `Credential is not registered for account ${challenge.expectedUserId}`
|
|
51
|
-
};
|
|
31
|
+
if (!binding) return failedVerification("unknown_credential", "Credential is not registered on this relay");
|
|
32
|
+
if (challenge.expectedUserId && binding.userId !== challenge.expectedUserId) return failedVerification("unknown_credential", `Credential is not registered for account ${challenge.expectedUserId}`);
|
|
52
33
|
return {
|
|
53
34
|
ok: true,
|
|
54
35
|
binding
|