@zkproofport-app/sdk 0.5.0-beta.2 → 0.5.0-beta.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/dist/index.js CHANGED
@@ -126,8 +126,10 @@ const CIRCUIT_METADATA = {
126
126
  oidc_domain_attestation: {
127
127
  name: 'OIDC Domain',
128
128
  description: 'Prove email domain affiliation via OIDC JWT',
129
- publicInputsCount: 148,
130
- publicInputNames: ['pubkey_modulus_limbs', 'domain', 'scope', 'nullifier', 'provider'],
129
+ // v2: 148 v1 fields, then aud_hash (32), nonce_mode (1), nonce_binding
130
+ // (32), now (1). oidc-domain-attestation/src/main.nr.
131
+ publicInputsCount: 214,
132
+ publicInputNames: ['pubkey_modulus_limbs', 'domain', 'scope', 'nullifier', 'provider', 'aud_hash', 'nonce_mode', 'nonce_binding', 'now'],
131
133
  },
132
134
  // Planned circuit — the identifier is reserved and the circuit exists, but it
133
135
  // is not officially supported yet. See CIRCUIT_SUPPORT_STATUS in ./circuits.
@@ -1141,9 +1143,11 @@ async function fetchVerificationKey(circuit, timeoutMs) {
1141
1143
  * Needs no setup from the caller: the verifier ships with this SDK and is
1142
1144
  * loaded on first use.
1143
1145
  *
1144
- * For `oidc_domain_attestation` it first checks the proof's RSA key against the
1145
- * provider's published JWKS (core's `checkOidcProviderKey`); a key the provider
1146
- * does not publish, or a JWKS that cannot be fetched, is `{ valid: false }`.
1146
+ * For `oidc_domain_attestation` it first checks the token's audience, nonce and
1147
+ * time (core's `checkOidcPolicy`, against `options.request` when given) and the
1148
+ * proof's RSA key against the provider's published JWKS (core's
1149
+ * `checkOidcProviderKey`); any refusal, or a JWKS that cannot be fetched, is
1150
+ * `{ valid: false }`.
1147
1151
  *
1148
1152
  * @param circuit - Canonical circuit identifier
1149
1153
  * @param proof - Proof bytes as hex, WITHOUT public inputs (as the relay sends it)
@@ -1171,7 +1175,7 @@ async function verifyProofOffChain(circuit, proof, publicInputs, options = {}) {
1171
1175
  // their trust anchor as a public input the prover chooses. For OIDC that is
1172
1176
  // the RSA key -- see core's oidcProviderKeys. Checked here so a dApp that
1173
1177
  // verifies off-chain gets the same answer as one that verifies on-chain.
1174
- const issuer = await core.checkProofIssuer(circuit, publicInputs);
1178
+ const issuer = await core.checkProofIssuer(circuit, publicInputs, { request: options.request });
1175
1179
  if (!issuer.ok) {
1176
1180
  return { valid: false, error: issuer.error };
1177
1181
  }
@@ -1313,6 +1317,13 @@ class ProofportSDK {
1313
1317
  */
1314
1318
  constructor(config = {}) {
1315
1319
  this.pendingRequests = new Map();
1320
+ /**
1321
+ * requestId -> scope of the relay requests this instance created, so that
1322
+ * verifyResponse* can check an OIDC proof's request-bound nonce without the
1323
+ * dApp passing the request back in. Oldest entries go first past
1324
+ * {@link ProofportSDK.MAX_REMEMBERED_RELAY_REQUESTS}.
1325
+ */
1326
+ this.relayRequests = new Map();
1316
1327
  this.signer = null;
1317
1328
  this.socket = null;
1318
1329
  /**
@@ -1874,9 +1885,49 @@ class ProofportSDK {
1874
1885
  * }
1875
1886
  * ```
1876
1887
  */
1877
- async verifyOnChain(circuit, proof, publicInputs, providerOrSigner) {
1888
+ async verifyOnChain(circuit, proof, publicInputs, providerOrSigner, options = {}) {
1878
1889
  const parsedProof = core.parseProofForOnChain(proof, publicInputs, publicInputs.length);
1879
- return core.verifyProofOnChain(circuit, parsedProof, providerOrSigner, this.verifierTarget(circuit));
1890
+ return core.verifyProofOnChain(circuit, parsedProof, providerOrSigner, this.verifierTarget(circuit), undefined, {
1891
+ request: options.request,
1892
+ });
1893
+ }
1894
+ /**
1895
+ * The request an `oidc_domain_attestation` response answers: the one the
1896
+ * caller passed, else the relay request this instance created under the
1897
+ * response's requestId. `{ error }` when there is none, or when the two
1898
+ * disagree -- an OIDC proof made with a request-bound nonce is only
1899
+ * meaningful against the request it was bound to, so a response this SDK
1900
+ * cannot place is refused rather than checked without it.
1901
+ */
1902
+ oidcRequestFor(response, explicit) {
1903
+ if (explicit !== undefined) {
1904
+ if (explicit === null || typeof explicit !== 'object' || explicit.requestId !== response.requestId) {
1905
+ return {
1906
+ error: `The request passed in (${JSON.stringify(explicit?.requestId)}) is not the one this response answers (${JSON.stringify(response.requestId)}).`,
1907
+ };
1908
+ }
1909
+ return { request: explicit };
1910
+ }
1911
+ const remembered = this.relayRequests.get(response.requestId);
1912
+ if (!remembered) {
1913
+ return {
1914
+ error: `No request ${JSON.stringify(response.requestId)} was created by this SDK instance, so the OIDC proof's ` +
1915
+ 'nonce cannot be checked against it. Pass { request: { scope, requestId } } -- the scope and relay ' +
1916
+ 'requestId of the request you created.',
1917
+ };
1918
+ }
1919
+ return { request: remembered };
1920
+ }
1921
+ /** @internal Remember a relay request's scope for verifyResponse*. */
1922
+ rememberRelayRequest(requestId, scope) {
1923
+ if (typeof requestId !== 'string' || typeof scope !== 'string')
1924
+ return;
1925
+ this.relayRequests.delete(requestId);
1926
+ this.relayRequests.set(requestId, { scope, requestId });
1927
+ while (this.relayRequests.size > ProofportSDK.MAX_REMEMBERED_RELAY_REQUESTS) {
1928
+ const oldest = this.relayRequests.keys().next().value;
1929
+ this.relayRequests.delete(oldest);
1930
+ }
1880
1931
  }
1881
1932
  /**
1882
1933
  * The verifier for a circuit: the one the dApp configured, otherwise the
@@ -1903,6 +1954,9 @@ class ProofportSDK {
1903
1954
  *
1904
1955
  * @param response - ProofResponse object from parseResponse()
1905
1956
  * @param providerOrSigner - ethers v6 Provider or Signer (defaults to base mainnet public RPC)
1957
+ * @param options.request - For `oidc_domain_attestation`: the `{ scope, requestId }`
1958
+ * the response answers. Not needed for a relay request this SDK instance
1959
+ * created; an OIDC response this instance cannot place is refused without it.
1906
1960
  *
1907
1961
  * @returns Promise resolving to verification result with valid boolean and optional error message
1908
1962
  *
@@ -1929,10 +1983,17 @@ class ProofportSDK {
1929
1983
  * });
1930
1984
  * ```
1931
1985
  */
1932
- async verifyResponseOnChain(response, providerOrSigner) {
1986
+ async verifyResponseOnChain(response, providerOrSigner, options = {}) {
1933
1987
  if (response.status !== 'completed' || !response.proof || !response.publicInputs) {
1934
1988
  return { valid: false, error: 'Invalid or incomplete response' };
1935
1989
  }
1990
+ let request;
1991
+ if (response.circuit === 'oidc_domain_attestation') {
1992
+ const found = this.oidcRequestFor(response, options.request);
1993
+ if ('error' in found)
1994
+ return { valid: false, error: found.error };
1995
+ request = found.request;
1996
+ }
1936
1997
  const parsedProof = core.parseProofForOnChain(response.proof, response.publicInputs, response.publicInputs.length);
1937
1998
  // The response's verifierAddress and chainId are a claim to check, never
1938
1999
  // the contract to call: whoever wrote the response would otherwise pick
@@ -1941,7 +2002,7 @@ class ProofportSDK {
1941
2002
  return core.verifyProofOnChain(response.circuit, parsedProof, providerOrSigner, this.verifierTarget(response.circuit), {
1942
2003
  verifierAddress: response.verifierAddress,
1943
2004
  chainId: response.chainId,
1944
- });
2005
+ }, { request });
1945
2006
  }
1946
2007
  /**
1947
2008
  * Verifies a proof response off-chain, against the circuit's verification key.
@@ -1971,7 +2032,14 @@ class ProofportSDK {
1971
2032
  if (response.status !== 'completed' || !response.proof || !response.publicInputs) {
1972
2033
  return { valid: false, error: 'Invalid or incomplete response' };
1973
2034
  }
1974
- return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, options);
2035
+ let request;
2036
+ if (response.circuit === 'oidc_domain_attestation') {
2037
+ const found = this.oidcRequestFor(response, options?.request);
2038
+ if ('error' in found)
2039
+ return { valid: false, error: found.error };
2040
+ request = found.request;
2041
+ }
2042
+ return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, { ...options, request });
1975
2043
  }
1976
2044
  // ============ Utility Methods ============
1977
2045
  /**
@@ -2410,7 +2478,9 @@ class ProofportSDK {
2410
2478
  const error = await response.json().catch(() => ({ error: `HTTP ${response.status}` }));
2411
2479
  throw new Error(error.error || `Relay request failed: HTTP ${response.status}`);
2412
2480
  }
2413
- return await response.json();
2481
+ const created = await response.json();
2482
+ this.rememberRelayRequest(created.requestId, scope);
2483
+ return created;
2414
2484
  }
2415
2485
  /**
2416
2486
  * Polls the relay for proof result status.
@@ -2693,6 +2763,8 @@ class ProofportSDK {
2693
2763
  return core.extractDomainFromPublicInputs(publicInputs, circuit);
2694
2764
  }
2695
2765
  }
2766
+ /** Bound on {@link relayRequests}; a dApp that verifies later can pass the request explicitly. */
2767
+ ProofportSDK.MAX_REMEMBERED_RELAY_REQUESTS = 1000;
2696
2768
  /**
2697
2769
  * How each circuit's request is built and checked. Keyed by circuit id and
2698
2770
  * exhaustive over it, so a new circuit is a compile error here instead of
@@ -2721,14 +2793,46 @@ Object.defineProperty(exports, "MDL_KR_PUBLIC_INPUT_LAYOUT", {
2721
2793
  enumerable: true,
2722
2794
  get: function () { return core.MDL_KR_PUBLIC_INPUT_LAYOUT; }
2723
2795
  });
2796
+ Object.defineProperty(exports, "OIDC_ALLOWED_AUDIENCES", {
2797
+ enumerable: true,
2798
+ get: function () { return core.OIDC_ALLOWED_AUDIENCES; }
2799
+ });
2724
2800
  Object.defineProperty(exports, "OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT", {
2725
2801
  enumerable: true,
2726
2802
  get: function () { return core.OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT; }
2727
2803
  });
2804
+ Object.defineProperty(exports, "OIDC_NONCE_DOMAIN", {
2805
+ enumerable: true,
2806
+ get: function () { return core.OIDC_NONCE_DOMAIN; }
2807
+ });
2808
+ Object.defineProperty(exports, "OIDC_NOW_MAX_AGE_SECONDS", {
2809
+ enumerable: true,
2810
+ get: function () { return core.OIDC_NOW_MAX_AGE_SECONDS; }
2811
+ });
2812
+ Object.defineProperty(exports, "OIDC_NOW_MAX_FUTURE_SECONDS", {
2813
+ enumerable: true,
2814
+ get: function () { return core.OIDC_NOW_MAX_FUTURE_SECONDS; }
2815
+ });
2816
+ Object.defineProperty(exports, "OIDC_V1_PUBLIC_INPUT_COUNT", {
2817
+ enumerable: true,
2818
+ get: function () { return core.OIDC_V1_PUBLIC_INPUT_COUNT; }
2819
+ });
2820
+ Object.defineProperty(exports, "OIDC_V2_PUBLIC_INPUT_COUNT", {
2821
+ enumerable: true,
2822
+ get: function () { return core.OIDC_V2_PUBLIC_INPUT_COUNT; }
2823
+ });
2728
2824
  Object.defineProperty(exports, "PINNED_VERIFIERS", {
2729
2825
  enumerable: true,
2730
2826
  get: function () { return core.PINNED_VERIFIERS; }
2731
2827
  });
2828
+ Object.defineProperty(exports, "checkOidcPolicy", {
2829
+ enumerable: true,
2830
+ get: function () { return core.checkOidcPolicy; }
2831
+ });
2832
+ Object.defineProperty(exports, "deriveOidcNonceBinding", {
2833
+ enumerable: true,
2834
+ get: function () { return core.deriveOidcNonceBinding; }
2835
+ });
2732
2836
  Object.defineProperty(exports, "extractDomainFromPublicInputs", {
2733
2837
  enumerable: true,
2734
2838
  get: function () { return core.extractDomainFromPublicInputs; }
@@ -2745,6 +2849,10 @@ Object.defineProperty(exports, "getPinnedVerifier", {
2745
2849
  enumerable: true,
2746
2850
  get: function () { return core.getPinnedVerifier; }
2747
2851
  });
2852
+ Object.defineProperty(exports, "oidcAudienceHash", {
2853
+ enumerable: true,
2854
+ get: function () { return core.oidcAudienceHash; }
2855
+ });
2748
2856
  Object.defineProperty(exports, "ALL_CIRCUIT_IDS", {
2749
2857
  enumerable: true,
2750
2858
  get: function () { return circuits.ALL_CIRCUIT_IDS; }