@reclaimprotocol/js-sdk 5.4.2-dev.0 → 5.6.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +53 -411
- package/dist/index.js +169 -163
- package/dist/index.js.map +1 -1
- package/package.json +2 -13
package/dist/index.js
CHANGED
|
@@ -84,20 +84,10 @@ 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.6.0-dev.0",
|
|
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",
|
|
91
|
-
exports: {
|
|
92
|
-
".": {
|
|
93
|
-
types: "./dist/index.d.ts",
|
|
94
|
-
default: "./dist/index.js"
|
|
95
|
-
},
|
|
96
|
-
"./internal": {
|
|
97
|
-
types: "./dist/internal.d.ts",
|
|
98
|
-
default: "./dist/internal.js"
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
91
|
keywords: [
|
|
102
92
|
"reclaim",
|
|
103
93
|
"protocol",
|
|
@@ -118,8 +108,7 @@ var require_package = __commonJS({
|
|
|
118
108
|
],
|
|
119
109
|
tsup: {
|
|
120
110
|
entry: [
|
|
121
|
-
"src/index.ts"
|
|
122
|
-
"src/internal.ts"
|
|
111
|
+
"src/index.ts"
|
|
123
112
|
],
|
|
124
113
|
splitting: false,
|
|
125
114
|
sourcemap: true,
|
|
@@ -203,40 +192,8 @@ var require_package = __commonJS({
|
|
|
203
192
|
// src/index.ts
|
|
204
193
|
var index_exports = {};
|
|
205
194
|
__export(index_exports, {
|
|
206
|
-
ApplicationError: () => ApplicationError,
|
|
207
|
-
AttestorTeeVerificationError: () => AttestorTeeVerificationError,
|
|
208
|
-
BackendServerError: () => BackendServerError,
|
|
209
|
-
CallbackUrlRequiredError: () => CallbackUrlRequiredError,
|
|
210
|
-
ErrorDuringVerificationError: () => ErrorDuringVerificationError,
|
|
211
|
-
GetAppCallbackUrlError: () => GetAppCallbackUrlError,
|
|
212
|
-
GetStatusUrlError: () => GetStatusUrlError,
|
|
213
|
-
HASH_MATCH_MULTIPLE_DEFAULT: () => HASH_MATCH_MULTIPLE_DEFAULT,
|
|
214
|
-
HASH_REQUIRED_DEFAULT: () => HASH_REQUIRED_DEFAULT,
|
|
215
|
-
InavlidParametersError: () => InavlidParametersError,
|
|
216
|
-
InitError: () => InitError,
|
|
217
|
-
InitSessionError: () => InitSessionError,
|
|
218
|
-
InvalidParamError: () => InvalidParamError,
|
|
219
|
-
InvalidRequestSpecError: () => InvalidRequestSpecError,
|
|
220
|
-
InvalidSignatureError: () => InvalidSignatureError,
|
|
221
|
-
NoProviderParamsError: () => NoProviderParamsError,
|
|
222
|
-
ProofNotValidatedError: () => ProofNotValidatedError,
|
|
223
|
-
ProofNotVerifiedError: () => ProofNotVerifiedError,
|
|
224
|
-
ProofSubmissionFailedError: () => ProofSubmissionFailedError,
|
|
225
|
-
ProviderConfigFetchError: () => ProviderConfigFetchError,
|
|
226
|
-
ProviderFailedError: () => ProviderFailedError,
|
|
227
|
-
ProviderNotFoundError: () => ProviderNotFoundError,
|
|
228
195
|
ReclaimProofRequest: () => ReclaimProofRequest,
|
|
229
|
-
SessionNotStartedError: () => SessionNotStartedError,
|
|
230
|
-
SetContextError: () => SetContextError,
|
|
231
|
-
SetParamsError: () => SetParamsError,
|
|
232
|
-
SetSignatureError: () => SetSignatureError,
|
|
233
|
-
SignatureGeneratingError: () => SignatureGeneratingError,
|
|
234
|
-
SignatureNotFoundError: () => SignatureNotFoundError,
|
|
235
|
-
StatusUrlError: () => StatusUrlError,
|
|
236
196
|
TeeVerificationError: () => TeeVerificationError,
|
|
237
|
-
TimeoutError: () => TimeoutError,
|
|
238
|
-
UnknownProofsNotValidatedError: () => UnknownProofsNotValidatedError,
|
|
239
|
-
UpdateSessionError: () => UpdateSessionError,
|
|
240
197
|
assertValidProofsByHash: () => assertValidProofsByHash,
|
|
241
198
|
assertValidateProof: () => assertValidateProof,
|
|
242
199
|
assertVerifiedProof: () => assertVerifiedProof,
|
|
@@ -251,7 +208,6 @@ __export(index_exports, {
|
|
|
251
208
|
generateSpecsFromRequestSpecTemplate: () => generateSpecsFromRequestSpecTemplate,
|
|
252
209
|
getAttestors: () => getAttestors,
|
|
253
210
|
getDeviceType: () => getDeviceType,
|
|
254
|
-
getHashFromProof: () => getHashFromProof,
|
|
255
211
|
getHttpProviderClaimParamsFromProof: () => getHttpProviderClaimParamsFromProof,
|
|
256
212
|
getIdentifierFromClaimInfo: () => getIdentifierFromClaimInfo,
|
|
257
213
|
getMobileDeviceType: () => getMobileDeviceType,
|
|
@@ -1548,9 +1504,6 @@ function generateAttestationNonce(appSecret, applicationId, sessionId, timestamp
|
|
|
1548
1504
|
return import_ethers4.ethers.keccak256(import_ethers4.ethers.toUtf8Bytes(noncePayload)).replace(/^0x/i, "");
|
|
1549
1505
|
}
|
|
1550
1506
|
|
|
1551
|
-
// src/utils/proofValidationUtils.ts
|
|
1552
|
-
var import_assert = __toESM(require("assert"));
|
|
1553
|
-
|
|
1554
1507
|
// src/utils/providerUtils.ts
|
|
1555
1508
|
var logger7 = logger_default.logger;
|
|
1556
1509
|
function fetchProviderHashRequirementsBy(providerId, exactProviderVersionString, allowedTags, proofs) {
|
|
@@ -1672,20 +1625,7 @@ function hashRequestSpec(request) {
|
|
|
1672
1625
|
var logger8 = logger_default.logger;
|
|
1673
1626
|
var HASH_REQUIRED_DEFAULT = true;
|
|
1674
1627
|
var HASH_MATCH_MULTIPLE_DEFAULT = true;
|
|
1675
|
-
function
|
|
1676
|
-
if ((piiConfig == null ? void 0 : piiConfig.hasNoPii) === true) {
|
|
1677
|
-
const contextObject = JSON.parse(proof.claimData.context);
|
|
1678
|
-
(0, import_assert.default)(contextObject, "Context must be present in proof's claimData");
|
|
1679
|
-
const providerHash = contextObject.providerHash;
|
|
1680
|
-
(0, import_assert.default)(providerHash, "Provider hash must be present in proof's claimData.context");
|
|
1681
|
-
return [providerHash];
|
|
1682
|
-
}
|
|
1683
|
-
const claimParams = getHttpProviderClaimParamsFromProof(proof);
|
|
1684
|
-
const computedHashesOfProof = hashProofClaimParams(claimParams);
|
|
1685
|
-
const proofHashes = Array.isArray(computedHashesOfProof) ? computedHashesOfProof.map((h) => h.toLowerCase().trim()) : [computedHashesOfProof.toLowerCase().trim()];
|
|
1686
|
-
return proofHashes;
|
|
1687
|
-
}
|
|
1688
|
-
function assertValidProofsByHash(proofs, config, piiConfig) {
|
|
1628
|
+
function assertValidProofsByHash(proofs, config) {
|
|
1689
1629
|
var _a, _b;
|
|
1690
1630
|
if (!config.hashes) {
|
|
1691
1631
|
throw new ProofNotValidatedError("No proof hash was provided for validation");
|
|
@@ -1693,7 +1633,9 @@ function assertValidProofsByHash(proofs, config, piiConfig) {
|
|
|
1693
1633
|
const unvalidatedProofHashByIndex = /* @__PURE__ */ new Map();
|
|
1694
1634
|
for (let i = 0; i < proofs.length; i++) {
|
|
1695
1635
|
const proof = proofs[i];
|
|
1696
|
-
const
|
|
1636
|
+
const claimParams = getHttpProviderClaimParamsFromProof(proof);
|
|
1637
|
+
const computedHashesOfProof = hashProofClaimParams(claimParams);
|
|
1638
|
+
const proofHashes = Array.isArray(computedHashesOfProof) ? computedHashesOfProof.map((h) => h.toLowerCase().trim()) : [computedHashesOfProof.toLowerCase().trim()];
|
|
1697
1639
|
unvalidatedProofHashByIndex.set(i, proofHashes);
|
|
1698
1640
|
}
|
|
1699
1641
|
for (const hashRequirement of config.hashes) {
|
|
@@ -1701,9 +1643,7 @@ function assertValidProofsByHash(proofs, config, piiConfig) {
|
|
|
1701
1643
|
const expectedHashes = Array.isArray(hashRequirement.value) ? hashRequirement.value.map((h) => h.toLowerCase().trim()) : [hashRequirement.value.toLowerCase().trim()];
|
|
1702
1644
|
const isRequired = (_a = hashRequirement.required) != null ? _a : HASH_REQUIRED_DEFAULT;
|
|
1703
1645
|
const canMatchMultiple = (_b = hashRequirement.multiple) != null ? _b : HASH_MATCH_MULTIPLE_DEFAULT;
|
|
1704
|
-
for (
|
|
1705
|
-
if (!unvalidatedProofHashByIndex.has(i)) continue;
|
|
1706
|
-
const proofHashes = unvalidatedProofHashByIndex.get(i);
|
|
1646
|
+
for (const [i, proofHashes] of unvalidatedProofHashByIndex.entries()) {
|
|
1707
1647
|
const intersection = expectedHashes.filter((eh) => proofHashes.includes(eh));
|
|
1708
1648
|
if (intersection.length > 0) {
|
|
1709
1649
|
unvalidatedProofHashByIndex.delete(i);
|
|
@@ -1744,7 +1684,7 @@ function getHttpProviderClaimParamsFromProof(proof) {
|
|
|
1744
1684
|
}
|
|
1745
1685
|
throw new ProofNotValidatedError("Proof has no HTTP provider params to hash");
|
|
1746
1686
|
}
|
|
1747
|
-
function assertValidateProof(proofs, config
|
|
1687
|
+
function assertValidateProof(proofs, config) {
|
|
1748
1688
|
return __async(this, null, function* () {
|
|
1749
1689
|
if ("dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
|
|
1750
1690
|
logger8.warn("Validation skipped because it was disabled during proof verification");
|
|
@@ -1765,14 +1705,14 @@ function assertValidateProof(proofs, config, piiConfig) {
|
|
|
1765
1705
|
let lastError = null;
|
|
1766
1706
|
for (const hashRequirement of hashRequirementsFromProvider) {
|
|
1767
1707
|
try {
|
|
1768
|
-
return yield assertValidateProof(proofs, hashRequirement
|
|
1708
|
+
return yield assertValidateProof(proofs, hashRequirement);
|
|
1769
1709
|
} catch (e) {
|
|
1770
1710
|
lastError = e;
|
|
1771
1711
|
}
|
|
1772
1712
|
}
|
|
1773
1713
|
throw new ProofNotValidatedError("Could not validate proof", lastError);
|
|
1774
1714
|
} else {
|
|
1775
|
-
return assertValidateProof(proofs, hashRequirementsFromProvider[0]
|
|
1715
|
+
return assertValidateProof(proofs, hashRequirementsFromProvider[0]);
|
|
1776
1716
|
}
|
|
1777
1717
|
}
|
|
1778
1718
|
const effectiveHashRequirement = ("hashes" in config && Array.isArray(config == null ? void 0 : config.hashes) ? config.hashes : []).map((it) => {
|
|
@@ -1784,13 +1724,9 @@ function assertValidateProof(proofs, config, piiConfig) {
|
|
|
1784
1724
|
return it;
|
|
1785
1725
|
}
|
|
1786
1726
|
});
|
|
1787
|
-
return assertValidProofsByHash(
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
hashes: effectiveHashRequirement
|
|
1791
|
-
},
|
|
1792
|
-
piiConfig
|
|
1793
|
-
);
|
|
1727
|
+
return assertValidProofsByHash(proofs, {
|
|
1728
|
+
hashes: effectiveHashRequirement
|
|
1729
|
+
});
|
|
1794
1730
|
});
|
|
1795
1731
|
}
|
|
1796
1732
|
|
|
@@ -1804,7 +1740,7 @@ var SUPPORTED_PROOF_VERSIONS = ["v2", "v3"];
|
|
|
1804
1740
|
var TOKEN_CLOCK_SKEW_S = 60;
|
|
1805
1741
|
var NONCE_TIMESTAMP_MAX_SKEW_MS = 10 * 60 * 1e3;
|
|
1806
1742
|
var BROWSER_ENVIRONMENT_ERROR = "TEE attestation verification is only supported in non-browser environments. Run verifyTeeAttestation on your server or API route.";
|
|
1807
|
-
function
|
|
1743
|
+
function assert(condition, message) {
|
|
1808
1744
|
if (!condition) {
|
|
1809
1745
|
throw new Error(message);
|
|
1810
1746
|
}
|
|
@@ -1854,7 +1790,7 @@ function decodeUtf8(bytes) {
|
|
|
1854
1790
|
}
|
|
1855
1791
|
function decodeJwt(token) {
|
|
1856
1792
|
const parts = token.split(".");
|
|
1857
|
-
|
|
1793
|
+
assert(parts.length === 3, "attestation token is not a JWT");
|
|
1858
1794
|
return {
|
|
1859
1795
|
header: JSON.parse(decodeUtf8(decodeBase64Url(parts[0]))),
|
|
1860
1796
|
payload: JSON.parse(decodeUtf8(decodeBase64Url(parts[1]))),
|
|
@@ -1864,7 +1800,7 @@ function decodeJwt(token) {
|
|
|
1864
1800
|
}
|
|
1865
1801
|
function getFetch() {
|
|
1866
1802
|
const fetchFn = globalThis.fetch;
|
|
1867
|
-
|
|
1803
|
+
assert(fetchFn, "fetch is not available in this environment");
|
|
1868
1804
|
return fetchFn.bind(globalThis);
|
|
1869
1805
|
}
|
|
1870
1806
|
function getSubtleCrypto() {
|
|
@@ -1900,19 +1836,19 @@ var cachedJwksAt = 0;
|
|
|
1900
1836
|
function verifyJwtSignature(token, issuer) {
|
|
1901
1837
|
return __async(this, null, function* () {
|
|
1902
1838
|
const { header, payload, signingInput, signature } = decodeJwt(token);
|
|
1903
|
-
|
|
1904
|
-
|
|
1839
|
+
assert(header.alg === "RS256", `unexpected attestation signing algorithm: ${header.alg}`);
|
|
1840
|
+
assert(typeof header.kid === "string" && header.kid.length > 0, "attestation token kid is missing");
|
|
1905
1841
|
const isCacheFresh = cachedJwksKeys && Date.now() - cachedJwksAt < JWKS_CACHE_TTL_MS;
|
|
1906
1842
|
if (!isCacheFresh) {
|
|
1907
1843
|
const oidc = yield fetchJson(`${issuer}/.well-known/openid-configuration`);
|
|
1908
|
-
|
|
1844
|
+
assert(typeof (oidc == null ? void 0 : oidc.jwks_uri) === "string" && oidc.jwks_uri.length > 0, "issuer JWKS URI is missing");
|
|
1909
1845
|
cachedJwksUri = oidc.jwks_uri;
|
|
1910
1846
|
const jwks = yield fetchJson(cachedJwksUri);
|
|
1911
1847
|
cachedJwksKeys = (jwks == null ? void 0 : jwks.keys) || [];
|
|
1912
1848
|
cachedJwksAt = Date.now();
|
|
1913
1849
|
}
|
|
1914
1850
|
const jwk = cachedJwksKeys.find((key) => key.kid === header.kid);
|
|
1915
|
-
|
|
1851
|
+
assert(jwk, `no JWKS key found for kid ${header.kid}`);
|
|
1916
1852
|
const cryptoKey = yield getSubtleCrypto().importKey(
|
|
1917
1853
|
"jwk",
|
|
1918
1854
|
jwk,
|
|
@@ -1926,7 +1862,7 @@ function verifyJwtSignature(token, issuer) {
|
|
|
1926
1862
|
signature,
|
|
1927
1863
|
new TextEncoder().encode(signingInput)
|
|
1928
1864
|
);
|
|
1929
|
-
|
|
1865
|
+
assert(isValid, "JWT signature verification failed");
|
|
1930
1866
|
return payload;
|
|
1931
1867
|
});
|
|
1932
1868
|
}
|
|
@@ -1947,16 +1883,16 @@ function parseProofContext(proof) {
|
|
|
1947
1883
|
}
|
|
1948
1884
|
const ctx = parsedContext;
|
|
1949
1885
|
const expectedNonce = ctx.attestationNonce;
|
|
1950
|
-
|
|
1886
|
+
assert(typeof expectedNonce === "string" && expectedNonce.length > 0, "Proof context is missing attestationNonce");
|
|
1951
1887
|
const nonceDataObj = ctx.attestationNonceData;
|
|
1952
|
-
|
|
1888
|
+
assert(isNonceContextData(nonceDataObj), "Proof context is missing or has invalid attestationNonceData (requires applicationId, sessionId, timestamp)");
|
|
1953
1889
|
return { parsedContext: ctx, nonceDataObj, expectedNonce };
|
|
1954
1890
|
}
|
|
1955
1891
|
function verifyApplicationAndSessionBinding(proof, parsedContext, nonceDataObj, expectedApplicationId) {
|
|
1956
1892
|
var _a;
|
|
1957
1893
|
const { applicationId, sessionId, timestamp } = nonceDataObj;
|
|
1958
1894
|
if (expectedApplicationId) {
|
|
1959
|
-
|
|
1895
|
+
assert(
|
|
1960
1896
|
applicationId.toLowerCase() === expectedApplicationId.toLowerCase(),
|
|
1961
1897
|
`Application ID Mismatch! Expected ${expectedApplicationId}, but proof context contains ${applicationId}`
|
|
1962
1898
|
);
|
|
@@ -1991,11 +1927,11 @@ function verifyApplicationAndSessionBinding(proof, parsedContext, nonceDataObj,
|
|
|
1991
1927
|
function verifyNonceMaterial(expectedNonce, nonceDataObj, expectedAppSecret) {
|
|
1992
1928
|
const cleanExpectedNonce = normalizeHex(expectedNonce);
|
|
1993
1929
|
const { applicationId, sessionId, timestamp } = nonceDataObj;
|
|
1994
|
-
|
|
1995
|
-
|
|
1930
|
+
assert(cleanExpectedNonce.length > 0, "Proof context attestationNonce is empty");
|
|
1931
|
+
assert(isHex(cleanExpectedNonce), "Proof context attestationNonce is not valid hex");
|
|
1996
1932
|
if (expectedAppSecret) {
|
|
1997
1933
|
const recomputedNonce = generateAttestationNonce(expectedAppSecret, applicationId, sessionId, timestamp);
|
|
1998
|
-
|
|
1934
|
+
assert(
|
|
1999
1935
|
recomputedNonce === cleanExpectedNonce,
|
|
2000
1936
|
"Attestation nonce verification failed: app secret, application ID, session ID, or timestamp do not match"
|
|
2001
1937
|
);
|
|
@@ -2008,7 +1944,7 @@ function verifyNonceMaterial(expectedNonce, nonceDataObj, expectedAppSecret) {
|
|
|
2008
1944
|
nonceMsg,
|
|
2009
1945
|
expectedNonce.startsWith("0x") ? expectedNonce : `0x${expectedNonce}`
|
|
2010
1946
|
);
|
|
2011
|
-
|
|
1947
|
+
assert(
|
|
2012
1948
|
recoveredAddress.toLowerCase() === applicationId.toLowerCase(),
|
|
2013
1949
|
`Nonce signature verification failed: recovered ${recoveredAddress}, expected ${applicationId}`
|
|
2014
1950
|
);
|
|
@@ -2030,12 +1966,12 @@ function assertTokenFresh(claims) {
|
|
|
2030
1966
|
}
|
|
2031
1967
|
function assertAudienceClaim(aud) {
|
|
2032
1968
|
if (typeof aud === "string") {
|
|
2033
|
-
|
|
1969
|
+
assert(aud.length > 0, "attestation token audience is empty");
|
|
2034
1970
|
return;
|
|
2035
1971
|
}
|
|
2036
1972
|
if (Array.isArray(aud)) {
|
|
2037
|
-
|
|
2038
|
-
|
|
1973
|
+
assert(aud.length > 0, "attestation token audience is empty");
|
|
1974
|
+
assert(aud.every((entry) => typeof entry === "string" && entry.length > 0), "attestation token audience contains invalid entries");
|
|
2039
1975
|
return;
|
|
2040
1976
|
}
|
|
2041
1977
|
throw new Error("attestation token audience is missing");
|
|
@@ -2050,22 +1986,22 @@ function assertProofShape(teeAttestation) {
|
|
|
2050
1986
|
throw new Error(`${teeAttestation.error.code}: ${teeAttestation.error.message}`);
|
|
2051
1987
|
}
|
|
2052
1988
|
const proofVersion = getProofVersion(teeAttestation);
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
1989
|
+
assert(typeof proofVersion === "string" && SUPPORTED_PROOF_VERSIONS.includes(proofVersion), `unexpected proof version: ${proofVersion}`);
|
|
1990
|
+
assert(teeAttestation.tee_provider === EXPECTED_TEE_PROVIDER, `unexpected tee provider: ${teeAttestation.tee_provider}`);
|
|
1991
|
+
assert(teeAttestation.tee_technology === EXPECTED_TEE_TECHNOLOGY, `unexpected tee technology: ${teeAttestation.tee_technology}`);
|
|
1992
|
+
assert(typeof teeAttestation.nonce === "string" && teeAttestation.nonce.length > 0, "tee attestation nonce missing");
|
|
1993
|
+
assert(typeof teeAttestation.timestamp === "string" && teeAttestation.timestamp.length > 0, "tee attestation timestamp missing");
|
|
1994
|
+
assert(!Number.isNaN(Date.parse(teeAttestation.timestamp)), "tee attestation timestamp is invalid");
|
|
1995
|
+
assert(typeof ((_a = teeAttestation.workload) == null ? void 0 : _a.image_digest) === "string" && teeAttestation.workload.image_digest.length > 0, "workload image digest missing");
|
|
1996
|
+
assert(typeof ((_b = teeAttestation.verifier) == null ? void 0 : _b.image_digest) === "string" && teeAttestation.verifier.image_digest.length > 0, "verifier image digest missing");
|
|
1997
|
+
assert(typeof ((_c = teeAttestation.attestation) == null ? void 0 : _c.token) === "string" && teeAttestation.attestation.token.length > 0, "attestation token missing");
|
|
2062
1998
|
}
|
|
2063
1999
|
function computeDigestBinding(teeAttestation) {
|
|
2064
2000
|
return __async(this, null, function* () {
|
|
2065
2001
|
const proofVersion = getProofVersion(teeAttestation);
|
|
2066
2002
|
if (proofVersion === "v3") {
|
|
2067
|
-
|
|
2068
|
-
|
|
2003
|
+
assert(typeof teeAttestation.workload.container_name === "string" && teeAttestation.workload.container_name.length > 0, "workload container name missing");
|
|
2004
|
+
assert(typeof teeAttestation.verifier.container_name === "string" && teeAttestation.verifier.container_name.length > 0, "verifier container name missing");
|
|
2069
2005
|
return sha256Hex([
|
|
2070
2006
|
"v3",
|
|
2071
2007
|
`workload.container_name=${teeAttestation.workload.container_name}`,
|
|
@@ -2084,15 +2020,15 @@ function verifyGcpClaims(teeAttestation, expectedNonce) {
|
|
|
2084
2020
|
return __async(this, null, function* () {
|
|
2085
2021
|
var _a;
|
|
2086
2022
|
const claims = yield verifyJwtSignature(teeAttestation.attestation.token, GCP_CONFIDENTIAL_SPACE_ISSUER);
|
|
2087
|
-
|
|
2023
|
+
assert(claims.iss === GCP_CONFIDENTIAL_SPACE_ISSUER, `unexpected issuer: ${claims.iss}`);
|
|
2088
2024
|
assertAudienceClaim(claims.aud);
|
|
2089
|
-
|
|
2025
|
+
assert(Array.isArray(claims.eat_nonce), "eat_nonce claim missing");
|
|
2090
2026
|
const digestBinding = yield computeDigestBinding(teeAttestation);
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2027
|
+
assert(claims.eat_nonce.includes(expectedNonce), "request nonce is not present in attestation token");
|
|
2028
|
+
assert(claims.eat_nonce.includes(digestBinding), "digest-binding nonce is not present in attestation token");
|
|
2029
|
+
assert(claims.hwmodel === EXPECTED_HW_MODEL, `unexpected hwmodel: ${claims.hwmodel}`);
|
|
2030
|
+
assert(claims.secboot === true, "secure boot claim is not true");
|
|
2031
|
+
assert((_a = claims.submods) == null ? void 0 : _a.gce, "gce submod claim missing");
|
|
2096
2032
|
assertTokenFresh(claims);
|
|
2097
2033
|
});
|
|
2098
2034
|
}
|
|
@@ -2114,9 +2050,9 @@ function verifyTeeAttestation(proof, appSecret) {
|
|
|
2114
2050
|
verifyNonceMaterial(expectedNonce, nonceDataObj, appSecret);
|
|
2115
2051
|
const cleanExpectedNonce = normalizeHex(expectedNonce);
|
|
2116
2052
|
const cleanTeeNonce = normalizeHex(teeAttestation.nonce);
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2053
|
+
assert(cleanTeeNonce.length > 0, "TEE attestation nonce is empty");
|
|
2054
|
+
assert(isHex(cleanTeeNonce), "TEE attestation nonce is not valid hex");
|
|
2055
|
+
assert(cleanTeeNonce === cleanExpectedNonce, `Nonce Mismatch! Expected ${cleanExpectedNonce}, got ${cleanTeeNonce}`);
|
|
2120
2056
|
yield verifyGcpClaims(teeAttestation, cleanExpectedNonce);
|
|
2121
2057
|
return { isVerified: true };
|
|
2122
2058
|
} catch (error) {
|
|
@@ -2382,14 +2318,11 @@ function verifyProof(proofOrProofs, config) {
|
|
|
2382
2318
|
if (!config) {
|
|
2383
2319
|
throw new ProofNotValidatedError("Verification configuration is required for `verifyProof(proof, config)`");
|
|
2384
2320
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
for (const proof of proofs) {
|
|
2389
|
-
yield assertVerifiedProof(proof, attestors);
|
|
2390
|
-
}
|
|
2321
|
+
const attestors = yield getAttestors();
|
|
2322
|
+
for (const proof of proofs) {
|
|
2323
|
+
yield assertVerifiedProof(proof, attestors);
|
|
2391
2324
|
}
|
|
2392
|
-
yield assertValidateProof(proofs, config
|
|
2325
|
+
yield assertValidateProof(proofs, config);
|
|
2393
2326
|
let isTeeAttestationVerified;
|
|
2394
2327
|
let isAttestorTeeAttestationVerified;
|
|
2395
2328
|
if (config.teeAttestation && "dangerouslyDisableContentValidation" in config && config.dangerouslyDisableContentValidation) {
|
|
@@ -3309,8 +3242,8 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3309
3242
|
template = replaceAll(template, ")", "%29");
|
|
3310
3243
|
return template;
|
|
3311
3244
|
}
|
|
3312
|
-
buildSharePageUrl(template) {
|
|
3313
|
-
return `${this.appSharePageUrl}/?template=${template}`;
|
|
3245
|
+
buildSharePageUrl(template, url) {
|
|
3246
|
+
return `${url != null ? url : this.appSharePageUrl}/?template=${template}`;
|
|
3314
3247
|
}
|
|
3315
3248
|
openPortalTab(templateData, preOpenedTab) {
|
|
3316
3249
|
return __async(this, null, function* () {
|
|
@@ -3378,6 +3311,49 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3378
3311
|
}
|
|
3379
3312
|
this.clearInterval();
|
|
3380
3313
|
}
|
|
3314
|
+
/**
|
|
3315
|
+
* Cancels an in-progress verification session.
|
|
3316
|
+
*
|
|
3317
|
+
* Use this when the user abandons the flow (e.g. navigates back) before a
|
|
3318
|
+
* proof is produced. It tears down all local session machinery — the status
|
|
3319
|
+
* polling interval, the 10-minute interval-ending timeout, and any portal UI
|
|
3320
|
+
* (modal / tab / embedded iframe) — and marks the session CANCELLED on the
|
|
3321
|
+
* backend.
|
|
3322
|
+
*
|
|
3323
|
+
* Marking the session CANCELLED is what prevents a stale, abandoned session
|
|
3324
|
+
* from later being reported as a failure: the portal's inactivity monitor
|
|
3325
|
+
* treats a cancelled session as a clean terminal state and will not emit a
|
|
3326
|
+
* connection-failure error to the cancel/error callback. Because that callback
|
|
3327
|
+
* URL is typically shared across sessions, suppressing it here stops an
|
|
3328
|
+
* abandoned session from contaminating the next one.
|
|
3329
|
+
*
|
|
3330
|
+
* `onSuccess` / `onError` are intentionally NOT invoked — cancellation is a
|
|
3331
|
+
* deliberate, silent teardown, not a verification outcome. Safe to call more
|
|
3332
|
+
* than once; a no-op when no session is active.
|
|
3333
|
+
*
|
|
3334
|
+
* @example
|
|
3335
|
+
* ```typescript
|
|
3336
|
+
* // e.g. in a React effect cleanup when the user navigates away
|
|
3337
|
+
* await proofRequest.cancelSession();
|
|
3338
|
+
* ```
|
|
3339
|
+
*/
|
|
3340
|
+
cancelSession() {
|
|
3341
|
+
return __async(this, null, function* () {
|
|
3342
|
+
if (!this.sessionId) {
|
|
3343
|
+
return;
|
|
3344
|
+
}
|
|
3345
|
+
const sessionId = this.sessionId;
|
|
3346
|
+
logger11.info(`Cancelling session: ${sessionId}`);
|
|
3347
|
+
this.closeModal();
|
|
3348
|
+
this.closePortalTab();
|
|
3349
|
+
this.closeEmbeddedFlow();
|
|
3350
|
+
try {
|
|
3351
|
+
yield updateSession(sessionId, "SESSION_CANCELLED" /* SESSION_CANCELLED */);
|
|
3352
|
+
} catch (error) {
|
|
3353
|
+
logger11.info(`cancelSession: backend update failed for ${sessionId}: ${error}`);
|
|
3354
|
+
}
|
|
3355
|
+
});
|
|
3356
|
+
}
|
|
3381
3357
|
/**
|
|
3382
3358
|
* Exports the Reclaim proof verification request as a JSON string
|
|
3383
3359
|
*
|
|
@@ -3573,11 +3549,11 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3573
3549
|
}
|
|
3574
3550
|
} else if (deviceType === "mobile" /* MOBILE */) {
|
|
3575
3551
|
if (mode === "app") {
|
|
3576
|
-
if (((_d = this.options) == null ? void 0 : _d.useAppClip) && getMobileDeviceType() === "ios" /* IOS */) {
|
|
3577
|
-
logger11.info("Redirecting
|
|
3578
|
-
this.
|
|
3552
|
+
if ((((_d = this.options) == null ? void 0 : _d.useAppClip) || options.canUseDeferredDeepLinksFlow) && getMobileDeviceType() === "ios" /* IOS */) {
|
|
3553
|
+
logger11.info("Redirecting for iOS");
|
|
3554
|
+
yield this.redirectToiOSApp(options);
|
|
3579
3555
|
} else {
|
|
3580
|
-
logger11.info("Redirecting
|
|
3556
|
+
logger11.info("Redirecting for android");
|
|
3581
3557
|
yield this.redirectToInstantApp(options);
|
|
3582
3558
|
}
|
|
3583
3559
|
} else {
|
|
@@ -3676,7 +3652,7 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3676
3652
|
const template = this.encodeTemplateData(this.templateData);
|
|
3677
3653
|
let instantAppUrl = this.buildSharePageUrl(template);
|
|
3678
3654
|
logger11.info("Redirecting to Android instant app: " + instantAppUrl);
|
|
3679
|
-
const isDeferredDeeplinksFlowEnabled = (_a = options.canUseDeferredDeepLinksFlow) != null ? _a :
|
|
3655
|
+
const isDeferredDeeplinksFlowEnabled = (_a = options.canUseDeferredDeepLinksFlow) != null ? _a : true;
|
|
3680
3656
|
if (isDeferredDeeplinksFlowEnabled) {
|
|
3681
3657
|
instantAppUrl = instantAppUrl.replace("/verifier", "/link");
|
|
3682
3658
|
const deepLink = `intent://details?id=org.reclaimprotocol.app&url=${encodeURIComponent(
|
|
@@ -3745,6 +3721,69 @@ var ReclaimProofRequest = class _ReclaimProofRequest {
|
|
|
3745
3721
|
throw error;
|
|
3746
3722
|
}
|
|
3747
3723
|
}
|
|
3724
|
+
redirectToiOSApp(options) {
|
|
3725
|
+
return __async(this, null, function* () {
|
|
3726
|
+
var _a;
|
|
3727
|
+
try {
|
|
3728
|
+
logger11.info("Preparing to launch for iOS app: ", options);
|
|
3729
|
+
const isDeferredDeeplinksFlowEnabled = (_a = options.canUseDeferredDeepLinksFlow) != null ? _a : false;
|
|
3730
|
+
if (!isDeferredDeeplinksFlowEnabled) {
|
|
3731
|
+
return this.redirectToAppClip();
|
|
3732
|
+
}
|
|
3733
|
+
const template = this.encodeTemplateData(this.templateData);
|
|
3734
|
+
const defaultiOSDeepLinkUrlBase = "reclaimverifier://org.reclaimprotocol.app";
|
|
3735
|
+
const deepLink = this.buildSharePageUrl(
|
|
3736
|
+
template,
|
|
3737
|
+
options.iosDeepLinkBaseUrl || defaultiOSDeepLinkUrlBase
|
|
3738
|
+
);
|
|
3739
|
+
const iosAppInstallUrl = options.iosAppDownloadUrl || "itms-apps://apps.apple.com/in/app/reclaim-verifier/id6503247508";
|
|
3740
|
+
logger11.info("Redirecting to iOS app: " + deepLink, "or store: ", iosAppInstallUrl);
|
|
3741
|
+
try {
|
|
3742
|
+
window.navigator.clipboard.writeText(deepLink).catch(() => {
|
|
3743
|
+
console.error("We can't access the clipboard. Please copy this link and open Reclaim Verifier app.");
|
|
3744
|
+
});
|
|
3745
|
+
let appInstalled = false;
|
|
3746
|
+
let timeoutId;
|
|
3747
|
+
const iframe = document.createElement("iframe");
|
|
3748
|
+
iframe.style.display = "none";
|
|
3749
|
+
iframe.style.width = "1px";
|
|
3750
|
+
iframe.style.height = "1px";
|
|
3751
|
+
document.body.appendChild(iframe);
|
|
3752
|
+
const cleanup = () => {
|
|
3753
|
+
if (iframe.parentNode) {
|
|
3754
|
+
document.body.removeChild(iframe);
|
|
3755
|
+
}
|
|
3756
|
+
if (timeoutId) {
|
|
3757
|
+
clearTimeout(timeoutId);
|
|
3758
|
+
}
|
|
3759
|
+
};
|
|
3760
|
+
const onVisibilityChange = () => {
|
|
3761
|
+
if (document.hidden) {
|
|
3762
|
+
logger11.info("App maybe installed, document hidden");
|
|
3763
|
+
appInstalled = true;
|
|
3764
|
+
cleanup();
|
|
3765
|
+
window.location.href = deepLink;
|
|
3766
|
+
}
|
|
3767
|
+
};
|
|
3768
|
+
document.addEventListener("visibilitychange", onVisibilityChange, { once: true });
|
|
3769
|
+
iframe.src = deepLink;
|
|
3770
|
+
timeoutId = setTimeout(() => {
|
|
3771
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3772
|
+
cleanup();
|
|
3773
|
+
if (!appInstalled) {
|
|
3774
|
+
window.location.href = iosAppInstallUrl;
|
|
3775
|
+
}
|
|
3776
|
+
}, 1500);
|
|
3777
|
+
} catch (e) {
|
|
3778
|
+
console.error("something went wrong during launch, opening store", e);
|
|
3779
|
+
window.location.href = iosAppInstallUrl;
|
|
3780
|
+
}
|
|
3781
|
+
} catch (error) {
|
|
3782
|
+
logger11.info("Error redirecting to instant app:", error);
|
|
3783
|
+
throw error;
|
|
3784
|
+
}
|
|
3785
|
+
});
|
|
3786
|
+
}
|
|
3748
3787
|
/**
|
|
3749
3788
|
* Returns the provider id and exact version of the provider that was used in the verification session of this request.
|
|
3750
3789
|
*
|
|
@@ -3966,40 +4005,8 @@ function generateInitSignature(appSecret, providerId, timestamp) {
|
|
|
3966
4005
|
}
|
|
3967
4006
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3968
4007
|
0 && (module.exports = {
|
|
3969
|
-
ApplicationError,
|
|
3970
|
-
AttestorTeeVerificationError,
|
|
3971
|
-
BackendServerError,
|
|
3972
|
-
CallbackUrlRequiredError,
|
|
3973
|
-
ErrorDuringVerificationError,
|
|
3974
|
-
GetAppCallbackUrlError,
|
|
3975
|
-
GetStatusUrlError,
|
|
3976
|
-
HASH_MATCH_MULTIPLE_DEFAULT,
|
|
3977
|
-
HASH_REQUIRED_DEFAULT,
|
|
3978
|
-
InavlidParametersError,
|
|
3979
|
-
InitError,
|
|
3980
|
-
InitSessionError,
|
|
3981
|
-
InvalidParamError,
|
|
3982
|
-
InvalidRequestSpecError,
|
|
3983
|
-
InvalidSignatureError,
|
|
3984
|
-
NoProviderParamsError,
|
|
3985
|
-
ProofNotValidatedError,
|
|
3986
|
-
ProofNotVerifiedError,
|
|
3987
|
-
ProofSubmissionFailedError,
|
|
3988
|
-
ProviderConfigFetchError,
|
|
3989
|
-
ProviderFailedError,
|
|
3990
|
-
ProviderNotFoundError,
|
|
3991
4008
|
ReclaimProofRequest,
|
|
3992
|
-
SessionNotStartedError,
|
|
3993
|
-
SetContextError,
|
|
3994
|
-
SetParamsError,
|
|
3995
|
-
SetSignatureError,
|
|
3996
|
-
SignatureGeneratingError,
|
|
3997
|
-
SignatureNotFoundError,
|
|
3998
|
-
StatusUrlError,
|
|
3999
4009
|
TeeVerificationError,
|
|
4000
|
-
TimeoutError,
|
|
4001
|
-
UnknownProofsNotValidatedError,
|
|
4002
|
-
UpdateSessionError,
|
|
4003
4010
|
assertValidProofsByHash,
|
|
4004
4011
|
assertValidateProof,
|
|
4005
4012
|
assertVerifiedProof,
|
|
@@ -4014,7 +4021,6 @@ function generateInitSignature(appSecret, providerId, timestamp) {
|
|
|
4014
4021
|
generateSpecsFromRequestSpecTemplate,
|
|
4015
4022
|
getAttestors,
|
|
4016
4023
|
getDeviceType,
|
|
4017
|
-
getHashFromProof,
|
|
4018
4024
|
getHttpProviderClaimParamsFromProof,
|
|
4019
4025
|
getIdentifierFromClaimInfo,
|
|
4020
4026
|
getMobileDeviceType,
|