@reclaimprotocol/js-sdk 5.3.0 → 5.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +144 -1
- package/dist/index.js +502 -135
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -84,7 +84,7 @@ var require_package = __commonJS({
|
|
|
84
84
|
"package.json"(exports2, module2) {
|
|
85
85
|
module2.exports = {
|
|
86
86
|
name: "@reclaimprotocol/js-sdk",
|
|
87
|
-
version: "5.
|
|
87
|
+
version: "5.4.1",
|
|
88
88
|
description: "Designed to request proofs from the Reclaim protocol and manage the flow of claims and witness interactions.",
|
|
89
89
|
main: "dist/index.js",
|
|
90
90
|
types: "dist/index.d.ts",
|
|
@@ -203,6 +203,8 @@ __export(index_exports, {
|
|
|
203
203
|
fetchProviderConfigs: () => fetchProviderConfigs,
|
|
204
204
|
fetchProviderHashRequirementsBy: () => fetchProviderHashRequirementsBy,
|
|
205
205
|
fetchStatusUrl: () => fetchStatusUrl,
|
|
206
|
+
generateAttestationNonce: () => generateAttestationNonce,
|
|
207
|
+
generateInitSignature: () => generateInitSignature,
|
|
206
208
|
generateSpecsFromRequestSpecTemplate: () => generateSpecsFromRequestSpecTemplate,
|
|
207
209
|
getAttestors: () => getAttestors,
|
|
208
210
|
getDeviceType: () => getDeviceType,
|
|
@@ -225,6 +227,7 @@ __export(index_exports, {
|
|
|
225
227
|
takeTemplateParametersFromProofs: () => takeTemplateParametersFromProofs,
|
|
226
228
|
transformForOnchain: () => transformForOnchain,
|
|
227
229
|
updateSession: () => updateSession,
|
|
230
|
+
verifyAttestorTeeAttestation: () => verifyAttestorTeeAttestation,
|
|
228
231
|
verifyProof: () => verifyProof,
|
|
229
232
|
verifyTeeAttestation: () => verifyTeeAttestation
|
|
230
233
|
});
|
|
@@ -239,7 +242,7 @@ var RECLAIM_EXTENSION_ACTIONS = {
|
|
|
239
242
|
};
|
|
240
243
|
|
|
241
244
|
// src/Reclaim.ts
|
|
242
|
-
var
|
|
245
|
+
var import_ethers7 = require("ethers");
|
|
243
246
|
var import_canonicalize3 = __toESM(require("canonicalize"));
|
|
244
247
|
|
|
245
248
|
// src/utils/errors.ts
|
|
@@ -287,6 +290,7 @@ var ProofSubmissionFailedError = createErrorClass("ProofSubmissionFailedError");
|
|
|
287
290
|
var ErrorDuringVerificationError = createErrorClass("ErrorDuringVerificationError");
|
|
288
291
|
var CallbackUrlRequiredError = createErrorClass("CallbackUrlRequiredError");
|
|
289
292
|
var TeeVerificationError = createErrorClass("TeeVerificationError");
|
|
293
|
+
var AttestorTeeVerificationError = createErrorClass("AttestorTeeVerificationError");
|
|
290
294
|
|
|
291
295
|
// src/utils/logger.ts
|
|
292
296
|
var SimpleLogger = class {
|
|
@@ -561,19 +565,21 @@ function scheduleIntervalEndingTask(sessionId, intervals, onFailureCallback, tim
|
|
|
561
565
|
}
|
|
562
566
|
}, timeout);
|
|
563
567
|
}
|
|
564
|
-
var createVerifyProofResultSuccess = (proofs, isTeeAttestationVerified) => {
|
|
568
|
+
var createVerifyProofResultSuccess = (proofs, isTeeAttestationVerified, isAttestorTeeAttestationVerified) => {
|
|
565
569
|
return {
|
|
566
570
|
isVerified: true,
|
|
567
571
|
isTeeAttestationVerified,
|
|
572
|
+
isAttestorTeeAttestationVerified,
|
|
568
573
|
error: void 0,
|
|
569
574
|
data: proofs.map(createTrustedDataFromProofData),
|
|
570
575
|
publicData: getPublicDataFromProofs(proofs)
|
|
571
576
|
};
|
|
572
577
|
};
|
|
573
|
-
var createVerifyProofResultFailure = (error, isTeeAttestationVerified) => {
|
|
578
|
+
var createVerifyProofResultFailure = (error, isTeeAttestationVerified, isAttestorTeeAttestationVerified) => {
|
|
574
579
|
return {
|
|
575
580
|
isVerified: false,
|
|
576
581
|
isTeeAttestationVerified,
|
|
582
|
+
isAttestorTeeAttestationVerified,
|
|
577
583
|
error,
|
|
578
584
|
data: [],
|
|
579
585
|
publicData: []
|
|
@@ -649,6 +655,43 @@ var constants = {
|
|
|
649
655
|
// Chrome extension URL for Reclaim Protocol
|
|
650
656
|
CHROME_EXTENSION_URL: "https://chromewebstore.google.com/detail/reclaim-extension/oafieibbbcepkmenknelhmgaoahamdeh"
|
|
651
657
|
};
|
|
658
|
+
var GCP_CONFIDENTIAL_SPACE_ROOT_CA = `-----BEGIN CERTIFICATE-----
|
|
659
|
+
MIIGCDCCA/CgAwIBAgITYBvRy5g9aYYMh7tJS7pFwafL6jANBgkqhkiG9w0BAQsF
|
|
660
|
+
ADCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcT
|
|
661
|
+
DU1vdW50YWluIFZpZXcxEzARBgNVBAoTCkdvb2dsZSBMTEMxFTATBgNVBAsTDEdv
|
|
662
|
+
b2dsZSBDbG91ZDEjMCEGA1UEAxMaQ29uZmlkZW50aWFsIFNwYWNlIFJvb3QgQ0Ew
|
|
663
|
+
HhcNMjQwMTE5MjIxMDUwWhcNMzQwMTE2MjIxMDQ5WjCBizELMAkGA1UEBhMCVVMx
|
|
664
|
+
EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEzAR
|
|
665
|
+
BgNVBAoTCkdvb2dsZSBMTEMxFTATBgNVBAsTDEdvb2dsZSBDbG91ZDEjMCEGA1UE
|
|
666
|
+
AxMaQ29uZmlkZW50aWFsIFNwYWNlIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUA
|
|
667
|
+
A4ICDwAwggIKAoICAQCvRuZasczAqhMZe1ODHJ6MFLX8EYVV+RN7xiO9GpuA53iz
|
|
668
|
+
l9Oxgp3NXik3FbYn+7bcIkMMSQpCr6K0jbSQCZT6d5P5PJT5DpNGYjLHkW67/fl+
|
|
669
|
+
Bu7eSMb0qRCa1jS+3OhNK7t7SIaHm1XdmSRghjwoglKRuk3CGrF4Zia9RcE/p2MU
|
|
670
|
+
69GyJZpqHYwTplNr3x4zF+2nJk86GywDP+sGwSPWfcmqY04VQD7ZPDEZZ/qgzdoL
|
|
671
|
+
5ilE92eQnAsy+6m6LxBEHHVcFpfDtNVUIt2VMCWLBeOKUQcn5js756xblInqw/Qt
|
|
672
|
+
QRR0An0yfRjBuGvmMjAwETDo5ETY/fc+nbQVYJzNQTc9EOpFFWPpw/ZjFcN9Amnd
|
|
673
|
+
dxYUETFXPmBYerMez0LKNtGpfKYHHhMMTI3mj0m/V9fCbfh2YbBUnMS2Swd20YSI
|
|
674
|
+
Mi/HiGaqOpGUqXMeQVw7phGTS3QYK8ZM65sC/QhIQzXdsiLDgFBitVnlIu3lIv6C
|
|
675
|
+
uiHvXeSJBRlRxQ8Vu+t6J7hBdl0etWBKAu9Vti46af5cjC03dspkHR3MAUGcrLWE
|
|
676
|
+
TkQ0msQAKvIAlwyQRLuQOI5D6pF+6af1Nbl+vR7sLCbDWdMqm1E9X6KyFKd6e3rn
|
|
677
|
+
E9O4dkFJp35WvR2gqIAkUoa+Vq1MXLFYG4imanZKH0igrIblbawRCr3Gr24FXQID
|
|
678
|
+
AQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
|
|
679
|
+
FgQUF+fBOE6Th1snpKuvIb6S8/mtPL4wHwYDVR0jBBgwFoAUF+fBOE6Th1snpKuv
|
|
680
|
+
Ib6S8/mtPL4wDQYJKoZIhvcNAQELBQADggIBAGtCuV5eHxWcffylK9GPumaD6Yjd
|
|
681
|
+
cs76KDBe3mky5ItBIrEOeZq3z47zM4dbKZHhFuoq4yAaO1MyApnG0w9wIQLBDndI
|
|
682
|
+
ovtkw6j9/64aqPWpNaoB5MB0SahCUCgI83Dx9SRqGmjPI/MTMfwDLdE5EF9gFmVI
|
|
683
|
+
oH62YnG2aa/sc6m/8wIK8WtTJazEI16/8GPG4ZUhwT6aR3IGGnEBPMbMd5VZQ0Hw
|
|
684
|
+
VbHBKWK3UykaSCxnEg8uaNx/rhNaOWuWtos4qL00dYyGV7ZXg4fpAq7244QUgkWV
|
|
685
|
+
AtVcU2SPBjDd30OFHASnenDHRzQdOtHaxLp4a4WaY3jb2V6Sn3LfE8zSy6GevxmN
|
|
686
|
+
COIWW3xnPF8rwKz4ABEPqECe37zzu3W1nzZAFtdkhPBNnlWYkIusTMtU+8v6EPKp
|
|
687
|
+
GIIRphpaDhtGPJQukpENOfk2728lenPycRfjxwA96UKWq0dKZC45MwBEK9Jngn8Q
|
|
688
|
+
cPmpPmx7pSMkSxEX2Vos2JNaNmCKJd2VaXz8M6F2cxscRdh9TbAYAjGEEjE1nLUH
|
|
689
|
+
2YHDS8Y7xYNFIDSFaJAlqGcCUbzjGhrwHGj4voTe9ZvlmngrcA/ptSuBidvsnRDw
|
|
690
|
+
kNPLowCd0NqxYYSLNL7GroYCFPxoBpr+++4vsCaXalbs8iJxdU2EPqG4MB4xWKYg
|
|
691
|
+
uyT5CnJulxSC5CT1
|
|
692
|
+
-----END CERTIFICATE-----`;
|
|
693
|
+
var ATTESTOR_NONCE_PATTERN = /^attestor_public_key:0x([0-9a-fA-F]{40})$/;
|
|
694
|
+
var GCP_CONFIDENTIAL_SPACE_ISSUER = "https://confidentialcomputing.googleapis.com";
|
|
652
695
|
|
|
653
696
|
// src/utils/fetch.ts
|
|
654
697
|
var import_fetch_retry = __toESM(require("fetch-retry"));
|
|
@@ -1690,7 +1733,6 @@ function assertValidateProof(proofs, config) {
|
|
|
1690
1733
|
// src/utils/verifyTee.ts
|
|
1691
1734
|
var import_ethers5 = require("ethers");
|
|
1692
1735
|
var logger9 = logger_default.logger;
|
|
1693
|
-
var EXPECTED_ISSUER = "https://confidentialcomputing.googleapis.com";
|
|
1694
1736
|
var EXPECTED_HW_MODEL = "GCP_AMD_SEV";
|
|
1695
1737
|
var EXPECTED_TEE_PROVIDER = "gcp";
|
|
1696
1738
|
var EXPECTED_TEE_TECHNOLOGY = "amd-sev";
|
|
@@ -1977,8 +2019,8 @@ ${teeAttestation.verifier.image_digest}`
|
|
|
1977
2019
|
function verifyGcpClaims(teeAttestation, expectedNonce) {
|
|
1978
2020
|
return __async(this, null, function* () {
|
|
1979
2021
|
var _a;
|
|
1980
|
-
const claims = yield verifyJwtSignature(teeAttestation.attestation.token,
|
|
1981
|
-
assert(claims.iss ===
|
|
2022
|
+
const claims = yield verifyJwtSignature(teeAttestation.attestation.token, GCP_CONFIDENTIAL_SPACE_ISSUER);
|
|
2023
|
+
assert(claims.iss === GCP_CONFIDENTIAL_SPACE_ISSUER, `unexpected issuer: ${claims.iss}`);
|
|
1982
2024
|
assertAudienceClaim(claims.aud);
|
|
1983
2025
|
assert(Array.isArray(claims.eat_nonce), "eat_nonce claim missing");
|
|
1984
2026
|
const digestBinding = yield computeDigestBinding(teeAttestation);
|
|
@@ -2045,8 +2087,225 @@ function runTeeVerification(proofs, config) {
|
|
|
2045
2087
|
});
|
|
2046
2088
|
}
|
|
2047
2089
|
|
|
2048
|
-
// src/
|
|
2090
|
+
// src/utils/verifyAttestorTee.ts
|
|
2091
|
+
var import_crypto = __toESM(require("crypto"));
|
|
2092
|
+
var import_ethers6 = require("ethers");
|
|
2049
2093
|
var logger10 = logger_default.logger;
|
|
2094
|
+
var BROWSER_ENVIRONMENT_ERROR2 = "Attestor TEE attestation verification is only supported in non-browser environments. Run verifyAttestorTeeAttestation on your server or API route.";
|
|
2095
|
+
function isBrowserEnvironment2() {
|
|
2096
|
+
if (typeof window !== "undefined" || typeof document !== "undefined") {
|
|
2097
|
+
return true;
|
|
2098
|
+
}
|
|
2099
|
+
if (typeof navigator !== "undefined" && typeof process === "undefined") {
|
|
2100
|
+
return true;
|
|
2101
|
+
}
|
|
2102
|
+
const workerGlobalScope = globalThis.WorkerGlobalScope;
|
|
2103
|
+
if (typeof workerGlobalScope !== "undefined" && typeof self !== "undefined" && self instanceof workerGlobalScope) {
|
|
2104
|
+
return true;
|
|
2105
|
+
}
|
|
2106
|
+
return false;
|
|
2107
|
+
}
|
|
2108
|
+
function assertNonBrowserEnvironment2() {
|
|
2109
|
+
if (isBrowserEnvironment2()) {
|
|
2110
|
+
throw new Error(BROWSER_ENVIRONMENT_ERROR2);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
var TOKEN_CLOCK_SKEW_S2 = 60;
|
|
2114
|
+
function decodeBase64Url2(input) {
|
|
2115
|
+
const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
2116
|
+
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
2117
|
+
return Buffer.from(padded, "base64");
|
|
2118
|
+
}
|
|
2119
|
+
function normalizeAddress(address) {
|
|
2120
|
+
return address.trim().toLowerCase().replace(/^0x/, "");
|
|
2121
|
+
}
|
|
2122
|
+
function verifyX5cChain(x5cChain) {
|
|
2123
|
+
if (!x5cChain || x5cChain.length === 0) {
|
|
2124
|
+
throw new Error("Empty x5c certificate chain");
|
|
2125
|
+
}
|
|
2126
|
+
const certs = x5cChain.map(
|
|
2127
|
+
(b64) => new import_crypto.X509Certificate(`-----BEGIN CERTIFICATE-----
|
|
2128
|
+
${b64}
|
|
2129
|
+
-----END CERTIFICATE-----`)
|
|
2130
|
+
);
|
|
2131
|
+
const root = new import_crypto.X509Certificate(GCP_CONFIDENTIAL_SPACE_ROOT_CA);
|
|
2132
|
+
for (let i = 0; i < certs.length - 1; i++) {
|
|
2133
|
+
if (!certs[i].verify(certs[i + 1].publicKey)) {
|
|
2134
|
+
throw new Error(`Certificate chain verification failed at level ${i}`);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
const top = certs[certs.length - 1];
|
|
2138
|
+
if (!top.verify(root.publicKey)) {
|
|
2139
|
+
throw new Error("Certificate chain does not root to GCP Confidential Space Root CA");
|
|
2140
|
+
}
|
|
2141
|
+
return certs[0].publicKey;
|
|
2142
|
+
}
|
|
2143
|
+
function verifyAttestorTeeAttestation(report, expectedAttestorAddress) {
|
|
2144
|
+
return __async(this, null, function* () {
|
|
2145
|
+
var _a, _b, _c, _d, _e;
|
|
2146
|
+
try {
|
|
2147
|
+
assertNonBrowserEnvironment2();
|
|
2148
|
+
if (!report || typeof report !== "string") {
|
|
2149
|
+
throw new Error("attestation report is empty or not a string");
|
|
2150
|
+
}
|
|
2151
|
+
if (!expectedAttestorAddress || typeof expectedAttestorAddress !== "string") {
|
|
2152
|
+
throw new Error("expectedAttestorAddress is required");
|
|
2153
|
+
}
|
|
2154
|
+
const parts = report.split(".");
|
|
2155
|
+
if (parts.length !== 3) {
|
|
2156
|
+
throw new Error("attestation report is not a JWT (expected 3 parts)");
|
|
2157
|
+
}
|
|
2158
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
2159
|
+
const header = JSON.parse(decodeBase64Url2(headerB64).toString("utf8"));
|
|
2160
|
+
const payload = JSON.parse(decodeBase64Url2(payloadB64).toString("utf8"));
|
|
2161
|
+
if (header.alg !== "RS256") {
|
|
2162
|
+
throw new Error(`unexpected signing algorithm: ${header.alg}`);
|
|
2163
|
+
}
|
|
2164
|
+
if (!Array.isArray(header.x5c) || header.x5c.length === 0) {
|
|
2165
|
+
throw new Error("attestation report is missing x5c certificate chain");
|
|
2166
|
+
}
|
|
2167
|
+
if (payload.iss !== GCP_CONFIDENTIAL_SPACE_ISSUER) {
|
|
2168
|
+
throw new Error(`unexpected issuer: ${payload.iss}`);
|
|
2169
|
+
}
|
|
2170
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2171
|
+
if (typeof payload.nbf === "number" && now + TOKEN_CLOCK_SKEW_S2 < payload.nbf) {
|
|
2172
|
+
throw new Error(`attestation not yet valid (nbf=${payload.nbf})`);
|
|
2173
|
+
}
|
|
2174
|
+
if (typeof payload.exp === "number" && now - TOKEN_CLOCK_SKEW_S2 > payload.exp) {
|
|
2175
|
+
throw new Error(`attestation expired (exp=${payload.exp})`);
|
|
2176
|
+
}
|
|
2177
|
+
if (typeof payload.iat === "number" && payload.iat > now + TOKEN_CLOCK_SKEW_S2) {
|
|
2178
|
+
throw new Error(`attestation issued in future (iat=${payload.iat})`);
|
|
2179
|
+
}
|
|
2180
|
+
const publicKey = verifyX5cChain(header.x5c);
|
|
2181
|
+
const verifier = import_crypto.default.createVerify("RSA-SHA256");
|
|
2182
|
+
verifier.update(`${headerB64}.${payloadB64}`);
|
|
2183
|
+
if (!verifier.verify(publicKey, new Uint8Array(decodeBase64Url2(signatureB64)))) {
|
|
2184
|
+
throw new Error("attestation signature verification failed");
|
|
2185
|
+
}
|
|
2186
|
+
if (!payload.eat_nonce) {
|
|
2187
|
+
throw new Error("eat_nonce claim is missing");
|
|
2188
|
+
}
|
|
2189
|
+
const nonces = Array.isArray(payload.eat_nonce) ? payload.eat_nonce : [payload.eat_nonce];
|
|
2190
|
+
let attestedAddress;
|
|
2191
|
+
for (const n of nonces) {
|
|
2192
|
+
const m = typeof n === "string" ? n.match(ATTESTOR_NONCE_PATTERN) : null;
|
|
2193
|
+
if (m) {
|
|
2194
|
+
attestedAddress = m[1];
|
|
2195
|
+
break;
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
if (!attestedAddress) {
|
|
2199
|
+
throw new Error(
|
|
2200
|
+
`attestor_public_key nonce not found in eat_nonce: ${JSON.stringify(payload.eat_nonce)}`
|
|
2201
|
+
);
|
|
2202
|
+
}
|
|
2203
|
+
if (normalizeAddress(attestedAddress) !== normalizeAddress(expectedAttestorAddress)) {
|
|
2204
|
+
throw new Error(
|
|
2205
|
+
`attestor address mismatch: attestation binds to 0x${attestedAddress.toLowerCase()}, expected ${expectedAttestorAddress}`
|
|
2206
|
+
);
|
|
2207
|
+
}
|
|
2208
|
+
const imageDigest = (_e = (_b = (_a = payload.submods) == null ? void 0 : _a.container) == null ? void 0 : _b.image_digest) != null ? _e : (_d = (_c = payload.google) == null ? void 0 : _c.compute_engine) == null ? void 0 : _d.image_digest;
|
|
2209
|
+
return { isVerified: true, imageDigest };
|
|
2210
|
+
} catch (error) {
|
|
2211
|
+
return {
|
|
2212
|
+
isVerified: false,
|
|
2213
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
function normalizeAttestorAddress(address) {
|
|
2219
|
+
return address.trim().toLowerCase();
|
|
2220
|
+
}
|
|
2221
|
+
function normalizeSignature(sig) {
|
|
2222
|
+
return sig.trim().toLowerCase();
|
|
2223
|
+
}
|
|
2224
|
+
function verifyAttestorTeeForProof(proof, config) {
|
|
2225
|
+
return __async(this, null, function* () {
|
|
2226
|
+
var _a;
|
|
2227
|
+
if (!proof.witnesses || proof.witnesses.length === 0) {
|
|
2228
|
+
throw new AttestorTeeVerificationError("Proof has no witnesses");
|
|
2229
|
+
}
|
|
2230
|
+
const expectedDigests = (_a = config.expectedImageDigests) == null ? void 0 : _a.map((d) => d.trim());
|
|
2231
|
+
const proofSignatures = new Set((proof.signatures || []).map(normalizeSignature));
|
|
2232
|
+
const claimSignData = createSignDataForClaim(proof.claimData);
|
|
2233
|
+
for (const witness of proof.witnesses) {
|
|
2234
|
+
const att = witness.claimAttestation;
|
|
2235
|
+
if (!att) {
|
|
2236
|
+
throw new AttestorTeeVerificationError(
|
|
2237
|
+
`Witness ${witness.id} is missing claimAttestation`
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
if (normalizeAttestorAddress(att.attestor_address) !== normalizeAttestorAddress(witness.id)) {
|
|
2241
|
+
throw new AttestorTeeVerificationError(
|
|
2242
|
+
`claimAttestation.attestor_address ${att.attestor_address} does not match witness id ${witness.id}`
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
if (!proofSignatures.has(normalizeSignature(att.claim_signature))) {
|
|
2246
|
+
throw new AttestorTeeVerificationError(
|
|
2247
|
+
`claimAttestation.claim_signature for witness ${witness.id} is not present in proof.signatures`
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
let recoveredSigner;
|
|
2251
|
+
try {
|
|
2252
|
+
recoveredSigner = import_ethers6.ethers.verifyMessage(claimSignData, att.claim_signature);
|
|
2253
|
+
} catch (error) {
|
|
2254
|
+
throw new AttestorTeeVerificationError(
|
|
2255
|
+
`Failed to recover signer from claimAttestation.claim_signature for witness ${witness.id}`,
|
|
2256
|
+
error
|
|
2257
|
+
);
|
|
2258
|
+
}
|
|
2259
|
+
if (normalizeAttestorAddress(recoveredSigner) !== normalizeAttestorAddress(witness.id)) {
|
|
2260
|
+
throw new AttestorTeeVerificationError(
|
|
2261
|
+
`claim_signature recovers to ${recoveredSigner}, expected attestor ${witness.id}`
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
const result = yield verifyAttestorTeeAttestation(att.attestation_report, witness.id);
|
|
2265
|
+
if (!result.isVerified) {
|
|
2266
|
+
throw new AttestorTeeVerificationError(
|
|
2267
|
+
`Attestor TEE attestation verification failed for witness ${witness.id}: ${result.error}`
|
|
2268
|
+
);
|
|
2269
|
+
}
|
|
2270
|
+
if (expectedDigests && expectedDigests.length > 0) {
|
|
2271
|
+
if (!result.imageDigest) {
|
|
2272
|
+
throw new AttestorTeeVerificationError(
|
|
2273
|
+
`Attestor TEE attestation for witness ${witness.id} did not expose an image digest to check against expectedImageDigests`
|
|
2274
|
+
);
|
|
2275
|
+
}
|
|
2276
|
+
if (!expectedDigests.includes(result.imageDigest)) {
|
|
2277
|
+
throw new AttestorTeeVerificationError(
|
|
2278
|
+
`Attestor image digest ${result.imageDigest} for witness ${witness.id} is not in expectedImageDigests`
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
});
|
|
2284
|
+
}
|
|
2285
|
+
function runAttestorTeeVerification(_0) {
|
|
2286
|
+
return __async(this, arguments, function* (proofs, config = {}) {
|
|
2287
|
+
if (!proofs || proofs.length === 0) {
|
|
2288
|
+
throw new AttestorTeeVerificationError("No proofs provided for attestor TEE verification");
|
|
2289
|
+
}
|
|
2290
|
+
try {
|
|
2291
|
+
for (const proof of proofs) {
|
|
2292
|
+
yield verifyAttestorTeeForProof(proof, config);
|
|
2293
|
+
}
|
|
2294
|
+
} catch (error) {
|
|
2295
|
+
logger10.error("Attestor TEE attestation verification failed:", error);
|
|
2296
|
+
if (error instanceof AttestorTeeVerificationError) {
|
|
2297
|
+
throw error;
|
|
2298
|
+
}
|
|
2299
|
+
throw new AttestorTeeVerificationError(
|
|
2300
|
+
"Attestor TEE attestation verification failed",
|
|
2301
|
+
error
|
|
2302
|
+
);
|
|
2303
|
+
}
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
// src/Reclaim.ts
|
|
2308
|
+
var logger11 = logger_default.logger;
|
|
2050
2309
|
var sdkVersion = require_package().version;
|
|
2051
2310
|
var SDK_TEE_ATTESTATION_VERSION = "v3";
|
|
2052
2311
|
function verifyProof(proofOrProofs, config) {
|
|
@@ -2065,16 +2324,21 @@ function verifyProof(proofOrProofs, config) {
|
|
|
2065
2324
|
}
|
|
2066
2325
|
yield assertValidateProof(proofs, config);
|
|
2067
2326
|
let isTeeAttestationVerified;
|
|
2327
|
+
let isAttestorTeeAttestationVerified;
|
|
2068
2328
|
if (config.teeAttestation && "dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
|
|
2069
|
-
|
|
2329
|
+
logger11.warn("teeAttestation is enabled but content validation is disabled \u2014 TEE attestation alone does not guarantee proof contents are valid");
|
|
2070
2330
|
}
|
|
2071
2331
|
if (config.teeAttestation) {
|
|
2072
2332
|
yield runTeeVerification(proofs, config.teeAttestation);
|
|
2073
2333
|
isTeeAttestationVerified = true;
|
|
2074
2334
|
}
|
|
2075
|
-
|
|
2335
|
+
if (config.attestorTeeAttestation) {
|
|
2336
|
+
yield runAttestorTeeVerification(proofs, config.attestorTeeAttestation);
|
|
2337
|
+
isAttestorTeeAttestationVerified = true;
|
|
2338
|
+
}
|
|
2339
|
+
return createVerifyProofResultSuccess(proofs, isTeeAttestationVerified, isAttestorTeeAttestationVerified);
|
|
2076
2340
|
} catch (error) {
|
|
2077
|
-
|
|
2341
|
+
logger11.error("Error in validating proof:", error);
|
|
2078
2342
|
const _error = error instanceof Error ? error : new Error(String(error));
|
|
2079
2343
|
return createVerifyProofResultFailure(_error);
|
|
2080
2344
|
}
|
|
@@ -2224,7 +2488,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2224
2488
|
}
|
|
2225
2489
|
this.options = options;
|
|
2226
2490
|
this.sdkVersion = "js-" + sdkVersion;
|
|
2227
|
-
|
|
2491
|
+
logger11.info(`Initializing client with applicationId: ${this.applicationId}`);
|
|
2228
2492
|
}
|
|
2229
2493
|
/**
|
|
2230
2494
|
* Initializes a new Reclaim proof request instance with automatic signature generation and session creation.
|
|
@@ -2255,81 +2519,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2255
2519
|
{ paramName: "providerId", input: providerId, isString: true },
|
|
2256
2520
|
{ paramName: "appSecret", input: appSecret, isString: true }
|
|
2257
2521
|
], "the constructor");
|
|
2258
|
-
|
|
2259
|
-
if (options.acceptAiProviders) {
|
|
2260
|
-
validateFunctionParams([
|
|
2261
|
-
{ paramName: "acceptAiProviders", input: options.acceptAiProviders }
|
|
2262
|
-
], "the constructor");
|
|
2263
|
-
}
|
|
2264
|
-
if (options.providerVersion) {
|
|
2265
|
-
validateFunctionParams([
|
|
2266
|
-
{ paramName: "providerVersion", input: options.providerVersion, isString: true }
|
|
2267
|
-
], "the constructor");
|
|
2268
|
-
}
|
|
2269
|
-
if (options.log) {
|
|
2270
|
-
validateFunctionParams([
|
|
2271
|
-
{ paramName: "log", input: options.log }
|
|
2272
|
-
], "the constructor");
|
|
2273
|
-
}
|
|
2274
|
-
if (options.useAppClip) {
|
|
2275
|
-
validateFunctionParams([
|
|
2276
|
-
{ paramName: "useAppClip", input: options.useAppClip }
|
|
2277
|
-
], "the constructor");
|
|
2278
|
-
}
|
|
2279
|
-
if (options.device) {
|
|
2280
|
-
validateFunctionParams([
|
|
2281
|
-
{ paramName: "device", input: options.device, isString: true }
|
|
2282
|
-
], "the constructor");
|
|
2283
|
-
}
|
|
2284
|
-
if (options.useBrowserExtension) {
|
|
2285
|
-
validateFunctionParams([
|
|
2286
|
-
{ paramName: "useBrowserExtension", input: options.useBrowserExtension }
|
|
2287
|
-
], "the constructor");
|
|
2288
|
-
}
|
|
2289
|
-
if (options.extensionID) {
|
|
2290
|
-
validateFunctionParams([
|
|
2291
|
-
{ paramName: "extensionID", input: options.extensionID, isString: true }
|
|
2292
|
-
], "the constructor");
|
|
2293
|
-
}
|
|
2294
|
-
if (options.envUrl) {
|
|
2295
|
-
validateFunctionParams([
|
|
2296
|
-
{ paramName: "envUrl", input: options.envUrl, isString: true }
|
|
2297
|
-
], "the constructor");
|
|
2298
|
-
}
|
|
2299
|
-
if (options.portalUrl) {
|
|
2300
|
-
validateFunctionParams([
|
|
2301
|
-
{ paramName: "portalUrl", input: options.portalUrl, isString: true }
|
|
2302
|
-
], "the constructor");
|
|
2303
|
-
}
|
|
2304
|
-
if (options.customSharePageUrl) {
|
|
2305
|
-
validateFunctionParams([
|
|
2306
|
-
{ paramName: "customSharePageUrl", input: options.customSharePageUrl, isString: true }
|
|
2307
|
-
], "the constructor");
|
|
2308
|
-
}
|
|
2309
|
-
if (options.customAppClipUrl) {
|
|
2310
|
-
validateFunctionParams([
|
|
2311
|
-
{ paramName: "customAppClipUrl", input: options.customAppClipUrl, isString: true }
|
|
2312
|
-
], "the constructor");
|
|
2313
|
-
}
|
|
2314
|
-
if (options.preferredLocale) {
|
|
2315
|
-
validateFunctionParams([
|
|
2316
|
-
{ paramName: "preferredLocale", input: options.preferredLocale, isString: true }
|
|
2317
|
-
], "the constructor");
|
|
2318
|
-
validateFunctionParamsWithFn({
|
|
2319
|
-
paramName: "preferredLocale",
|
|
2320
|
-
input: options.preferredLocale,
|
|
2321
|
-
isValid: () => {
|
|
2322
|
-
try {
|
|
2323
|
-
Intl.getCanonicalLocales(options.preferredLocale);
|
|
2324
|
-
return true;
|
|
2325
|
-
} catch (error) {
|
|
2326
|
-
logger10.info("Failed to canonicalize locale", error);
|
|
2327
|
-
return false;
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
}, "the constructor");
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
2522
|
+
_ReclaimProofRequest.validateInitOptions(options, "the constructor");
|
|
2333
2523
|
const proofRequestOptions = __spreadProps(__spreadValues({}, options), {
|
|
2334
2524
|
acceptTeeAttestation: (_a = options == null ? void 0 : options.acceptTeeAttestation) != null ? _a : true
|
|
2335
2525
|
});
|
|
@@ -2357,11 +2547,100 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2357
2547
|
return proofRequestInstance;
|
|
2358
2548
|
} catch (error) {
|
|
2359
2549
|
console.error(error);
|
|
2360
|
-
|
|
2550
|
+
logger11.info("Failed to initialize ReclaimProofRequest", error);
|
|
2361
2551
|
throw new InitError("Failed to initialize ReclaimProofRequest", error);
|
|
2362
2552
|
}
|
|
2363
2553
|
});
|
|
2364
2554
|
}
|
|
2555
|
+
/**
|
|
2556
|
+
* Initializes a new Reclaim proof request using a signature computed externally
|
|
2557
|
+
* (e.g. on a trusted backend), so `appSecret` never has to live on the client.
|
|
2558
|
+
*
|
|
2559
|
+
* The signature must be produced over `canonicalize({ providerId, timestamp })`
|
|
2560
|
+
* using the application's `appSecret` — see `generateInitSignature()` for the
|
|
2561
|
+
* exact algorithm. The same `timestamp` used at signing time must be passed here.
|
|
2562
|
+
*
|
|
2563
|
+
* TEE attestation: the attestation nonce depends on `sessionId`, which is only
|
|
2564
|
+
* known after the backend init call. To use TEE without exposing `appSecret`,
|
|
2565
|
+
* pass an async `getAttestationNonce` callback that derives the nonce on your
|
|
2566
|
+
* server using `generateAttestationNonce(appSecret, applicationId, sessionId, timestamp)`.
|
|
2567
|
+
* If `acceptTeeAttestation` is left enabled but no callback is provided, init throws.
|
|
2568
|
+
*
|
|
2569
|
+
* @param applicationId - Your Reclaim application ID
|
|
2570
|
+
* @param providerId - The ID of the provider to use for proof generation
|
|
2571
|
+
* @param sessionAuth - Pre-computed signature, the timestamp it was signed over,
|
|
2572
|
+
* and an optional async callback to compute the attestation nonce.
|
|
2573
|
+
* @param options - Optional configuration options for the proof request
|
|
2574
|
+
*
|
|
2575
|
+
* @example
|
|
2576
|
+
* ```typescript
|
|
2577
|
+
* // Backend (Node):
|
|
2578
|
+
* const timestamp = Date.now().toString();
|
|
2579
|
+
* const signature = await generateInitSignature(APP_SECRET, providerId, timestamp);
|
|
2580
|
+
* // ...return { signature, timestamp } to the client...
|
|
2581
|
+
*
|
|
2582
|
+
* // Client:
|
|
2583
|
+
* const proofRequest = await ReclaimProofRequest.initWithSignature(
|
|
2584
|
+
* applicationId,
|
|
2585
|
+
* providerId,
|
|
2586
|
+
* { signature, timestamp },
|
|
2587
|
+
* { acceptTeeAttestation: false }
|
|
2588
|
+
* );
|
|
2589
|
+
* ```
|
|
2590
|
+
*/
|
|
2591
|
+
static initWithSignature(applicationId, providerId, sessionAuth, options) {
|
|
2592
|
+
return __async(this, null, function* () {
|
|
2593
|
+
var _a;
|
|
2594
|
+
try {
|
|
2595
|
+
validateFunctionParams([
|
|
2596
|
+
{ paramName: "applicationId", input: applicationId, isString: true },
|
|
2597
|
+
{ paramName: "providerId", input: providerId, isString: true },
|
|
2598
|
+
{ paramName: "signature", input: sessionAuth == null ? void 0 : sessionAuth.signature, isString: true },
|
|
2599
|
+
{ paramName: "timestamp", input: sessionAuth == null ? void 0 : sessionAuth.timestamp, isString: true }
|
|
2600
|
+
], "initWithSignature");
|
|
2601
|
+
_ReclaimProofRequest.validateInitOptions(options, "initWithSignature");
|
|
2602
|
+
const proofRequestOptions = __spreadProps(__spreadValues({}, options), {
|
|
2603
|
+
acceptTeeAttestation: (_a = options == null ? void 0 : options.acceptTeeAttestation) != null ? _a : true
|
|
2604
|
+
});
|
|
2605
|
+
if (proofRequestOptions.acceptTeeAttestation && !sessionAuth.getAttestationNonce) {
|
|
2606
|
+
throw new InvalidParamError(
|
|
2607
|
+
"initWithSignature requires a `getAttestationNonce` callback when `acceptTeeAttestation` is enabled. Either pass `acceptTeeAttestation: false`, or provide a callback that computes the nonce server-side using `generateAttestationNonce(appSecret, applicationId, sessionId, timestamp)`."
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2610
|
+
const proofRequestInstance = new _ReclaimProofRequest(applicationId, providerId, proofRequestOptions);
|
|
2611
|
+
proofRequestInstance.timeStamp = sessionAuth.timestamp;
|
|
2612
|
+
proofRequestInstance.setSignature(sessionAuth.signature);
|
|
2613
|
+
const data = yield initSession(
|
|
2614
|
+
providerId,
|
|
2615
|
+
applicationId,
|
|
2616
|
+
sessionAuth.timestamp,
|
|
2617
|
+
sessionAuth.signature,
|
|
2618
|
+
options == null ? void 0 : options.providerVersion
|
|
2619
|
+
);
|
|
2620
|
+
proofRequestInstance.sessionId = data.sessionId;
|
|
2621
|
+
proofRequestInstance.resolvedProviderVersion = data.resolvedProviderVersion;
|
|
2622
|
+
proofRequestInstance.context.reclaimSessionId = data.sessionId;
|
|
2623
|
+
if (proofRequestOptions.acceptTeeAttestation && sessionAuth.getAttestationNonce) {
|
|
2624
|
+
const attestationNonce = yield sessionAuth.getAttestationNonce(data.sessionId);
|
|
2625
|
+
validateFunctionParams(
|
|
2626
|
+
[{ input: attestationNonce, paramName: "attestationNonce", isString: true }],
|
|
2627
|
+
"initWithSignature"
|
|
2628
|
+
);
|
|
2629
|
+
proofRequestInstance.setAttestationContext(attestationNonce, {
|
|
2630
|
+
applicationId,
|
|
2631
|
+
sessionId: data.sessionId,
|
|
2632
|
+
timestamp: sessionAuth.timestamp,
|
|
2633
|
+
attestationVersion: SDK_TEE_ATTESTATION_VERSION
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
return proofRequestInstance;
|
|
2637
|
+
} catch (error) {
|
|
2638
|
+
console.error(error);
|
|
2639
|
+
logger11.info("Failed to initialize ReclaimProofRequest with signature", error);
|
|
2640
|
+
throw new InitError("Failed to initialize ReclaimProofRequest with signature", error);
|
|
2641
|
+
}
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2365
2644
|
/**
|
|
2366
2645
|
* Creates a ReclaimProofRequest instance from a JSON string representation
|
|
2367
2646
|
*
|
|
@@ -2474,7 +2753,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2474
2753
|
Intl.getCanonicalLocales(options.preferredLocale);
|
|
2475
2754
|
return true;
|
|
2476
2755
|
} catch (error) {
|
|
2477
|
-
|
|
2756
|
+
logger11.info("Failed to canonicalize locale", error);
|
|
2478
2757
|
return false;
|
|
2479
2758
|
}
|
|
2480
2759
|
}
|
|
@@ -2499,7 +2778,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2499
2778
|
proofRequestInstance.cancelRedirectUrlOptions = cancelRedirectUrlOptions;
|
|
2500
2779
|
return proofRequestInstance;
|
|
2501
2780
|
} catch (error) {
|
|
2502
|
-
|
|
2781
|
+
logger11.info("Failed to parse JSON string in fromJsonString:", error);
|
|
2503
2782
|
throw new InvalidParamError("Invalid JSON string provided to fromJsonString");
|
|
2504
2783
|
}
|
|
2505
2784
|
});
|
|
@@ -2660,9 +2939,9 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2660
2939
|
try {
|
|
2661
2940
|
validateModalOptions(options, "setModalOptions");
|
|
2662
2941
|
this.modalOptions = __spreadValues(__spreadValues({}, this.modalOptions), options);
|
|
2663
|
-
|
|
2942
|
+
logger11.info("Modal options set successfully");
|
|
2664
2943
|
} catch (error) {
|
|
2665
|
-
|
|
2944
|
+
logger11.info("Error setting modal options:", error);
|
|
2666
2945
|
throw new SetParamsError("Error setting modal options", error);
|
|
2667
2946
|
}
|
|
2668
2947
|
}
|
|
@@ -2692,7 +2971,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2692
2971
|
this.context = JSON.parse(canonicalStringify(__spreadProps(__spreadValues({}, context), { reclaimSessionId: this.sessionId })));
|
|
2693
2972
|
this.applyAttestationContext();
|
|
2694
2973
|
} catch (error) {
|
|
2695
|
-
|
|
2974
|
+
logger11.info("Error setting context", error);
|
|
2696
2975
|
throw new SetContextError("Error setting context", error);
|
|
2697
2976
|
}
|
|
2698
2977
|
}
|
|
@@ -2724,7 +3003,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2724
3003
|
this.context = { contextAddress: address, contextMessage: message, reclaimSessionId: this.sessionId };
|
|
2725
3004
|
this.applyAttestationContext();
|
|
2726
3005
|
} catch (error) {
|
|
2727
|
-
|
|
3006
|
+
logger11.info("Error setting context", error);
|
|
2728
3007
|
throw new SetContextError("Error setting context", error);
|
|
2729
3008
|
}
|
|
2730
3009
|
}
|
|
@@ -2759,7 +3038,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2759
3038
|
validateParameters(params);
|
|
2760
3039
|
this.parameters = __spreadValues(__spreadValues({}, this.parameters), params);
|
|
2761
3040
|
} catch (error) {
|
|
2762
|
-
|
|
3041
|
+
logger11.info("Error Setting Params:", error);
|
|
2763
3042
|
throw new SetParamsError("Error setting params", error);
|
|
2764
3043
|
}
|
|
2765
3044
|
}
|
|
@@ -2783,7 +3062,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2783
3062
|
validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getAppCallbackUrl");
|
|
2784
3063
|
return this.appCallbackUrl || `${constants.DEFAULT_RECLAIM_CALLBACK_URL}${this.sessionId}`;
|
|
2785
3064
|
} catch (error) {
|
|
2786
|
-
|
|
3065
|
+
logger11.info("Error getting app callback url", error);
|
|
2787
3066
|
throw new GetAppCallbackUrlError("Error getting app callback url", error);
|
|
2788
3067
|
}
|
|
2789
3068
|
}
|
|
@@ -2807,7 +3086,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2807
3086
|
validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getCancelCallbackUrl");
|
|
2808
3087
|
return this.cancelCallbackUrl || `${constants.DEFAULT_RECLAIM_CANCEL_CALLBACK_URL}${this.sessionId}`;
|
|
2809
3088
|
} catch (error) {
|
|
2810
|
-
|
|
3089
|
+
logger11.info("Error getting cancel callback url", error);
|
|
2811
3090
|
throw new GetAppCallbackUrlError("Error getting cancel callback url", error);
|
|
2812
3091
|
}
|
|
2813
3092
|
}
|
|
@@ -2830,7 +3109,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2830
3109
|
validateFunctionParams([{ input: this.sessionId, paramName: "sessionId", isString: true }], "getStatusUrl");
|
|
2831
3110
|
return `${constants.DEFAULT_RECLAIM_STATUS_URL}${this.sessionId}`;
|
|
2832
3111
|
} catch (error) {
|
|
2833
|
-
|
|
3112
|
+
logger11.info("Error fetching Status Url", error);
|
|
2834
3113
|
throw new GetStatusUrlError("Error fetching status url", error);
|
|
2835
3114
|
}
|
|
2836
3115
|
}
|
|
@@ -2855,29 +3134,81 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2855
3134
|
}
|
|
2856
3135
|
return this.sessionId;
|
|
2857
3136
|
}
|
|
3137
|
+
static validateInitOptions(options, caller) {
|
|
3138
|
+
if (!options) return;
|
|
3139
|
+
if (options.acceptAiProviders) {
|
|
3140
|
+
validateFunctionParams([{ paramName: "acceptAiProviders", input: options.acceptAiProviders }], caller);
|
|
3141
|
+
}
|
|
3142
|
+
if (options.providerVersion) {
|
|
3143
|
+
validateFunctionParams([{ paramName: "providerVersion", input: options.providerVersion, isString: true }], caller);
|
|
3144
|
+
}
|
|
3145
|
+
if (options.log) {
|
|
3146
|
+
validateFunctionParams([{ paramName: "log", input: options.log }], caller);
|
|
3147
|
+
}
|
|
3148
|
+
if (options.useAppClip) {
|
|
3149
|
+
validateFunctionParams([{ paramName: "useAppClip", input: options.useAppClip }], caller);
|
|
3150
|
+
}
|
|
3151
|
+
if (options.device) {
|
|
3152
|
+
validateFunctionParams([{ paramName: "device", input: options.device, isString: true }], caller);
|
|
3153
|
+
}
|
|
3154
|
+
if (options.useBrowserExtension) {
|
|
3155
|
+
validateFunctionParams([{ paramName: "useBrowserExtension", input: options.useBrowserExtension }], caller);
|
|
3156
|
+
}
|
|
3157
|
+
if (options.extensionID) {
|
|
3158
|
+
validateFunctionParams([{ paramName: "extensionID", input: options.extensionID, isString: true }], caller);
|
|
3159
|
+
}
|
|
3160
|
+
if (options.envUrl) {
|
|
3161
|
+
validateFunctionParams([{ paramName: "envUrl", input: options.envUrl, isString: true }], caller);
|
|
3162
|
+
}
|
|
3163
|
+
if (options.portalUrl) {
|
|
3164
|
+
validateFunctionParams([{ paramName: "portalUrl", input: options.portalUrl, isString: true }], caller);
|
|
3165
|
+
}
|
|
3166
|
+
if (options.customSharePageUrl) {
|
|
3167
|
+
validateFunctionParams([{ paramName: "customSharePageUrl", input: options.customSharePageUrl, isString: true }], caller);
|
|
3168
|
+
}
|
|
3169
|
+
if (options.customAppClipUrl) {
|
|
3170
|
+
validateFunctionParams([{ paramName: "customAppClipUrl", input: options.customAppClipUrl, isString: true }], caller);
|
|
3171
|
+
}
|
|
3172
|
+
if (options.preferredLocale) {
|
|
3173
|
+
validateFunctionParams([{ paramName: "preferredLocale", input: options.preferredLocale, isString: true }], caller);
|
|
3174
|
+
validateFunctionParamsWithFn({
|
|
3175
|
+
paramName: "preferredLocale",
|
|
3176
|
+
input: options.preferredLocale,
|
|
3177
|
+
isValid: () => {
|
|
3178
|
+
try {
|
|
3179
|
+
Intl.getCanonicalLocales(options.preferredLocale);
|
|
3180
|
+
return true;
|
|
3181
|
+
} catch (error) {
|
|
3182
|
+
logger11.info("Failed to canonicalize locale", error);
|
|
3183
|
+
return false;
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
}, caller);
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
2858
3189
|
// Private helper methods
|
|
2859
3190
|
setSignature(signature) {
|
|
2860
3191
|
try {
|
|
2861
3192
|
validateFunctionParams([{ input: signature, paramName: "signature", isString: true }], "setSignature");
|
|
2862
3193
|
this.signature = signature;
|
|
2863
|
-
|
|
3194
|
+
logger11.info(`Signature set successfully for applicationId: ${this.applicationId}`);
|
|
2864
3195
|
} catch (error) {
|
|
2865
|
-
|
|
3196
|
+
logger11.info("Error setting signature", error);
|
|
2866
3197
|
throw new SetSignatureError("Error setting signature", error);
|
|
2867
3198
|
}
|
|
2868
3199
|
}
|
|
2869
3200
|
generateSignature(applicationSecret) {
|
|
2870
3201
|
return __async(this, null, function* () {
|
|
2871
3202
|
try {
|
|
2872
|
-
const wallet = new
|
|
3203
|
+
const wallet = new import_ethers7.ethers.Wallet(applicationSecret);
|
|
2873
3204
|
const canonicalData = (0, import_canonicalize3.default)({ providerId: this.providerId, timestamp: this.timeStamp });
|
|
2874
3205
|
if (!canonicalData) {
|
|
2875
3206
|
throw new SignatureGeneratingError("Failed to canonicalize data for signing.");
|
|
2876
3207
|
}
|
|
2877
|
-
const messageHash =
|
|
2878
|
-
return yield wallet.signMessage(
|
|
3208
|
+
const messageHash = import_ethers7.ethers.keccak256(new TextEncoder().encode(canonicalData));
|
|
3209
|
+
return yield wallet.signMessage(import_ethers7.ethers.getBytes(messageHash));
|
|
2879
3210
|
} catch (err) {
|
|
2880
|
-
|
|
3211
|
+
logger11.info(`Error generating proof request for applicationId: ${this.applicationId}, providerId: ${this.providerId}, timeStamp: ${this.timeStamp}`);
|
|
2881
3212
|
throw new SignatureGeneratingError(`Error generating signature for applicationId: ${this.applicationId}`);
|
|
2882
3213
|
}
|
|
2883
3214
|
});
|
|
@@ -2918,7 +3249,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2918
3249
|
return __async(this, null, function* () {
|
|
2919
3250
|
const newTab = preOpenedTab != null ? preOpenedTab : window.open("about:blank", "_blank");
|
|
2920
3251
|
const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
|
|
2921
|
-
|
|
3252
|
+
logger11.info("Opening portal in new tab: " + link);
|
|
2922
3253
|
if (newTab) {
|
|
2923
3254
|
this.portalTab = newTab;
|
|
2924
3255
|
newTab.location = link;
|
|
@@ -2948,7 +3279,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
2948
3279
|
let link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
|
|
2949
3280
|
const separator = link.includes("?") ? "&" : "?";
|
|
2950
3281
|
link = `${link}${separator}embedded=true`;
|
|
2951
|
-
|
|
3282
|
+
logger11.info("Embedding portal in iframe: " + link);
|
|
2952
3283
|
this.closeEmbeddedFlow();
|
|
2953
3284
|
const iframe = document.createElement("iframe");
|
|
2954
3285
|
iframe.src = link;
|
|
@@ -3060,7 +3391,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3060
3391
|
var _a, _b, _c;
|
|
3061
3392
|
const options = __spreadValues(__spreadValues({}, (_a = this.options) == null ? void 0 : _a.launchOptions), launchOptions);
|
|
3062
3393
|
const mode = (_b = options.verificationMode) != null ? _b : "portal";
|
|
3063
|
-
|
|
3394
|
+
logger11.info("Creating Request Url");
|
|
3064
3395
|
if (!this.signature) {
|
|
3065
3396
|
throw new SignatureNotFoundError("Signature is not set.");
|
|
3066
3397
|
}
|
|
@@ -3071,18 +3402,18 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3071
3402
|
const template = this.encodeTemplateData(templateData);
|
|
3072
3403
|
if (((_c = this.options) == null ? void 0 : _c.useAppClip) && getDeviceType() === "mobile" /* MOBILE */ && getMobileDeviceType() === "ios" /* IOS */) {
|
|
3073
3404
|
const appClipUrl = this.customAppClipUrl ? `${this.customAppClipUrl}&template=${template}` : `https://appclip.apple.com/id?p=org.reclaimprotocol.app.clip&template=${template}`;
|
|
3074
|
-
|
|
3405
|
+
logger11.info("App Clip Url created successfully: " + appClipUrl);
|
|
3075
3406
|
return appClipUrl;
|
|
3076
3407
|
}
|
|
3077
3408
|
const sharePageUrl = yield createLinkWithTemplateData(templateData, this.appSharePageUrl);
|
|
3078
|
-
|
|
3409
|
+
logger11.info("Share page Url created successfully: " + sharePageUrl);
|
|
3079
3410
|
return sharePageUrl;
|
|
3080
3411
|
}
|
|
3081
3412
|
const link = yield createLinkWithTemplateData(templateData, this.customSharePageUrl);
|
|
3082
|
-
|
|
3413
|
+
logger11.info("Request Url created successfully: " + link);
|
|
3083
3414
|
return link;
|
|
3084
3415
|
} catch (error) {
|
|
3085
|
-
|
|
3416
|
+
logger11.info("Error creating Request Url:", error);
|
|
3086
3417
|
throw error;
|
|
3087
3418
|
}
|
|
3088
3419
|
});
|
|
@@ -3141,11 +3472,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3141
3472
|
try {
|
|
3142
3473
|
const templateData = this.getTemplateData();
|
|
3143
3474
|
this.templateData = templateData;
|
|
3144
|
-
|
|
3475
|
+
logger11.info(`Triggering Reclaim flow (mode: ${mode})`);
|
|
3145
3476
|
const deviceType = getDeviceType();
|
|
3146
3477
|
updateSession(this.sessionId, "SESSION_STARTED" /* SESSION_STARTED */);
|
|
3147
3478
|
if (launchOptions && "target" in launchOptions && !launchOptions.target) {
|
|
3148
|
-
|
|
3479
|
+
logger11.warn("triggerReclaimFlow: target was provided but is null/undefined \u2014 falling back to default flow. Ensure the element exists in the DOM.");
|
|
3149
3480
|
}
|
|
3150
3481
|
if ((launchOptions == null ? void 0 : launchOptions.target) && mode === "portal") {
|
|
3151
3482
|
yield this.embedPortalIframe(templateData, launchOptions.target);
|
|
@@ -3158,7 +3489,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3158
3489
|
if ((_c = this.options) == null ? void 0 : _c.useBrowserExtension) {
|
|
3159
3490
|
const extensionAvailable = yield this.isBrowserExtensionAvailable();
|
|
3160
3491
|
if (extensionAvailable) {
|
|
3161
|
-
|
|
3492
|
+
logger11.info("Triggering browser extension flow");
|
|
3162
3493
|
this.triggerBrowserExtensionFlow();
|
|
3163
3494
|
return {
|
|
3164
3495
|
close: () => {
|
|
@@ -3170,16 +3501,16 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3170
3501
|
if (mode === "portal") {
|
|
3171
3502
|
yield this.openPortalTab(templateData);
|
|
3172
3503
|
} else {
|
|
3173
|
-
|
|
3504
|
+
logger11.info("Showing QR code modal with share page URL");
|
|
3174
3505
|
yield this.showQRCodeModal();
|
|
3175
3506
|
}
|
|
3176
3507
|
} else if (deviceType === "mobile" /* MOBILE */) {
|
|
3177
3508
|
if (mode === "app") {
|
|
3178
3509
|
if (((_d = this.options) == null ? void 0 : _d.useAppClip) && getMobileDeviceType() === "ios" /* IOS */) {
|
|
3179
|
-
|
|
3510
|
+
logger11.info("Redirecting to iOS app clip");
|
|
3180
3511
|
this.redirectToAppClip();
|
|
3181
3512
|
} else {
|
|
3182
|
-
|
|
3513
|
+
logger11.info("Redirecting to share page");
|
|
3183
3514
|
yield this.redirectToInstantApp(options);
|
|
3184
3515
|
}
|
|
3185
3516
|
} else {
|
|
@@ -3196,7 +3527,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3196
3527
|
tab: (_e = this.portalTab) != null ? _e : void 0
|
|
3197
3528
|
};
|
|
3198
3529
|
} catch (error) {
|
|
3199
|
-
|
|
3530
|
+
logger11.info("Error triggering Reclaim flow:", error);
|
|
3200
3531
|
throw error;
|
|
3201
3532
|
}
|
|
3202
3533
|
});
|
|
@@ -3244,7 +3575,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3244
3575
|
window.postMessage(message, "*");
|
|
3245
3576
|
});
|
|
3246
3577
|
} catch (error) {
|
|
3247
|
-
|
|
3578
|
+
logger11.info("Error checking Reclaim extension installed:", error);
|
|
3248
3579
|
return false;
|
|
3249
3580
|
}
|
|
3250
3581
|
});
|
|
@@ -3257,7 +3588,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3257
3588
|
extensionID: this.extensionID
|
|
3258
3589
|
};
|
|
3259
3590
|
window.postMessage(message, "*");
|
|
3260
|
-
|
|
3591
|
+
logger11.info("Browser extension flow triggered");
|
|
3261
3592
|
}
|
|
3262
3593
|
showQRCodeModal() {
|
|
3263
3594
|
return __async(this, null, function* () {
|
|
@@ -3266,7 +3597,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3266
3597
|
this.modal = new QRCodeModal(this.modalOptions);
|
|
3267
3598
|
yield this.modal.show(requestUrl);
|
|
3268
3599
|
} catch (error) {
|
|
3269
|
-
|
|
3600
|
+
logger11.info("Error showing QR code modal:", error);
|
|
3270
3601
|
throw error;
|
|
3271
3602
|
}
|
|
3272
3603
|
});
|
|
@@ -3277,7 +3608,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3277
3608
|
try {
|
|
3278
3609
|
const template = this.encodeTemplateData(this.templateData);
|
|
3279
3610
|
let instantAppUrl = this.buildSharePageUrl(template);
|
|
3280
|
-
|
|
3611
|
+
logger11.info("Redirecting to Android instant app: " + instantAppUrl);
|
|
3281
3612
|
const isDeferredDeeplinksFlowEnabled = (_a = options.canUseDeferredDeepLinksFlow) != null ? _a : false;
|
|
3282
3613
|
if (isDeferredDeeplinksFlowEnabled) {
|
|
3283
3614
|
instantAppUrl = instantAppUrl.replace("/verifier", "/link");
|
|
@@ -3327,7 +3658,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3327
3658
|
}
|
|
3328
3659
|
window.location.href = instantAppUrl;
|
|
3329
3660
|
} catch (error) {
|
|
3330
|
-
|
|
3661
|
+
logger11.info("Error redirecting to instant app:", error);
|
|
3331
3662
|
throw error;
|
|
3332
3663
|
}
|
|
3333
3664
|
});
|
|
@@ -3336,14 +3667,14 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3336
3667
|
try {
|
|
3337
3668
|
const template = this.encodeTemplateData(this.templateData);
|
|
3338
3669
|
const appClipUrl = this.customAppClipUrl ? `${this.customAppClipUrl}&template=${template}` : `https://appclip.apple.com/id?p=org.reclaimprotocol.app.clip&template=${template}`;
|
|
3339
|
-
|
|
3670
|
+
logger11.info("Redirecting to iOS app clip: " + appClipUrl);
|
|
3340
3671
|
const verifierUrl = `${this.appSharePageUrl}/?template=${template}`;
|
|
3341
3672
|
window.location.href = appClipUrl;
|
|
3342
3673
|
setTimeout(() => {
|
|
3343
3674
|
window.location.href = verifierUrl;
|
|
3344
3675
|
}, 5 * 1e3);
|
|
3345
3676
|
} catch (error) {
|
|
3346
|
-
|
|
3677
|
+
logger11.info("Error redirecting to app clip:", error);
|
|
3347
3678
|
throw error;
|
|
3348
3679
|
}
|
|
3349
3680
|
}
|
|
@@ -3424,13 +3755,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3424
3755
|
return __async(this, arguments, function* ({ onSuccess, onError, verificationConfig }) {
|
|
3425
3756
|
if (!this.sessionId) {
|
|
3426
3757
|
const message = "Session can't be started due to undefined value of sessionId";
|
|
3427
|
-
|
|
3758
|
+
logger11.info(message);
|
|
3428
3759
|
throw new SessionNotStartedError(message);
|
|
3429
3760
|
}
|
|
3430
|
-
|
|
3761
|
+
logger11.info("Starting session");
|
|
3431
3762
|
const sessionUpdatePollingInterval = 3 * 1e3;
|
|
3432
3763
|
const interval = setInterval(() => __async(this, null, function* () {
|
|
3433
|
-
var _a, _b, _c, _d, _e;
|
|
3764
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3434
3765
|
try {
|
|
3435
3766
|
const statusUrlResponse = yield fetchStatusUrl(this.sessionId);
|
|
3436
3767
|
if (!statusUrlResponse.session) return;
|
|
@@ -3455,9 +3786,15 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3455
3786
|
if (statusUrlResponse.session.proofs && statusUrlResponse.session.proofs.length > 0) {
|
|
3456
3787
|
const proofs = statusUrlResponse.session.proofs;
|
|
3457
3788
|
if (this.claimCreationType === "createClaim" /* STANDALONE */) {
|
|
3458
|
-
const
|
|
3789
|
+
const sessionProviderVersion = statusUrlResponse.session.providerVersionString;
|
|
3790
|
+
const effectiveConfig = verificationConfig != null ? verificationConfig : {
|
|
3791
|
+
providerId: this.providerId,
|
|
3792
|
+
providerVersion: sessionProviderVersion || this.resolvedProviderVersion || "",
|
|
3793
|
+
allowedTags: ((_b = this.options) == null ? void 0 : _b.acceptAiProviders) ? ["ai"] : []
|
|
3794
|
+
};
|
|
3795
|
+
const result = yield verifyProof(proofs, effectiveConfig);
|
|
3459
3796
|
if (!result.isVerified) {
|
|
3460
|
-
|
|
3797
|
+
logger11.info(`Proofs not verified: count=${proofs == null ? void 0 : proofs.length}`);
|
|
3461
3798
|
throw new ProofNotVerifiedError(`Proofs not verified: count=${proofs == null ? void 0 : proofs.length}`, result.error);
|
|
3462
3799
|
}
|
|
3463
3800
|
}
|
|
@@ -3467,13 +3804,13 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3467
3804
|
onSuccess(proofs);
|
|
3468
3805
|
}
|
|
3469
3806
|
this.clearInterval();
|
|
3470
|
-
(
|
|
3807
|
+
(_c = this.modal) == null ? void 0 : _c.close();
|
|
3471
3808
|
this.closePortalTab();
|
|
3472
3809
|
this.closeEmbeddedFlow();
|
|
3473
3810
|
}
|
|
3474
3811
|
} else {
|
|
3475
3812
|
if (statusUrlResponse.session.statusV2 === "PROOF_SUBMISSION_FAILED" /* PROOF_SUBMISSION_FAILED */) {
|
|
3476
|
-
const errorMessage = ((
|
|
3813
|
+
const errorMessage = ((_d = statusUrlResponse.session.error) == null ? void 0 : _d.message) || "Proof submission failed";
|
|
3477
3814
|
throw new ProofSubmissionFailedError(errorMessage);
|
|
3478
3815
|
}
|
|
3479
3816
|
if (statusUrlResponse.session.statusV2 === "PROOF_SUBMITTED" /* PROOF_SUBMITTED */ || statusUrlResponse.session.statusV2 === "AI_PROOF_SUBMITTED" /* AI_PROOF_SUBMITTED */) {
|
|
@@ -3481,7 +3818,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3481
3818
|
onSuccess([]);
|
|
3482
3819
|
}
|
|
3483
3820
|
this.clearInterval();
|
|
3484
|
-
(
|
|
3821
|
+
(_e = this.modal) == null ? void 0 : _e.close();
|
|
3485
3822
|
this.closePortalTab();
|
|
3486
3823
|
this.closeEmbeddedFlow();
|
|
3487
3824
|
}
|
|
@@ -3491,7 +3828,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3491
3828
|
onError(e);
|
|
3492
3829
|
}
|
|
3493
3830
|
this.clearInterval();
|
|
3494
|
-
(
|
|
3831
|
+
(_f = this.modal) == null ? void 0 : _f.close();
|
|
3495
3832
|
this.closePortalTab();
|
|
3496
3833
|
this.closeEmbeddedFlow();
|
|
3497
3834
|
}
|
|
@@ -3515,7 +3852,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3515
3852
|
closeModal() {
|
|
3516
3853
|
if (this.modal) {
|
|
3517
3854
|
this.modal.close();
|
|
3518
|
-
|
|
3855
|
+
logger11.info("Modal closed by user");
|
|
3519
3856
|
}
|
|
3520
3857
|
}
|
|
3521
3858
|
/**
|
|
@@ -3533,6 +3870,33 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3533
3870
|
return this.jsonProofResponse;
|
|
3534
3871
|
}
|
|
3535
3872
|
};
|
|
3873
|
+
|
|
3874
|
+
// src/utils/signatureUtils.ts
|
|
3875
|
+
var import_ethers8 = require("ethers");
|
|
3876
|
+
var import_canonicalize4 = __toESM(require("canonicalize"));
|
|
3877
|
+
function generateInitSignature(appSecret, providerId, timestamp) {
|
|
3878
|
+
return __async(this, null, function* () {
|
|
3879
|
+
validateFunctionParams([
|
|
3880
|
+
{ input: appSecret, paramName: "appSecret", isString: true },
|
|
3881
|
+
{ input: providerId, paramName: "providerId", isString: true },
|
|
3882
|
+
{ input: timestamp, paramName: "timestamp", isString: true }
|
|
3883
|
+
], "generateInitSignature");
|
|
3884
|
+
try {
|
|
3885
|
+
const wallet = new import_ethers8.ethers.Wallet(appSecret);
|
|
3886
|
+
const canonicalData = (0, import_canonicalize4.default)({ providerId, timestamp });
|
|
3887
|
+
if (!canonicalData) {
|
|
3888
|
+
throw new SignatureGeneratingError("Failed to canonicalize data for signing.");
|
|
3889
|
+
}
|
|
3890
|
+
const messageHash = import_ethers8.ethers.keccak256(new TextEncoder().encode(canonicalData));
|
|
3891
|
+
return yield wallet.signMessage(import_ethers8.ethers.getBytes(messageHash));
|
|
3892
|
+
} catch (err) {
|
|
3893
|
+
throw new SignatureGeneratingError(
|
|
3894
|
+
`Error generating init signature for providerId: ${providerId}`,
|
|
3895
|
+
err
|
|
3896
|
+
);
|
|
3897
|
+
}
|
|
3898
|
+
});
|
|
3899
|
+
}
|
|
3536
3900
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3537
3901
|
0 && (module.exports = {
|
|
3538
3902
|
ReclaimProofRequest,
|
|
@@ -3546,6 +3910,8 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3546
3910
|
fetchProviderConfigs,
|
|
3547
3911
|
fetchProviderHashRequirementsBy,
|
|
3548
3912
|
fetchStatusUrl,
|
|
3913
|
+
generateAttestationNonce,
|
|
3914
|
+
generateInitSignature,
|
|
3549
3915
|
generateSpecsFromRequestSpecTemplate,
|
|
3550
3916
|
getAttestors,
|
|
3551
3917
|
getDeviceType,
|
|
@@ -3568,6 +3934,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3568
3934
|
takeTemplateParametersFromProofs,
|
|
3569
3935
|
transformForOnchain,
|
|
3570
3936
|
updateSession,
|
|
3937
|
+
verifyAttestorTeeAttestation,
|
|
3571
3938
|
verifyProof,
|
|
3572
3939
|
verifyTeeAttestation
|
|
3573
3940
|
});
|