@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
|
@@ -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 { validateSecp256k1PublicKey33 } from "../../../../core/ThresholdService/evmCryptoWasm.js";
|
|
4
5
|
import { emailOtpDeviceEnrollmentId } from "../../../../shared-ts/src/utils/emailOtpDomain.js";
|
|
5
6
|
import { validateEmailOtpEnrollmentMaterial } from "./d1EmailOtpRecords.js";
|
|
@@ -20,27 +21,11 @@ var CloudflareD1EmailOtpRegistrationEnrollmentFinalizer = class {
|
|
|
20
21
|
this.googleEmailOtpSessions = input.googleEmailOtpSessions;
|
|
21
22
|
}
|
|
22
23
|
async prepareRegistrationFinalize(input) {
|
|
23
|
-
if (input.authority.kind !== "email_otp") return input.request.emailOtpEnrollment ? {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
message: "Email OTP enrollment material is only valid for Email OTP registration"
|
|
27
|
-
} : { ok: true };
|
|
28
|
-
if (!input.request.emailOtpEnrollment) return {
|
|
29
|
-
ok: false,
|
|
30
|
-
code: "invalid_body",
|
|
31
|
-
message: "Email OTP registration finalize requires emailOtpEnrollment"
|
|
32
|
-
};
|
|
33
|
-
if (input.authority.walletId !== input.walletId || input.authority.finalWalletId !== input.walletId || input.authority.orgId !== input.orgId) return {
|
|
34
|
-
ok: false,
|
|
35
|
-
code: "authority_binding_mismatch",
|
|
36
|
-
message: "Email OTP registration authority does not match finalize scope"
|
|
37
|
-
};
|
|
24
|
+
if (input.authority.kind !== "email_otp") return input.request.emailOtpEnrollment ? failure("invalid_body", "Email OTP enrollment material is only valid for Email OTP registration") : { ok: true };
|
|
25
|
+
if (!input.request.emailOtpEnrollment) return failure("invalid_body", "Email OTP registration finalize requires emailOtpEnrollment");
|
|
26
|
+
if (input.authority.walletId !== input.walletId || input.authority.finalWalletId !== input.walletId || input.authority.orgId !== input.orgId) return failure("authority_binding_mismatch", "Email OTP registration authority does not match finalize scope");
|
|
38
27
|
const material = parseEmailOtpEnrollmentMaterialBoundaryInput(input.request.emailOtpEnrollment);
|
|
39
|
-
if (!material) return
|
|
40
|
-
ok: false,
|
|
41
|
-
code: "invalid_body",
|
|
42
|
-
message: "Email OTP enrollment material must be an object with the expected fields"
|
|
43
|
-
};
|
|
28
|
+
if (!material) return failure("invalid_body", "Email OTP enrollment material must be an object with the expected fields");
|
|
44
29
|
return await this.buildPersistence({
|
|
45
30
|
walletId: input.walletId,
|
|
46
31
|
orgId: input.orgId,
|
|
@@ -131,11 +116,7 @@ var CloudflareD1EmailOtpRegistrationEnrollmentFinalizer = class {
|
|
|
131
116
|
* batch instead of silently replacing material that another operation owns.
|
|
132
117
|
*/
|
|
133
118
|
async prepareLinkedDeviceEnrollment(input) {
|
|
134
|
-
if (!await this.emailOtpEnrollments.signerWalletExists(input.walletId)) return
|
|
135
|
-
ok: false,
|
|
136
|
-
code: "wallet_registration_incomplete",
|
|
137
|
-
message: "Email OTP enrollment requires a canonical wallet"
|
|
138
|
-
};
|
|
119
|
+
if (!await this.emailOtpEnrollments.signerWalletExists(input.walletId)) return failure("wallet_registration_incomplete", "Email OTP enrollment requires a canonical wallet");
|
|
139
120
|
if (await this.emailOtpEnrollments.readEnrollment(input.walletId)) return {
|
|
140
121
|
ok: false,
|
|
141
122
|
code: "enrollment_conflict",
|
|
@@ -164,11 +145,7 @@ var CloudflareD1EmailOtpRegistrationEnrollmentFinalizer = class {
|
|
|
164
145
|
const walletId = normalizeOptionalTrimmedString(input.walletId) || "";
|
|
165
146
|
const authSubjectId = normalizeOptionalTrimmedString(input.authSubjectId) || "";
|
|
166
147
|
const verifiedEmail = normalizeOptionalTrimmedString(input.verifiedEmail)?.toLowerCase() || "";
|
|
167
|
-
if (!orgId || !walletId || !authSubjectId || !verifiedEmail) return
|
|
168
|
-
ok: false,
|
|
169
|
-
code: "invalid_body",
|
|
170
|
-
message: "Email OTP registration enrollment requires wallet, org, and email identity"
|
|
171
|
-
};
|
|
148
|
+
if (!orgId || !walletId || !authSubjectId || !verifiedEmail) return failure("invalid_body", "Email OTP registration enrollment requires wallet, org, and email identity");
|
|
172
149
|
const existing = await this.emailOtpEnrollments.readEnrollment(walletId);
|
|
173
150
|
const existingAuthState = await this.emailOtpEnrollments.readAuthState(walletId);
|
|
174
151
|
return {
|
|
@@ -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 { createSigningSessionSealShamir3PassCipherAdapter } from "../../../../threshold/session/signingSessionSeal/crypto/cipher.js";
|
|
4
5
|
//#region src/router/cloudflare/d1/emailOtp/d1EmailOtpServerSealRuntime.ts
|
|
5
6
|
const applyEmailOtpServerSealOperation = {
|
|
@@ -26,11 +27,7 @@ var CloudflareD1EmailOtpServerSealRuntime = class {
|
|
|
26
27
|
async runServerSealOperation(input, operation) {
|
|
27
28
|
try {
|
|
28
29
|
const wrappedCiphertext = normalizeOptionalTrimmedString(input.wrappedCiphertext);
|
|
29
|
-
if (!wrappedCiphertext) return
|
|
30
|
-
ok: false,
|
|
31
|
-
code: "invalid_body",
|
|
32
|
-
message: "Missing wrappedCiphertext"
|
|
33
|
-
};
|
|
30
|
+
if (!wrappedCiphertext) return failure("invalid_body", "Missing wrappedCiphertext");
|
|
34
31
|
const shamir = this.cipherResult;
|
|
35
32
|
if (!shamir.ok) return shamir;
|
|
36
33
|
const result = await shamir.cipher.run({
|
|
@@ -47,19 +44,11 @@ var CloudflareD1EmailOtpServerSealRuntime = class {
|
|
|
47
44
|
enrollmentSealKeyVersion: result.keyVersion || shamir.keyVersion
|
|
48
45
|
};
|
|
49
46
|
} catch (error) {
|
|
50
|
-
return
|
|
51
|
-
ok: false,
|
|
52
|
-
code: "internal",
|
|
53
|
-
message: serverSealErrorMessage(error) || operation.failureMessage
|
|
54
|
-
};
|
|
47
|
+
return failure("internal", serverSealErrorMessage(error) || operation.failureMessage);
|
|
55
48
|
}
|
|
56
49
|
}
|
|
57
50
|
createCipher() {
|
|
58
|
-
if (!this.config.configured) return
|
|
59
|
-
ok: false,
|
|
60
|
-
code: "not_configured",
|
|
61
|
-
message: this.config.message
|
|
62
|
-
};
|
|
51
|
+
if (!this.config.configured) return failure("not_configured", this.config.message);
|
|
63
52
|
try {
|
|
64
53
|
return {
|
|
65
54
|
ok: true,
|
|
@@ -67,11 +56,7 @@ var CloudflareD1EmailOtpServerSealRuntime = class {
|
|
|
67
56
|
cipher: createSigningSessionSealShamir3PassCipherAdapter({ config: this.config.rootConfig })
|
|
68
57
|
};
|
|
69
58
|
} catch (error) {
|
|
70
|
-
return
|
|
71
|
-
ok: false,
|
|
72
|
-
code: "not_configured",
|
|
73
|
-
message: serverSealErrorMessage(error) || "Email OTP Shamir configuration is invalid"
|
|
74
|
-
};
|
|
59
|
+
return failure("not_configured", serverSealErrorMessage(error) || "Email OTP Shamir configuration is invalid");
|
|
75
60
|
}
|
|
76
61
|
}
|
|
77
62
|
};
|
|
@@ -2,6 +2,7 @@ import { parseGoogleProviderSubject, parseOrgId, parseVerifiedGoogleEmail } from
|
|
|
2
2
|
import { normalizeOptionalTrimmedString } from "../../../../shared-ts/src/utils/normalize.js";
|
|
3
3
|
import "../../../../shared-ts/src/utils/validation.js";
|
|
4
4
|
import { secureRandomBase64Url } from "../../../../shared-ts/src/utils/secureRandomId.js";
|
|
5
|
+
import { failure } from "../../../../shared-ts/src/utils/failure.js";
|
|
5
6
|
import { createServerAllocatedWalletId } from "../../../../shared-ts/src/utils/registrationIds.js";
|
|
6
7
|
import { hashEmailOtpOperationBinding } from "../../../domains/emailOtp/emailOtpSessionRouteHelpers.js";
|
|
7
8
|
import { parseD1BoundaryWalletId, parseD1BoundaryWalletIdResult } from "../auth/d1RouterApiAuthBoundary.js";
|
|
@@ -61,17 +62,9 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
|
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
64
|
async cleanupDevRegistrationState(input) {
|
|
64
|
-
if (this.production) return
|
|
65
|
-
ok: false,
|
|
66
|
-
code: "not_found",
|
|
67
|
-
message: "Google Email OTP dev cleanup is not available"
|
|
68
|
-
};
|
|
65
|
+
if (this.production) return failure("not_found", "Google Email OTP dev cleanup is not available");
|
|
69
66
|
const providerSubject = normalizeOptionalTrimmedString(input.providerSubject);
|
|
70
|
-
if (!providerSubject || !providerSubject.startsWith("google:")) return
|
|
71
|
-
ok: false,
|
|
72
|
-
code: "invalid_body",
|
|
73
|
-
message: "Missing Google provider subject"
|
|
74
|
-
};
|
|
67
|
+
if (!providerSubject || !providerSubject.startsWith("google:")) return failure("invalid_body", "Missing Google provider subject");
|
|
75
68
|
const requestedWalletId = parseD1BoundaryWalletId(input.walletId);
|
|
76
69
|
const requestedOrgId = normalizeOptionalTrimmedString(input.orgId);
|
|
77
70
|
const nowMs = cleanupNowMs(input.nowMs);
|
|
@@ -122,23 +115,11 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
|
|
|
122
115
|
async consumeRegistrationAttemptRateLimit(input) {
|
|
123
116
|
if (normalizeOptionalTrimmedString(input.accountMode)?.toLowerCase() !== "register") return { ok: true };
|
|
124
117
|
const providerSubject = parseGoogleProviderSubject(input.providerSubject);
|
|
125
|
-
if (!providerSubject.ok) return
|
|
126
|
-
ok: false,
|
|
127
|
-
code: "invalid_body",
|
|
128
|
-
message: providerSubject.error.message
|
|
129
|
-
};
|
|
118
|
+
if (!providerSubject.ok) return failure("invalid_body", providerSubject.error.message);
|
|
130
119
|
const email = parseVerifiedGoogleEmail(input.email);
|
|
131
|
-
if (!email.ok) return
|
|
132
|
-
ok: false,
|
|
133
|
-
code: "invalid_body",
|
|
134
|
-
message: email.error.message
|
|
135
|
-
};
|
|
120
|
+
if (!email.ok) return failure("invalid_body", email.error.message);
|
|
136
121
|
const orgId = parseOrgId(input.runtimePolicyScope?.orgId);
|
|
137
|
-
if (!orgId.ok) return
|
|
138
|
-
ok: false,
|
|
139
|
-
code: "invalid_body",
|
|
140
|
-
message: orgId.error.message
|
|
141
|
-
};
|
|
122
|
+
if (!orgId.ok) return failure("invalid_body", orgId.error.message);
|
|
142
123
|
const restartOffer = isTrueFlag(input.restartRegistrationOffer);
|
|
143
124
|
return await this.emailOtpRateLimits.consume({
|
|
144
125
|
scope: "googleRegistrationAttempt",
|
|
@@ -153,39 +134,19 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
|
|
|
153
134
|
const registrationAttemptId = normalizeOptionalTrimmedString(input.registrationAttemptId);
|
|
154
135
|
if (!registrationAttemptId) return { ok: true };
|
|
155
136
|
const walletId = parseD1BoundaryWalletIdResult(input.walletId);
|
|
156
|
-
if (!walletId.ok) return
|
|
157
|
-
ok: false,
|
|
158
|
-
code: "invalid_body",
|
|
159
|
-
message: walletId.code === "missing" ? "Missing walletId" : "Invalid walletId"
|
|
160
|
-
};
|
|
137
|
+
if (!walletId.ok) return failure("invalid_body", walletId.code === "missing" ? "Missing walletId" : "Invalid walletId");
|
|
161
138
|
const attempt = await this.registrationAttempts.read(registrationAttemptId);
|
|
162
|
-
if (!attempt) return
|
|
163
|
-
ok: false,
|
|
164
|
-
code: "registration_incomplete",
|
|
165
|
-
message: "Google Email OTP registration attempt expired or was not found"
|
|
166
|
-
};
|
|
139
|
+
if (!attempt) return failure("registration_incomplete", "Google Email OTP registration attempt expired or was not found");
|
|
167
140
|
if (attempt.expiresAtMs <= Date.now()) {
|
|
168
141
|
await this.registrationAttempts.put(expiredGoogleEmailOtpRegistrationAttemptRecord({
|
|
169
142
|
record: attempt,
|
|
170
143
|
updatedAtMs: Date.now()
|
|
171
144
|
}));
|
|
172
|
-
return
|
|
173
|
-
ok: false,
|
|
174
|
-
code: "registration_incomplete",
|
|
175
|
-
message: "Google Email OTP registration attempt expired"
|
|
176
|
-
};
|
|
145
|
+
return failure("registration_incomplete", "Google Email OTP registration attempt expired");
|
|
177
146
|
}
|
|
178
|
-
if (walletId.value !== attempt.walletId) return
|
|
179
|
-
ok: false,
|
|
180
|
-
code: "wallet_identity_mismatch",
|
|
181
|
-
message: "registrationAttemptId does not match walletId"
|
|
182
|
-
};
|
|
147
|
+
if (walletId.value !== attempt.walletId) return failure("wallet_identity_mismatch", "registrationAttemptId does not match walletId");
|
|
183
148
|
if (attempt.state === "active") return { ok: true };
|
|
184
|
-
if (attempt.state !== "started" && attempt.state !== "key_finalized") return
|
|
185
|
-
ok: false,
|
|
186
|
-
code: "registration_incomplete",
|
|
187
|
-
message: "Google Email OTP registration attempt is no longer active"
|
|
188
|
-
};
|
|
149
|
+
if (attempt.state !== "started" && attempt.state !== "key_finalized") return failure("registration_incomplete", "Google Email OTP registration attempt is no longer active");
|
|
189
150
|
const linked = await this.linkIdentity({
|
|
190
151
|
userId: attempt.walletId,
|
|
191
152
|
subject: `wallet:${attempt.providerSubject}`,
|
|
@@ -197,11 +158,7 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
|
|
|
197
158
|
failureCode: linked.code,
|
|
198
159
|
updatedAtMs: Date.now()
|
|
199
160
|
}));
|
|
200
|
-
return
|
|
201
|
-
ok: false,
|
|
202
|
-
code: linked.code,
|
|
203
|
-
message: linked.message
|
|
204
|
-
};
|
|
161
|
+
return failure(linked.code, linked.message);
|
|
205
162
|
}
|
|
206
163
|
await this.registrationAttempts.put(activeGoogleEmailOtpRegistrationAttemptRecord({
|
|
207
164
|
record: attempt,
|
|
@@ -214,48 +171,20 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
|
|
|
214
171
|
const walletId = parseD1BoundaryWalletIdResult(input.walletId);
|
|
215
172
|
const providerSubject = parseGoogleProviderSubject(input.providerSubject);
|
|
216
173
|
const ownerProofBindingDigest = normalizeOptionalTrimmedString(input.ownerProofBindingDigest);
|
|
217
|
-
if (!registrationAttemptId || !walletId.ok || !providerSubject.ok || !ownerProofBindingDigest) return
|
|
218
|
-
ok: false,
|
|
219
|
-
code: "invalid_body",
|
|
220
|
-
message: "Google Email OTP registration candidate validation requires signed session scope"
|
|
221
|
-
};
|
|
174
|
+
if (!registrationAttemptId || !walletId.ok || !providerSubject.ok || !ownerProofBindingDigest) return failure("invalid_body", "Google Email OTP registration candidate validation requires signed session scope");
|
|
222
175
|
const attempt = await this.registrationAttempts.read(registrationAttemptId);
|
|
223
|
-
if (!attempt) return
|
|
224
|
-
ok: false,
|
|
225
|
-
code: "registration_attempt_missing",
|
|
226
|
-
message: "Google Email OTP registration attempt expired or was not found"
|
|
227
|
-
};
|
|
176
|
+
if (!attempt) return failure("registration_attempt_missing", "Google Email OTP registration attempt expired or was not found");
|
|
228
177
|
if (attempt.expiresAtMs <= Date.now()) {
|
|
229
178
|
await this.registrationAttempts.put(expiredGoogleEmailOtpRegistrationAttemptRecord({
|
|
230
179
|
record: attempt,
|
|
231
180
|
updatedAtMs: Date.now()
|
|
232
181
|
}));
|
|
233
|
-
return
|
|
234
|
-
ok: false,
|
|
235
|
-
code: "registration_attempt_expired",
|
|
236
|
-
message: "Google Email OTP registration attempt expired"
|
|
237
|
-
};
|
|
182
|
+
return failure("registration_attempt_expired", "Google Email OTP registration attempt expired");
|
|
238
183
|
}
|
|
239
|
-
if (attempt.providerSubject !== providerSubject.value) return
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
};
|
|
244
|
-
if (attempt.ownerProofBindingDigest !== ownerProofBindingDigest) return {
|
|
245
|
-
ok: false,
|
|
246
|
-
code: "owner_proof_binding_mismatch",
|
|
247
|
-
message: "Google Email OTP registration attempt does not match the owner proof binding"
|
|
248
|
-
};
|
|
249
|
-
if (attempt.state !== "started" && attempt.state !== "key_finalized") return {
|
|
250
|
-
ok: false,
|
|
251
|
-
code: "registration_incomplete",
|
|
252
|
-
message: "Google Email OTP registration attempt is no longer active"
|
|
253
|
-
};
|
|
254
|
-
if (!attempt.offerCandidates.find((offerCandidate) => offerCandidate.walletId === walletId.value)) return {
|
|
255
|
-
ok: false,
|
|
256
|
-
code: "wallet_identity_mismatch",
|
|
257
|
-
message: "walletId is not an active Google Email OTP registration candidate"
|
|
258
|
-
};
|
|
184
|
+
if (attempt.providerSubject !== providerSubject.value) return failure("challenge_subject_mismatch", "Email OTP registration attempt does not match the provider subject");
|
|
185
|
+
if (attempt.ownerProofBindingDigest !== ownerProofBindingDigest) return failure("owner_proof_binding_mismatch", "Google Email OTP registration attempt does not match the owner proof binding");
|
|
186
|
+
if (attempt.state !== "started" && attempt.state !== "key_finalized") return failure("registration_incomplete", "Google Email OTP registration attempt is no longer active");
|
|
187
|
+
if (!attempt.offerCandidates.find((offerCandidate) => offerCandidate.walletId === walletId.value)) return failure("wallet_identity_mismatch", "walletId is not an active Google Email OTP registration candidate");
|
|
259
188
|
return { ok: true };
|
|
260
189
|
}
|
|
261
190
|
async resolveLoginSession(input) {
|
|
@@ -460,21 +389,9 @@ var CloudflareD1GoogleEmailOtpSessionResolver = class {
|
|
|
460
389
|
}
|
|
461
390
|
async readActiveEnrollment(input) {
|
|
462
391
|
const enrollment = await this.emailOtpEnrollments.readEnrollment(input.walletId);
|
|
463
|
-
if (!enrollment) return
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
message: "Email OTP enrollment not found"
|
|
467
|
-
};
|
|
468
|
-
if (enrollment.orgId !== input.orgId) return {
|
|
469
|
-
ok: false,
|
|
470
|
-
code: "tenant_scope_mismatch",
|
|
471
|
-
message: "Email OTP enrollment does not match the requested orgId"
|
|
472
|
-
};
|
|
473
|
-
if (enrollment.providerUserId !== input.providerUserId) return {
|
|
474
|
-
ok: false,
|
|
475
|
-
code: "provider_identity_mismatch",
|
|
476
|
-
message: "Email OTP enrollment does not belong to the requested provider identity"
|
|
477
|
-
};
|
|
392
|
+
if (!enrollment) return failure("not_found", "Email OTP enrollment not found");
|
|
393
|
+
if (enrollment.orgId !== input.orgId) return failure("tenant_scope_mismatch", "Email OTP enrollment does not match the requested orgId");
|
|
394
|
+
if (enrollment.providerUserId !== input.providerUserId) return failure("provider_identity_mismatch", "Email OTP enrollment does not belong to the requested provider identity");
|
|
478
395
|
return {
|
|
479
396
|
ok: true,
|
|
480
397
|
enrollment
|
|
@@ -497,11 +414,7 @@ function codedError(code, message) {
|
|
|
497
414
|
return error;
|
|
498
415
|
}
|
|
499
416
|
function devCleanupIdentityDeleteFailure(input) {
|
|
500
|
-
return
|
|
501
|
-
ok: false,
|
|
502
|
-
code: input.code,
|
|
503
|
-
message: input.message
|
|
504
|
-
};
|
|
417
|
+
return failure(input.code, input.message);
|
|
505
418
|
}
|
|
506
419
|
//#endregion
|
|
507
420
|
export { CloudflareD1GoogleEmailOtpSessionResolver };
|
|
@@ -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 { parseD1BoundaryWalletId } from "../auth/d1RouterApiAuthBoundary.js";
|
|
4
5
|
import { requireD1RouterApiAuthScopeString } from "../auth/d1RouterApiAuthConfig.js";
|
|
5
6
|
import { deriveHostedNearAccountId } from "../../../../core/hostedAccountIds.js";
|
|
@@ -36,74 +37,42 @@ var CloudflareD1IdentityService = class {
|
|
|
36
37
|
async listIdentities(input) {
|
|
37
38
|
try {
|
|
38
39
|
const userId = normalizeOptionalTrimmedString(input.userId);
|
|
39
|
-
if (!userId) return
|
|
40
|
-
ok: false,
|
|
41
|
-
code: "invalid_args",
|
|
42
|
-
message: "Missing userId"
|
|
43
|
-
};
|
|
40
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
44
41
|
return {
|
|
45
42
|
ok: true,
|
|
46
43
|
subjects: await this.identityStore.listSubjectsByUserId(userId)
|
|
47
44
|
};
|
|
48
45
|
} catch (error) {
|
|
49
|
-
return
|
|
50
|
-
ok: false,
|
|
51
|
-
code: "internal",
|
|
52
|
-
message: errorMessage(error) || "Failed to list identities"
|
|
53
|
-
};
|
|
46
|
+
return failure("internal", errorMessage(error) || "Failed to list identities");
|
|
54
47
|
}
|
|
55
48
|
}
|
|
56
49
|
async linkIdentity(input) {
|
|
57
50
|
try {
|
|
58
51
|
const userId = normalizeOptionalTrimmedString(input.userId);
|
|
59
52
|
const subject = normalizeOptionalTrimmedString(input.subject);
|
|
60
|
-
if (!userId) return
|
|
61
|
-
|
|
62
|
-
code: "invalid_args",
|
|
63
|
-
message: "Missing userId"
|
|
64
|
-
};
|
|
65
|
-
if (!subject) return {
|
|
66
|
-
ok: false,
|
|
67
|
-
code: "invalid_args",
|
|
68
|
-
message: "Missing subject"
|
|
69
|
-
};
|
|
53
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
54
|
+
if (!subject) return failure("invalid_args", "Missing subject");
|
|
70
55
|
return await this.identityStore.linkSubjectToUserId({
|
|
71
56
|
userId,
|
|
72
57
|
subject,
|
|
73
58
|
allowMoveIfSoleIdentity: Boolean(input.allowMoveIfSoleIdentity)
|
|
74
59
|
});
|
|
75
60
|
} catch (error) {
|
|
76
|
-
return
|
|
77
|
-
ok: false,
|
|
78
|
-
code: "internal",
|
|
79
|
-
message: errorMessage(error) || "Failed to link identity"
|
|
80
|
-
};
|
|
61
|
+
return failure("internal", errorMessage(error) || "Failed to link identity");
|
|
81
62
|
}
|
|
82
63
|
}
|
|
83
64
|
async unlinkIdentity(input) {
|
|
84
65
|
try {
|
|
85
66
|
const userId = normalizeOptionalTrimmedString(input.userId);
|
|
86
67
|
const subject = normalizeOptionalTrimmedString(input.subject);
|
|
87
|
-
if (!userId) return
|
|
88
|
-
|
|
89
|
-
code: "invalid_args",
|
|
90
|
-
message: "Missing userId"
|
|
91
|
-
};
|
|
92
|
-
if (!subject) return {
|
|
93
|
-
ok: false,
|
|
94
|
-
code: "invalid_args",
|
|
95
|
-
message: "Missing subject"
|
|
96
|
-
};
|
|
68
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
69
|
+
if (!subject) return failure("invalid_args", "Missing subject");
|
|
97
70
|
return await this.identityStore.unlinkSubjectFromUserId({
|
|
98
71
|
userId,
|
|
99
72
|
subject
|
|
100
73
|
});
|
|
101
74
|
} catch (error) {
|
|
102
|
-
return
|
|
103
|
-
ok: false,
|
|
104
|
-
code: "internal",
|
|
105
|
-
message: errorMessage(error) || "Failed to unlink identity"
|
|
106
|
-
};
|
|
75
|
+
return failure("internal", errorMessage(error) || "Failed to unlink identity");
|
|
107
76
|
}
|
|
108
77
|
}
|
|
109
78
|
async resolveOidcWalletId(input) {
|
|
@@ -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 { parseNearPublicKey } from "../webauthn/d1WebAuthnRecords.js";
|
|
4
5
|
import { NEAR_PUBLIC_KEYS_BY_USER_SQL } from "../../../../core/NearPublicKeyStore.js";
|
|
5
6
|
//#region src/router/cloudflare/d1/near/d1NearPublicKeyStore.ts
|
|
@@ -10,21 +11,13 @@ var CloudflareD1NearPublicKeyStore = class {
|
|
|
10
11
|
async listForRelayUser(input) {
|
|
11
12
|
try {
|
|
12
13
|
const userId = normalizeOptionalTrimmedString(input.userId);
|
|
13
|
-
if (!userId) return
|
|
14
|
-
ok: false,
|
|
15
|
-
code: "invalid_args",
|
|
16
|
-
message: "Missing userId"
|
|
17
|
-
};
|
|
14
|
+
if (!userId) return failure("invalid_args", "Missing userId");
|
|
18
15
|
return {
|
|
19
16
|
ok: true,
|
|
20
17
|
keys: (await this.listForUser(userId)).map(nearPublicKeyForRelayResponse)
|
|
21
18
|
};
|
|
22
19
|
} catch (error) {
|
|
23
|
-
return
|
|
24
|
-
ok: false,
|
|
25
|
-
code: "internal",
|
|
26
|
-
message: nearPublicKeyErrorMessage(error) || "Failed to list keys"
|
|
27
|
-
};
|
|
20
|
+
return failure("internal", nearPublicKeyErrorMessage(error) || "Failed to list keys");
|
|
28
21
|
}
|
|
29
22
|
}
|
|
30
23
|
async listForUser(userId) {
|
|
@@ -2,7 +2,9 @@ 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 "../../../../shared-ts/src/utils/validation.js";
|
|
5
|
-
import {
|
|
5
|
+
import { failedVerification } from "../../../../shared-ts/src/utils/failure.js";
|
|
6
|
+
import { toArrayBufferCopy } from "../../../../core/authService/portableCrypto.js";
|
|
7
|
+
import { toRecordValue } from "../auth/d1RouterApiAuthBoundary.js";
|
|
6
8
|
//#region src/router/cloudflare/d1/oidc/d1OidcBoundary.ts
|
|
7
9
|
function parseJwtAud(input) {
|
|
8
10
|
const values = [];
|
|
@@ -75,43 +77,18 @@ var CloudflareD1OidcJwksCache = class {
|
|
|
75
77
|
};
|
|
76
78
|
function parseRs256JwtForVerification(input) {
|
|
77
79
|
const parts = input.token.split(".");
|
|
78
|
-
if (parts.length !== 3) return {
|
|
79
|
-
ok: false,
|
|
80
|
-
verified: false,
|
|
81
|
-
code: "invalid_body",
|
|
82
|
-
message: `${input.tokenLabel} must be a JWT (3 segments)`
|
|
83
|
-
};
|
|
80
|
+
if (parts.length !== 3) return failedVerification("invalid_body", `${input.tokenLabel} must be a JWT (3 segments)`);
|
|
84
81
|
const headerB64u = parts[0] || "";
|
|
85
82
|
const payloadB64u = parts[1] || "";
|
|
86
83
|
const signatureB64u = parts[2] || "";
|
|
87
84
|
const header = parseJwtSegmentJson(headerB64u);
|
|
88
|
-
if (!header) return {
|
|
89
|
-
ok: false,
|
|
90
|
-
verified: false,
|
|
91
|
-
code: "invalid_body",
|
|
92
|
-
message: `Invalid ${input.tokenLabel} header encoding`
|
|
93
|
-
};
|
|
85
|
+
if (!header) return failedVerification("invalid_body", `Invalid ${input.tokenLabel} header encoding`);
|
|
94
86
|
const payload = parseJwtSegmentJson(payloadB64u);
|
|
95
|
-
if (!payload) return {
|
|
96
|
-
ok: false,
|
|
97
|
-
verified: false,
|
|
98
|
-
code: "invalid_body",
|
|
99
|
-
message: `Invalid ${input.tokenLabel} payload encoding`
|
|
100
|
-
};
|
|
87
|
+
if (!payload) return failedVerification("invalid_body", `Invalid ${input.tokenLabel} payload encoding`);
|
|
101
88
|
const kid = normalizeOptionalTrimmedString(header.kid);
|
|
102
89
|
const alg = normalizeOptionalTrimmedString(header.alg);
|
|
103
|
-
if (!kid) return {
|
|
104
|
-
|
|
105
|
-
verified: false,
|
|
106
|
-
code: "invalid_body",
|
|
107
|
-
message: `${input.tokenLabel} header.kid is required`
|
|
108
|
-
};
|
|
109
|
-
if (alg !== "RS256") return {
|
|
110
|
-
ok: false,
|
|
111
|
-
verified: false,
|
|
112
|
-
code: "invalid_body",
|
|
113
|
-
message: `${input.tokenLabel} header.alg must be RS256`
|
|
114
|
-
};
|
|
90
|
+
if (!kid) return failedVerification("invalid_body", `${input.tokenLabel} header.kid is required`);
|
|
91
|
+
if (alg !== "RS256") return failedVerification("invalid_body", `${input.tokenLabel} header.alg must be RS256`);
|
|
115
92
|
return {
|
|
116
93
|
ok: true,
|
|
117
94
|
jwt: {
|
|
@@ -128,24 +105,14 @@ async function verifyRs256JwtSignature(input) {
|
|
|
128
105
|
try {
|
|
129
106
|
signatureBytes = base64UrlDecode(input.jwt.signatureB64u);
|
|
130
107
|
} catch {
|
|
131
|
-
return {
|
|
132
|
-
ok: false,
|
|
133
|
-
verified: false,
|
|
134
|
-
code: "invalid_body",
|
|
135
|
-
message: `Invalid ${input.tokenLabel} signature encoding`
|
|
136
|
-
};
|
|
108
|
+
return failedVerification("invalid_body", `Invalid ${input.tokenLabel} signature encoding`);
|
|
137
109
|
}
|
|
138
110
|
const dataBytes = new TextEncoder().encode(`${input.jwt.headerB64u}.${input.jwt.payloadB64u}`);
|
|
139
111
|
const key = await input.subtle.importKey("jwk", input.jwk, {
|
|
140
112
|
name: "RSASSA-PKCS1-v1_5",
|
|
141
113
|
hash: "SHA-256"
|
|
142
114
|
}, false, ["verify"]);
|
|
143
|
-
if (!await input.subtle.verify({ name: "RSASSA-PKCS1-v1_5" }, key, toArrayBufferCopy(signatureBytes), toArrayBufferCopy(dataBytes))) return
|
|
144
|
-
ok: false,
|
|
145
|
-
verified: false,
|
|
146
|
-
code: "invalid_signature",
|
|
147
|
-
message: input.invalidSignatureMessage
|
|
148
|
-
};
|
|
115
|
+
if (!await input.subtle.verify({ name: "RSASSA-PKCS1-v1_5" }, key, toArrayBufferCopy(signatureBytes), toArrayBufferCopy(dataBytes))) return failedVerification("invalid_signature", input.invalidSignatureMessage);
|
|
149
116
|
return { ok: true };
|
|
150
117
|
}
|
|
151
118
|
function parseBooleanJwtClaim(input) {
|
|
@@ -157,61 +124,21 @@ function parseBooleanJwtClaim(input) {
|
|
|
157
124
|
function validateGoogleIdTokenClaims(input) {
|
|
158
125
|
const payload = input.payload;
|
|
159
126
|
const iss = normalizeOptionalTrimmedString(payload.iss);
|
|
160
|
-
if (iss !== "https://accounts.google.com" && iss !== "accounts.google.com") return
|
|
161
|
-
ok: false,
|
|
162
|
-
verified: false,
|
|
163
|
-
code: "invalid_issuer",
|
|
164
|
-
message: "Invalid Google id_token issuer"
|
|
165
|
-
};
|
|
127
|
+
if (iss !== "https://accounts.google.com" && iss !== "accounts.google.com") return failedVerification("invalid_issuer", "Invalid Google id_token issuer");
|
|
166
128
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
167
129
|
const exp = Number(payload.exp);
|
|
168
|
-
if (!Number.isFinite(exp) || exp <= 0) return
|
|
169
|
-
|
|
170
|
-
verified: false,
|
|
171
|
-
code: "invalid_claims",
|
|
172
|
-
message: "Invalid Google id_token exp"
|
|
173
|
-
};
|
|
174
|
-
if (nowSec >= exp) return {
|
|
175
|
-
ok: false,
|
|
176
|
-
verified: false,
|
|
177
|
-
code: "expired",
|
|
178
|
-
message: "Google id_token is expired"
|
|
179
|
-
};
|
|
130
|
+
if (!Number.isFinite(exp) || exp <= 0) return failedVerification("invalid_claims", "Invalid Google id_token exp");
|
|
131
|
+
if (nowSec >= exp) return failedVerification("expired", "Google id_token is expired");
|
|
180
132
|
if (payload.nbf !== void 0) {
|
|
181
133
|
const nbf = Number(payload.nbf);
|
|
182
|
-
if (!Number.isFinite(nbf)) return
|
|
183
|
-
|
|
184
|
-
verified: false,
|
|
185
|
-
code: "invalid_claims",
|
|
186
|
-
message: "Invalid Google id_token nbf"
|
|
187
|
-
};
|
|
188
|
-
if (nowSec < nbf) return {
|
|
189
|
-
ok: false,
|
|
190
|
-
verified: false,
|
|
191
|
-
code: "not_yet_valid",
|
|
192
|
-
message: "Google id_token is not yet valid"
|
|
193
|
-
};
|
|
134
|
+
if (!Number.isFinite(nbf)) return failedVerification("invalid_claims", "Invalid Google id_token nbf");
|
|
135
|
+
if (nowSec < nbf) return failedVerification("not_yet_valid", "Google id_token is not yet valid");
|
|
194
136
|
}
|
|
195
137
|
const aud = parseJwtAud(payload.aud);
|
|
196
|
-
if (aud.length === 0) return
|
|
197
|
-
|
|
198
|
-
verified: false,
|
|
199
|
-
code: "invalid_claims",
|
|
200
|
-
message: "Missing Google id_token aud"
|
|
201
|
-
};
|
|
202
|
-
if (!aud.includes(input.clientId)) return {
|
|
203
|
-
ok: false,
|
|
204
|
-
verified: false,
|
|
205
|
-
code: "invalid_audience",
|
|
206
|
-
message: "Google id_token audience mismatch"
|
|
207
|
-
};
|
|
138
|
+
if (aud.length === 0) return failedVerification("invalid_claims", "Missing Google id_token aud");
|
|
139
|
+
if (!aud.includes(input.clientId)) return failedVerification("invalid_audience", "Google id_token audience mismatch");
|
|
208
140
|
const sub = normalizeOptionalTrimmedString(payload.sub);
|
|
209
|
-
if (!sub) return
|
|
210
|
-
ok: false,
|
|
211
|
-
verified: false,
|
|
212
|
-
code: "invalid_claims",
|
|
213
|
-
message: "Missing Google id_token sub"
|
|
214
|
-
};
|
|
141
|
+
if (!sub) return failedVerification("invalid_claims", "Missing Google id_token sub");
|
|
215
142
|
const email = normalizeOptionalTrimmedString(payload.email);
|
|
216
143
|
const name = normalizeOptionalTrimmedString(payload.name);
|
|
217
144
|
const givenName = normalizeOptionalTrimmedString(payload.given_name);
|
|
@@ -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 { failedVerification } from "../../../../shared-ts/src/utils/failure.js";
|
|
3
4
|
import { CloudflareD1OidcJwksCache, parseRs256JwtForVerification, validateGoogleIdTokenClaims, verifyRs256JwtSignature } from "./d1OidcBoundary.js";
|
|
4
5
|
import { githubOAuthPublicConfig, verifyGithubOAuthCodeWithIdentityStore } from "../../../../core/authService/githubOAuth.js";
|
|
5
6
|
//#region src/router/cloudflare/d1/oidc/d1OidcVerificationService.ts
|
|
@@ -45,26 +46,11 @@ var CloudflareD1OidcVerificationService = class {
|
|
|
45
46
|
async verifyGoogleIdToken(input, linkIdentity) {
|
|
46
47
|
try {
|
|
47
48
|
const clientId = normalizeOptionalTrimmedString(this.googleOidcClientId);
|
|
48
|
-
if (!clientId) return
|
|
49
|
-
ok: false,
|
|
50
|
-
verified: false,
|
|
51
|
-
code: "not_configured",
|
|
52
|
-
message: "Google OIDC is not configured on this Worker"
|
|
53
|
-
};
|
|
49
|
+
if (!clientId) return failedVerification("not_configured", "Google OIDC is not configured on this Worker");
|
|
54
50
|
const idToken = normalizeOptionalTrimmedString(input.idToken ?? input.id_token);
|
|
55
|
-
if (!idToken) return
|
|
56
|
-
ok: false,
|
|
57
|
-
verified: false,
|
|
58
|
-
code: "invalid_body",
|
|
59
|
-
message: "id_token is required"
|
|
60
|
-
};
|
|
51
|
+
if (!idToken) return failedVerification("invalid_body", "id_token is required");
|
|
61
52
|
const subtle = globalThis.crypto?.subtle;
|
|
62
|
-
if (!subtle) return
|
|
63
|
-
ok: false,
|
|
64
|
-
verified: false,
|
|
65
|
-
code: "unsupported",
|
|
66
|
-
message: "WebCrypto (crypto.subtle) is unavailable in this runtime"
|
|
67
|
-
};
|
|
53
|
+
if (!subtle) return failedVerification("unsupported", "WebCrypto (crypto.subtle) is unavailable in this runtime");
|
|
68
54
|
const parsed = parseRs256JwtForVerification({
|
|
69
55
|
token: idToken,
|
|
70
56
|
tokenLabel: "id_token"
|
|
@@ -72,12 +58,7 @@ var CloudflareD1OidcVerificationService = class {
|
|
|
72
58
|
if (!parsed.ok) return parsed;
|
|
73
59
|
const jwt = parsed.jwt;
|
|
74
60
|
const jwk = (await this.oidcJwksCache.getGoogleJwks()).keysByKid.get(jwt.kid);
|
|
75
|
-
if (!jwk) return
|
|
76
|
-
ok: false,
|
|
77
|
-
verified: false,
|
|
78
|
-
code: "unknown_kid",
|
|
79
|
-
message: "Unknown Google key id (kid)"
|
|
80
|
-
};
|
|
61
|
+
if (!jwk) return failedVerification("unknown_kid", "Unknown Google key id (kid)");
|
|
81
62
|
const signature = await verifyRs256JwtSignature({
|
|
82
63
|
subtle,
|
|
83
64
|
jwt,
|
|
@@ -106,12 +87,7 @@ var CloudflareD1OidcVerificationService = class {
|
|
|
106
87
|
...claims.hostedDomain ? { hostedDomain: claims.hostedDomain } : {}
|
|
107
88
|
};
|
|
108
89
|
} catch (error) {
|
|
109
|
-
return
|
|
110
|
-
ok: false,
|
|
111
|
-
verified: false,
|
|
112
|
-
code: "internal",
|
|
113
|
-
message: errorMessage(error) || "Google OIDC verification failed"
|
|
114
|
-
};
|
|
90
|
+
return failedVerification("internal", errorMessage(error) || "Google OIDC verification failed");
|
|
115
91
|
}
|
|
116
92
|
}
|
|
117
93
|
async linkGoogleIdentity(providerSubject) {
|