@credo-ts/core 0.7.3 → 0.7.4-alpha-20261028231852

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.
Files changed (80) hide show
  1. package/build/agent/TrustedIssuerContext.d.mts +11 -1
  2. package/build/agent/TrustedIssuerContext.d.mts.map +1 -1
  3. package/build/agent/TrustedIssuerContext.mjs +7 -0
  4. package/build/agent/TrustedIssuerContext.mjs.map +1 -1
  5. package/build/agent/TrustedIssuersForVerification.d.mts +11 -1
  6. package/build/agent/TrustedIssuersForVerification.d.mts.map +1 -1
  7. package/build/crypto/webcrypto/CredoWalletWebCrypto.d.mts +1 -1
  8. package/build/index.d.mts +3 -3
  9. package/build/index.mjs +2 -2
  10. package/build/modules/dcql/DcqlService.d.mts.map +1 -1
  11. package/build/modules/dcql/DcqlService.mjs +24 -12
  12. package/build/modules/dcql/DcqlService.mjs.map +1 -1
  13. package/build/modules/dids/services/DidResolverService.d.mts +4 -0
  14. package/build/modules/dids/services/DidResolverService.d.mts.map +1 -1
  15. package/build/modules/dids/services/DidResolverService.mjs +21 -5
  16. package/build/modules/dids/services/DidResolverService.mjs.map +1 -1
  17. package/build/modules/sd-jwt-vc/utils.mjs +4 -4
  18. package/build/modules/sd-jwt-vc/utils.mjs.map +1 -1
  19. package/build/modules/vc/W3cCredentialServiceOptions.d.mts +5 -5
  20. package/build/modules/vc/W3cCredentialServiceOptions.d.mts.map +1 -1
  21. package/build/modules/vc/W3cV2CredentialService.d.mts +5 -1
  22. package/build/modules/vc/W3cV2CredentialService.d.mts.map +1 -1
  23. package/build/modules/vc/W3cV2CredentialService.mjs +72 -26
  24. package/build/modules/vc/W3cV2CredentialService.mjs.map +1 -1
  25. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts +14 -6
  26. package/build/modules/vc/W3cV2CredentialServiceOptions.d.mts.map +1 -1
  27. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts +0 -18
  28. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.d.mts.map +1 -1
  29. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs +38 -36
  30. package/build/modules/vc/data-integrity/W3cV2DataIntegrityCredentialService.mjs.map +1 -1
  31. package/build/modules/vc/data-integrity/v2-di-utils.mjs +17 -35
  32. package/build/modules/vc/data-integrity/v2-di-utils.mjs.map +1 -1
  33. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts +0 -23
  34. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.d.mts.map +1 -1
  35. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs +17 -68
  36. package/build/modules/vc/jwt-vc/W3cJwtCredentialService.mjs.map +1 -1
  37. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.d.mts.map +1 -1
  38. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs +11 -17
  39. package/build/modules/vc/jwt-vc/W3cV2JwtCredentialService.mjs.map +1 -1
  40. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts +5 -0
  41. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.d.mts.map +1 -1
  42. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs +18 -4
  43. package/build/modules/vc/linked-data-proofs/W3cJsonLdCredentialService.mjs.map +1 -1
  44. package/build/modules/vc/models/W3cV2VerifyResult.d.mts +6 -0
  45. package/build/modules/vc/models/W3cV2VerifyResult.d.mts.map +1 -1
  46. package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts +1 -1
  47. package/build/modules/vc/models/credential/W3cV2EnvelopedVerifiableCredential.d.mts.map +1 -1
  48. package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts +1 -1
  49. package/build/modules/vc/models/credential/W3cV2VerifiableCredential.d.mts.map +1 -1
  50. package/build/modules/vc/resolveSigner.mjs +74 -0
  51. package/build/modules/vc/resolveSigner.mjs.map +1 -0
  52. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.d.mts.map +1 -1
  53. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs +16 -18
  54. package/build/modules/vc/sd-jwt-vc/W3cV2SdJwtCredentialService.mjs.map +1 -1
  55. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts +1 -1
  56. package/build/modules/vc/sd-jwt-vc/disclosureFrame.d.mts.map +1 -1
  57. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs +2 -1
  58. package/build/modules/vc/sd-jwt-vc/disclosureFrame.mjs.map +1 -1
  59. package/build/modules/vc/v2-jwt-utils.mjs +54 -55
  60. package/build/modules/vc/v2-jwt-utils.mjs.map +1 -1
  61. package/build/modules/x509/X509ModuleConfig.d.mts +5 -13
  62. package/build/modules/x509/X509ModuleConfig.d.mts.map +1 -1
  63. package/build/modules/x509/X509ModuleConfig.mjs +2 -1
  64. package/build/modules/x509/X509ModuleConfig.mjs.map +1 -1
  65. package/build/modules/x509/X509RevocationService.d.mts.map +1 -1
  66. package/build/modules/x509/X509RevocationService.mjs +17 -20
  67. package/build/modules/x509/X509RevocationService.mjs.map +1 -1
  68. package/build/modules/x509/X509Service.mjs +1 -1
  69. package/build/modules/x509/X509Service.mjs.map +1 -1
  70. package/build/modules/x509/X509ServiceOptions.d.mts +4 -6
  71. package/build/modules/x509/X509ServiceOptions.d.mts.map +1 -1
  72. package/build/modules/x509/X509ValidationOptions.d.mts +19 -2
  73. package/build/modules/x509/X509ValidationOptions.d.mts.map +1 -1
  74. package/build/modules/x509/X509ValidationOptions.mjs +21 -1
  75. package/build/modules/x509/X509ValidationOptions.mjs.map +1 -1
  76. package/build/modules/x509/index.d.mts +2 -2
  77. package/build/modules/x509/index.mjs +2 -2
  78. package/build/modules/x509/utils/crlFetcher.mjs +1 -11
  79. package/build/modules/x509/utils/crlFetcher.mjs.map +1 -1
  80. package/package.json +1 -1
@@ -2,8 +2,8 @@ import { CredoError } from "../../../error/CredoError.mjs";
2
2
  import "../../../error/index.mjs";
3
3
  import { asArray } from "../../../utils/array.mjs";
4
4
  import "../../../utils/index.mjs";
5
- import { DidsApi } from "../../dids/DidsApi.mjs";
6
- import "../../dids/index.mjs";
5
+ import { tryParseDid } from "../../dids/domain/parse.mjs";
6
+ import { resolveSigner } from "../resolveSigner.mjs";
7
7
  //#region src/modules/vc/data-integrity/v2-di-utils.ts
8
8
  function isDataIntegrityProof(proof) {
9
9
  if (typeof proof !== "object" || proof === null) return false;
@@ -14,52 +14,34 @@ function getProofs(securedDocument) {
14
14
  return asArray(securedDocument.proof).filter(isDataIntegrityProof);
15
15
  }
16
16
  /**
17
- * Resolves the verification method that secured a Data Integrity credential or presentation for
18
- * an already verified proof or proof set.
19
- *
20
- * Mirrors `getVerificationMethodForJwt` for the Data Integrity securing mechanism, so that all
21
- * three securing mechanisms derive a signer the same way at the call site.
17
+ * Resolves the signer of a Data Integrity credential or presentation for an already verified proof
18
+ * or proof set.
22
19
  *
23
20
  * A `proof` value may be a proof set, which per VC-DATA-INTEGRITY has no order. Its proof purposes
24
21
  * have already been validated by w3c-di before this helper is called. Where several proofs name
25
- * different verification methods, position therefore carries no meaning. `expectedController` is
26
- * used to disambiguate: the proof whose verification method is controlled by that identity is
27
- * selected. This is the co-signature case — several parties sign, and only the one identified as
28
- * the issuer or holder is relevant here.
22
+ * different verification methods, position therefore carries no meaning. `expectedSigner` is
23
+ * used to disambiguate: the proof signed by that identity is selected. This is the co-signature
24
+ * case — several parties sign, and only the one identified as the issuer or holder is relevant here.
29
25
  *
30
- * @param expectedController the identity the signer is expected to be, where known — the
26
+ * @param expectedSigner the identity the signer is expected to be, where known — the
31
27
  * credential's `issuer` or the presentation's `holder`. Omit when unknown, in which case an
32
28
  * ambiguous proof set is rejected rather than resolved arbitrarily.
33
29
  *
34
30
  * @throws {CredoError} if there is no proof with a verification method, if several verification
35
- * methods cannot be disambiguated, or if a verification method cannot be resolved.
31
+ * methods cannot be disambiguated, or if a verification method cannot be resolved or is controlled
32
+ * by another DID.
36
33
  */
37
- async function getVerificationMethodForDataIntegrityProof(agentContext, securedDocument, purpose, expectedController) {
34
+ async function resolveDataIntegritySigner(agentContext, securedDocument, purpose, expectedSigner) {
38
35
  const proofs = getProofs(securedDocument);
39
36
  if (proofs.length === 0) throw new CredoError("Data Integrity secured document does not contain a proof with a verification method");
40
- const didsApi = agentContext.dependencyManager.resolve(DidsApi);
41
- const resolveVerificationMethod = async (verificationMethodId) => {
42
- return (await didsApi.resolveDidDocument(verificationMethodId)).dereferenceKey(verificationMethodId, [purpose]);
43
- };
44
37
  const verificationMethodIds = new Set(proofs.map((proof) => proof.verificationMethod));
45
- if (verificationMethodIds.size === 1) return resolveVerificationMethod(proofs[0].verificationMethod);
46
- if (!expectedController) throw new CredoError(`Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(", ")}). Unable to determine the signer.`);
47
- const matching = (await Promise.all([...verificationMethodIds].map(resolveVerificationMethod))).filter((verificationMethod) => verificationMethod.controller === expectedController);
48
- if (matching.length === 0) throw new CredoError(`Data Integrity secured document contains multiple proofs, none of which is controlled by '${expectedController}'`);
49
- return matching[0];
50
- }
51
- /**
52
- * Resolves the identity that secured a Data Integrity credential or presentation for the given
53
- * proof purpose.
54
- *
55
- * @param expectedController see `getVerificationMethodForDataIntegrityProof`.
56
- */
57
- async function getSignerForDataIntegrityProof(agentContext, securedDocument, purpose, expectedController) {
58
- const verificationMethod = await getVerificationMethodForDataIntegrityProof(agentContext, securedDocument, purpose, expectedController);
59
- if (!verificationMethod.controller) throw new CredoError(`Verification method '${verificationMethod.id}' does not have a controller to use as the signer`);
60
- return verificationMethod.controller;
38
+ if (verificationMethodIds.size === 1) return resolveSigner(agentContext, proofs[0].verificationMethod, [purpose]);
39
+ if (!expectedSigner) throw new CredoError(`Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(", ")}). Unable to determine the signer.`);
40
+ const expectedSignerVerificationMethodId = [...verificationMethodIds].find((verificationMethodId) => tryParseDid(verificationMethodId)?.did === expectedSigner);
41
+ if (!expectedSignerVerificationMethodId) throw new CredoError(`Data Integrity secured document contains multiple proofs, none of which is signed by '${expectedSigner}'`);
42
+ return resolveSigner(agentContext, expectedSignerVerificationMethodId, [purpose]);
61
43
  }
62
44
  //#endregion
63
- export { getSignerForDataIntegrityProof, getVerificationMethodForDataIntegrityProof };
45
+ export { resolveDataIntegritySigner };
64
46
 
65
47
  //# sourceMappingURL=v2-di-utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"v2-di-utils.mjs","names":[],"sources":["../../../../src/modules/vc/data-integrity/v2-di-utils.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent'\nimport { CredoError } from '../../../error'\nimport { asArray } from '../../../utils'\nimport { type DidPurpose, DidsApi, type VerificationMethod } from '../../dids'\n\n/**\n * A Data Integrity proof, narrowed to the properties needed to identify the signer.\n */\ntype DataIntegrityProof = {\n verificationMethod: string\n}\n\nfunction isDataIntegrityProof(proof: unknown): proof is DataIntegrityProof {\n if (typeof proof !== 'object' || proof === null) return false\n\n const { verificationMethod } = proof as Record<string, unknown>\n return typeof verificationMethod === 'string'\n}\n\n/**\n * The part of a Data Integrity secured document this module needs: the embedded proof or proof\n * set. Both secured credentials and secured presentations satisfy this.\n */\ntype DataIntegritySecuredDocument = { proof: unknown }\n\nfunction getProofs(securedDocument: DataIntegritySecuredDocument): DataIntegrityProof[] {\n return asArray(securedDocument.proof).filter(isDataIntegrityProof)\n}\n\n/**\n * Resolves the verification method that secured a Data Integrity credential or presentation for\n * an already verified proof or proof set.\n *\n * Mirrors `getVerificationMethodForJwt` for the Data Integrity securing mechanism, so that all\n * three securing mechanisms derive a signer the same way at the call site.\n *\n * A `proof` value may be a proof set, which per VC-DATA-INTEGRITY has no order. Its proof purposes\n * have already been validated by w3c-di before this helper is called. Where several proofs name\n * different verification methods, position therefore carries no meaning. `expectedController` is\n * used to disambiguate: the proof whose verification method is controlled by that identity is\n * selected. This is the co-signature case — several parties sign, and only the one identified as\n * the issuer or holder is relevant here.\n *\n * @param expectedController the identity the signer is expected to be, where known — the\n * credential's `issuer` or the presentation's `holder`. Omit when unknown, in which case an\n * ambiguous proof set is rejected rather than resolved arbitrarily.\n *\n * @throws {CredoError} if there is no proof with a verification method, if several verification\n * methods cannot be disambiguated, or if a verification method cannot be resolved.\n */\nexport async function getVerificationMethodForDataIntegrityProof(\n agentContext: AgentContext,\n securedDocument: DataIntegritySecuredDocument,\n purpose: DidPurpose,\n expectedController?: string\n): Promise<VerificationMethod> {\n const proofs = getProofs(securedDocument)\n\n if (proofs.length === 0) {\n throw new CredoError('Data Integrity secured document does not contain a proof with a verification method')\n }\n\n const didsApi = agentContext.dependencyManager.resolve(DidsApi)\n\n const resolveVerificationMethod = async (verificationMethodId: string) => {\n const didDocument = await didsApi.resolveDidDocument(verificationMethodId)\n return didDocument.dereferenceKey(verificationMethodId, [purpose])\n }\n\n const verificationMethodIds = new Set(proofs.map((proof) => proof.verificationMethod))\n\n if (verificationMethodIds.size === 1) {\n return resolveVerificationMethod(proofs[0].verificationMethod)\n }\n\n if (!expectedController) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(', ')}). Unable to determine the signer.`\n )\n }\n\n const resolved = await Promise.all([...verificationMethodIds].map(resolveVerificationMethod))\n const matching = resolved.filter((verificationMethod) => verificationMethod.controller === expectedController)\n\n if (matching.length === 0) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs, none of which is controlled by '${expectedController}'`\n )\n }\n\n return matching[0]\n}\n\n/**\n * Resolves the identity that secured a Data Integrity credential or presentation for the given\n * proof purpose.\n *\n * @param expectedController see `getVerificationMethodForDataIntegrityProof`.\n */\nexport async function getSignerForDataIntegrityProof(\n agentContext: AgentContext,\n securedDocument: DataIntegritySecuredDocument,\n purpose: DidPurpose,\n expectedController?: string\n): Promise<string> {\n const verificationMethod = await getVerificationMethodForDataIntegrityProof(\n agentContext,\n securedDocument,\n purpose,\n expectedController\n )\n\n if (!verificationMethod.controller) {\n throw new CredoError(\n `Verification method '${verificationMethod.id}' does not have a controller to use as the signer`\n )\n }\n\n return verificationMethod.controller\n}\n"],"mappings":";;;;;;;AAYA,SAAS,qBAAqB,OAA6C;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CAExD,MAAM,EAAE,uBAAuB;CAC/B,OAAO,OAAO,uBAAuB;AACvC;AAQA,SAAS,UAAU,iBAAqE;CACtF,OAAO,QAAQ,gBAAgB,KAAK,CAAC,CAAC,OAAO,oBAAoB;AACnE;;;;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,2CACpB,cACA,iBACA,SACA,oBAC6B;CAC7B,MAAM,SAAS,UAAU,eAAe;CAExC,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,WAAW,qFAAqF;CAG5G,MAAM,UAAU,aAAa,kBAAkB,QAAQ,OAAO;CAE9D,MAAM,4BAA4B,OAAO,yBAAiC;EAExE,QAAO,MADmB,QAAQ,mBAAmB,oBAAoB,EAAA,CACtD,eAAe,sBAAsB,CAAC,OAAO,CAAC;CACnE;CAEA,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;CAErF,IAAI,sBAAsB,SAAS,GACjC,OAAO,0BAA0B,OAAO,EAAE,CAAC,kBAAkB;CAG/D,IAAI,CAAC,oBACH,MAAM,IAAI,WACR,iGAAiG,CAAC,GAAG,qBAAqB,CAAC,CAAC,KAAK,IAAI,EAAE,mCACzI;CAIF,MAAM,YAAW,MADM,QAAQ,IAAI,CAAC,GAAG,qBAAqB,CAAC,CAAC,IAAI,yBAAyB,CAAC,EAAA,CAClE,QAAQ,uBAAuB,mBAAmB,eAAe,kBAAkB;CAE7G,IAAI,SAAS,WAAW,GACtB,MAAM,IAAI,WACR,6FAA6F,mBAAmB,EAClH;CAGF,OAAO,SAAS;AAClB;;;;;;;AAQA,eAAsB,+BACpB,cACA,iBACA,SACA,oBACiB;CACjB,MAAM,qBAAqB,MAAM,2CAC/B,cACA,iBACA,SACA,kBACF;CAEA,IAAI,CAAC,mBAAmB,YACtB,MAAM,IAAI,WACR,wBAAwB,mBAAmB,GAAG,kDAChD;CAGF,OAAO,mBAAmB;AAC5B"}
1
+ {"version":3,"file":"v2-di-utils.mjs","names":[],"sources":["../../../../src/modules/vc/data-integrity/v2-di-utils.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent'\nimport { CredoError } from '../../../error'\nimport { asArray } from '../../../utils'\nimport type { DidPurpose } from '../../dids'\nimport { tryParseDid } from '../../dids/domain/parse'\nimport { type ResolvedSigner, resolveSigner } from '../resolveSigner'\n\n/**\n * A Data Integrity proof, narrowed to the properties needed to identify the signer.\n */\ntype DataIntegrityProof = {\n verificationMethod: string\n}\n\nfunction isDataIntegrityProof(proof: unknown): proof is DataIntegrityProof {\n if (typeof proof !== 'object' || proof === null) return false\n\n const { verificationMethod } = proof as Record<string, unknown>\n return typeof verificationMethod === 'string'\n}\n\n/**\n * The part of a Data Integrity secured document this module needs: the embedded proof or proof\n * set. Both secured credentials and secured presentations satisfy this.\n */\ntype DataIntegritySecuredDocument = { proof: unknown }\n\nfunction getProofs(securedDocument: DataIntegritySecuredDocument): DataIntegrityProof[] {\n return asArray(securedDocument.proof).filter(isDataIntegrityProof)\n}\n\n/**\n * Resolves the signer of a Data Integrity credential or presentation for an already verified proof\n * or proof set.\n *\n * A `proof` value may be a proof set, which per VC-DATA-INTEGRITY has no order. Its proof purposes\n * have already been validated by w3c-di before this helper is called. Where several proofs name\n * different verification methods, position therefore carries no meaning. `expectedSigner` is\n * used to disambiguate: the proof signed by that identity is selected. This is the co-signature\n * case — several parties sign, and only the one identified as the issuer or holder is relevant here.\n *\n * @param expectedSigner the identity the signer is expected to be, where known — the\n * credential's `issuer` or the presentation's `holder`. Omit when unknown, in which case an\n * ambiguous proof set is rejected rather than resolved arbitrarily.\n *\n * @throws {CredoError} if there is no proof with a verification method, if several verification\n * methods cannot be disambiguated, or if a verification method cannot be resolved or is controlled\n * by another DID.\n */\nexport async function resolveDataIntegritySigner(\n agentContext: AgentContext,\n securedDocument: DataIntegritySecuredDocument,\n purpose: DidPurpose,\n expectedSigner?: string\n): Promise<ResolvedSigner> {\n const proofs = getProofs(securedDocument)\n\n if (proofs.length === 0) {\n throw new CredoError('Data Integrity secured document does not contain a proof with a verification method')\n }\n\n const verificationMethodIds = new Set(proofs.map((proof) => proof.verificationMethod))\n\n if (verificationMethodIds.size === 1) {\n return resolveSigner(agentContext, proofs[0].verificationMethod, [purpose])\n }\n\n if (!expectedSigner) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs with different verification methods (${[...verificationMethodIds].join(', ')}). Unable to determine the signer.`\n )\n }\n\n // The signer is the DID of the verification method, so the other proofs don't need to be resolved\n const expectedSignerVerificationMethodId = [...verificationMethodIds].find(\n (verificationMethodId) => tryParseDid(verificationMethodId)?.did === expectedSigner\n )\n\n if (!expectedSignerVerificationMethodId) {\n throw new CredoError(\n `Data Integrity secured document contains multiple proofs, none of which is signed by '${expectedSigner}'`\n )\n }\n\n return resolveSigner(agentContext, expectedSignerVerificationMethodId, [purpose])\n}\n"],"mappings":";;;;;;;AAcA,SAAS,qBAAqB,OAA6C;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CAExD,MAAM,EAAE,uBAAuB;CAC/B,OAAO,OAAO,uBAAuB;AACvC;AAQA,SAAS,UAAU,iBAAqE;CACtF,OAAO,QAAQ,gBAAgB,KAAK,CAAC,CAAC,OAAO,oBAAoB;AACnE;;;;;;;;;;;;;;;;;;;AAoBA,eAAsB,2BACpB,cACA,iBACA,SACA,gBACyB;CACzB,MAAM,SAAS,UAAU,eAAe;CAExC,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,WAAW,qFAAqF;CAG5G,MAAM,wBAAwB,IAAI,IAAI,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;CAErF,IAAI,sBAAsB,SAAS,GACjC,OAAO,cAAc,cAAc,OAAO,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC;CAG5E,IAAI,CAAC,gBACH,MAAM,IAAI,WACR,iGAAiG,CAAC,GAAG,qBAAqB,CAAC,CAAC,KAAK,IAAI,EAAE,mCACzI;CAIF,MAAM,qCAAqC,CAAC,GAAG,qBAAqB,CAAC,CAAC,MACnE,yBAAyB,YAAY,oBAAoB,CAAC,EAAE,QAAQ,cACvE;CAEA,IAAI,CAAC,oCACH,MAAM,IAAI,WACR,yFAAyF,eAAe,EAC1G;CAGF,OAAO,cAAc,cAAc,oCAAoC,CAAC,OAAO,CAAC;AAClF"}
@@ -40,29 +40,6 @@ export declare class W3cJwtCredentialService {
40
40
  */
41
41
  verifyPresentation(agentContext: AgentContext, options: W3cJwtVerifyPresentationOptions): Promise<W3cVerifyPresentationResult>;
42
42
  private resolveVerificationMethod;
43
- /**
44
- * This method tries to find the verification method associated with the JWT credential or presentation.
45
- * This verification method can then be used to verify the credential or presentation signature.
46
- *
47
- * The following methods are used to extract the verification method:
48
- * - verification method is resolved based on the `kid` in the protected header
49
- * - either as absolute reference (e.g. `did:example:123#key-1`)
50
- * - or as relative reference to the `iss` of the JWT (e.g. `iss` is `did:example:123` and `kid` is `#key-1`)
51
- * - the did document is resolved based on the `iss` field, after which the verification method is extracted based on the `alg`
52
- * used to sign the JWT and the specified `purpose`. Only a single verification method may be present, and in all other cases,
53
- * an error is thrown.
54
- *
55
- * The signer (`iss`) of the JWT is verified against the `controller` of the verificationMethod resolved in the did
56
- * document. This means if the `iss` of a credential is `did:example:123` and the controller of the verificationMethod
57
- * is `did:example:456`, an error is thrown to prevent the JWT from successfully being verified.
58
- *
59
- * In addition the JWT must conform to one of the following rules:
60
- * - MUST be a credential and have an `iss` field and MAY have an absolute or relative `kid`
61
- * - MUST not be a credential AND ONE of the following:
62
- * - have an `iss` field and MAY have an absolute or relative `kid`
63
- * - does not have an `iss` field and MUST have an absolute `kid`
64
- */
65
- private getVerificationMethodForJwtCredential;
66
43
  }
67
44
  //#endregion
68
45
  //# sourceMappingURL=W3cJwtCredentialService.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"W3cJwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;qBAiCa;UACH;EAEW,YAAA,YAAY;;;;EAOlB,eACX,cAAc,cACd,SAAS,8BACR,QAAQ;;;;;;;EAuCE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAkJE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAqCE,mBACX,cAAc,cACd,SAAS,kCACR,QAAQ;UAsJG;;;;;;;;;;;;;;;;;;;;;;;UAyCA"}
1
+ {"version":3,"file":"W3cJwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;qBA+Ba;UACH;EAEW,YAAA,YAAY;;;;EAOlB,eACX,cAAc,cACd,SAAS,8BACR,QAAQ;;;;;;;EAuCE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EA8HE,iBACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAqCE,mBACX,cAAc,cACd,SAAS,kCACR,QAAQ;UA8IG"}
@@ -7,16 +7,15 @@ import "../../../utils/index.mjs";
7
7
  import { injectable } from "../../../plugins/index.mjs";
8
8
  import __decorateMetadata from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.mjs";
9
9
  import __decorate from "../../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.mjs";
10
- import { PublicJwk } from "../../kms/jwk/PublicJwk.mjs";
11
10
  import "../../kms/index.mjs";
12
11
  import { JwsService } from "../../../crypto/JwsService.mjs";
13
12
  import { parseDid } from "../../dids/domain/parse.mjs";
14
- import { getPublicJwkFromVerificationMethod, getSupportedVerificationMethodTypesForPublicJwk } from "../../dids/domain/key-type/keyDidMapping.mjs";
15
- import { DidResolverService } from "../../dids/services/DidResolverService.mjs";
13
+ import { getPublicJwkFromVerificationMethod } from "../../dids/domain/key-type/keyDidMapping.mjs";
16
14
  import { DidsApi } from "../../dids/DidsApi.mjs";
17
15
  import "../../dids/index.mjs";
18
16
  import { TrustedIssuerContext } from "../../../agent/TrustedIssuerContext.mjs";
19
17
  import { W3cJsonLdVerifiableCredential } from "../linked-data-proofs/models/W3cJsonLdVerifiableCredential.mjs";
18
+ import { resolveJwtSigner, validateSignerIsExpectedParty } from "../resolveSigner.mjs";
20
19
  import { validateCredentialSubjectAuthentication } from "../util.mjs";
21
20
  import { getJwtPayloadFromCredential } from "./credentialTransformer.mjs";
22
21
  import { W3cJwtVerifiableCredential } from "./W3cJwtVerifiableCredential.mjs";
@@ -72,12 +71,15 @@ let W3cJwtCredentialService = class W3cJwtCredentialService {
72
71
  };
73
72
  return validationResults;
74
73
  }
75
- const issuerVerificationMethod = await this.getVerificationMethodForJwtCredential(agentContext, {
76
- credential,
74
+ const issuer = await resolveJwtSigner(agentContext, {
75
+ alg: credential.jwt.header.alg,
76
+ kid: credential.jwt.header.kid,
77
+ iss: credential.jwt.payload.iss,
77
78
  purpose: ["assertionMethod"]
78
79
  });
80
+ const issuerVerificationMethod = issuer.verificationMethod;
79
81
  const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod);
80
- await TrustedIssuerContext.ensureTrustedSigner(agentContext, {
82
+ await TrustedIssuerContext.ensureTrustedCredentialSigner(agentContext, {
81
83
  signer: {
82
84
  method: "did",
83
85
  didUrl: issuerVerificationMethod.id
@@ -108,16 +110,11 @@ let W3cJwtCredentialService = class W3cJwtCredentialService {
108
110
  error
109
111
  };
110
112
  }
111
- if (credential.issuerId !== issuerVerificationMethod.controller) validationResults.validations.issuerIsSigner = {
112
- isValid: false,
113
- error: new CredoError(`Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.issuerId}'`)
114
- };
115
- else validationResults.validations.issuerIsSigner = { isValid: true };
116
- if (!signatureResult?.jwsSigners.some((jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint)) validationResults.validations.issuerIsSigner = {
113
+ const isSignedByIssuerKey = signatureResult?.jwsSigners.some((jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint);
114
+ validationResults.validations.issuerIsSigner = isSignedByIssuerKey ? validateSignerIsExpectedParty(issuer, credential.issuerId, "issuer") : {
117
115
  isValid: false,
118
116
  error: new CredoError("Credential is not signed by the issuer of the credential")
119
117
  };
120
- else validationResults.validations.issuerIsSigner = { isValid: true };
121
118
  if (verifyCredentialStatus && !credential.credentialStatus) validationResults.validations.credentialStatus = { isValid: true };
122
119
  else if (verifyCredentialStatus && credential.credentialStatus) validationResults.validations.credentialStatus = {
123
120
  isValid: false,
@@ -181,10 +178,13 @@ let W3cJwtCredentialService = class W3cJwtCredentialService {
181
178
  };
182
179
  return validationResults;
183
180
  }
184
- const proverVerificationMethod = await this.getVerificationMethodForJwtCredential(agentContext, {
185
- credential: presentation,
181
+ const prover = await resolveJwtSigner(agentContext, {
182
+ alg: presentation.jwt.header.alg,
183
+ kid: presentation.jwt.header.kid,
184
+ iss: presentation.jwt.payload.iss,
186
185
  purpose: ["authentication"]
187
186
  });
187
+ const proverVerificationMethod = prover.verificationMethod;
188
188
  const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod);
189
189
  let signatureResult;
190
190
  try {
@@ -209,11 +209,7 @@ let W3cJwtCredentialService = class W3cJwtCredentialService {
209
209
  error
210
210
  };
211
211
  }
212
- if (presentation.holderId && proverVerificationMethod.controller !== presentation.holderId) validationResults.validations.holderIsSigner = {
213
- isValid: false,
214
- error: new CredoError(`Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.holderId}'`)
215
- };
216
- else validationResults.validations.holderIsSigner = { isValid: true };
212
+ validationResults.validations.holderIsSigner = validateSignerIsExpectedParty(prover, presentation.holderId, "holder");
217
213
  const credentials = asArray(presentation.presentation.verifiableCredential);
218
214
  validationResults.validations.credentials = await Promise.all(credentials.map(async (credential) => {
219
215
  if (credential instanceof W3cJsonLdVerifiableCredential) return {
@@ -226,7 +222,7 @@ let W3cJwtCredentialService = class W3cJwtCredentialService {
226
222
  verifyCredentialStatus: options.verifyCredentialStatus,
227
223
  trustedIssuers: options.trustedIssuers
228
224
  });
229
- const credentialSubjectAuthentication = validateCredentialSubjectAuthentication(credential.credentialSubjectIds, proverVerificationMethod.controller);
225
+ const credentialSubjectAuthentication = validateCredentialSubjectAuthentication(credential.credentialSubjectIds, prover.signer);
230
226
  return {
231
227
  ...credentialResult,
232
228
  isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,
@@ -252,53 +248,6 @@ let W3cJwtCredentialService = class W3cJwtCredentialService {
252
248
  publicJwk.keyId = keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId ?? publicJwk.legacyKeyId;
253
249
  return publicJwk;
254
250
  }
255
- /**
256
- * This method tries to find the verification method associated with the JWT credential or presentation.
257
- * This verification method can then be used to verify the credential or presentation signature.
258
- *
259
- * The following methods are used to extract the verification method:
260
- * - verification method is resolved based on the `kid` in the protected header
261
- * - either as absolute reference (e.g. `did:example:123#key-1`)
262
- * - or as relative reference to the `iss` of the JWT (e.g. `iss` is `did:example:123` and `kid` is `#key-1`)
263
- * - the did document is resolved based on the `iss` field, after which the verification method is extracted based on the `alg`
264
- * used to sign the JWT and the specified `purpose`. Only a single verification method may be present, and in all other cases,
265
- * an error is thrown.
266
- *
267
- * The signer (`iss`) of the JWT is verified against the `controller` of the verificationMethod resolved in the did
268
- * document. This means if the `iss` of a credential is `did:example:123` and the controller of the verificationMethod
269
- * is `did:example:456`, an error is thrown to prevent the JWT from successfully being verified.
270
- *
271
- * In addition the JWT must conform to one of the following rules:
272
- * - MUST be a credential and have an `iss` field and MAY have an absolute or relative `kid`
273
- * - MUST not be a credential AND ONE of the following:
274
- * - have an `iss` field and MAY have an absolute or relative `kid`
275
- * - does not have an `iss` field and MUST have an absolute `kid`
276
- */
277
- async getVerificationMethodForJwtCredential(agentContext, options) {
278
- const { credential, purpose } = options;
279
- const kid = credential.jwt.header.kid;
280
- const didResolver = agentContext.dependencyManager.resolve(DidResolverService);
281
- const signerId = credential.jwt.payload.iss;
282
- let verificationMethod;
283
- if (kid?.startsWith("#")) {
284
- if (!signerId) throw new CredoError(`JWT 'kid' MUST be absolute when when no 'iss' is present in JWT payload`);
285
- verificationMethod = (await didResolver.resolveDidDocument(agentContext, signerId)).dereferenceKey(`${signerId}${kid}`, purpose);
286
- } else if (kid && isDid(kid)) {
287
- const didDocument = await didResolver.resolveDidDocument(agentContext, kid);
288
- verificationMethod = didDocument.dereferenceKey(kid, purpose);
289
- if (signerId && didDocument.id !== signerId) throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${signerId}'`);
290
- } else {
291
- if (!signerId) throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`);
292
- const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(credential.jwt.header.alg);
293
- const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass);
294
- const verificationMethods = (await didResolver.resolveDidDocument(agentContext, signerId)).findVerificationMethodsByTypeAndPurpose(supportedVerificationMethodTypes, ["assertionMethod"]);
295
- if (verificationMethods.length === 0) throw new CredoError(`No verification methods found for signer '${signerId}' and key type '${jwkClass.name}' for alg '${credential.jwt.header.alg}'. Unable to determine which public key is associated with the credential.`);
296
- if (verificationMethods.length > 1) throw new CredoError(`Multiple verification methods found for signer '${signerId}' and key type '${jwkClass.name}' for alg '${credential.jwt.header.alg}'. Unable to determine which public key is associated with the credential.`);
297
- verificationMethod = verificationMethods[0];
298
- }
299
- if (signerId && verificationMethod.controller !== signerId) throw new CredoError(`Verification method controller '${verificationMethod.controller}' does not match the signer '${signerId}'`);
300
- return verificationMethod;
301
- }
302
251
  };
303
252
  W3cJwtCredentialService = __decorate([injectable(), __decorateMetadata("design:paramtypes", [typeof JwsService === "undefined" ? Object : JwsService])], W3cJwtCredentialService);
304
253
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"W3cJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport type { VerifyJwsResult } from '../../../crypto/JwsService'\nimport { JwsService } from '../../../crypto/JwsService'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport { asArray, isDid, MessageValidator } from '../../../utils'\nimport type { DidPurpose, VerificationMethod } from '../../dids'\nimport { DidResolverService, DidsApi, parseDid } from '../../dids'\nimport {\n getPublicJwkFromVerificationMethod,\n getSupportedVerificationMethodTypesForPublicJwk,\n} from '../../dids/domain/key-type/keyDidMapping'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../../kms'\nimport { W3cJsonLdVerifiableCredential } from '../linked-data-proofs/models/W3cJsonLdVerifiableCredential'\nimport type { W3cVerifyCredentialResult, W3cVerifyPresentationResult } from '../models'\nimport { validateCredentialSubjectAuthentication } from '../util'\nimport type {\n W3cJwtSignCredentialOptions,\n W3cJwtSignPresentationOptions,\n W3cJwtVerifyCredentialOptions,\n W3cJwtVerifyPresentationOptions,\n} from '../W3cCredentialServiceOptions'\nimport { getJwtPayloadFromCredential } from './credentialTransformer'\nimport { getJwtPayloadFromPresentation } from './presentationTransformer'\nimport { W3cJwtVerifiableCredential } from './W3cJwtVerifiableCredential'\nimport { W3cJwtVerifiablePresentation } from './W3cJwtVerifiablePresentation'\n\n/**\n * Supports signing and verification of credentials according to the [Verifiable Credential Data Model](https://www.w3.org/TR/vc-data-model)\n * using [Json Web Tokens](https://www.w3.org/TR/vc-data-model/#json-web-token).\n */\n@injectable()\nexport class W3cJwtCredentialService {\n private jwsService: JwsService\n\n public constructor(jwsService: JwsService) {\n this.jwsService = jwsService\n }\n\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cJwtSignCredentialOptions\n ): Promise<W3cJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // Get the JWT payload for the JWT based on the JWT Encoding rules form the VC-DATA-MODEL\n // https://www.w3.org/TR/vc-data-model/#jwt-encoding\n const jwtPayload = getJwtPayloadFromCredential(options.credential)\n\n if (!isDid(options.verificationMethod)) {\n throw new CredoError('Only did identifiers are supported as verification method')\n }\n\n const publicJwk = await this.resolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n const jwt = await this.jwsService.createJwsCompact(agentContext, {\n payload: jwtPayload,\n keyId: publicJwk.keyId,\n protectedHeaderOptions: {\n typ: 'JWT',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n // TODO: this re-parses and validates the credential in the JWT, which is not necessary.\n // We should somehow create an instance of W3cJwtVerifiableCredential directly from the JWT\n const jwtVc = W3cJwtVerifiableCredential.fromSerializedJwt(jwt)\n\n return jwtVc\n }\n\n /**\n * Verifies the signature(s) of a credential\n *\n * @param credential the credential to be verified\n * @returns the verification result\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cJwtVerifyCredentialOptions\n ): Promise<W3cVerifyCredentialResult> {\n // NOTE: this is mostly from the JSON-LD service that adds this option. Once we support\n // the same granular validation results, we can remove this and the user could just check\n // which of the validations failed. Supporting for consistency with the JSON-LD service for now.\n const verifyCredentialStatus = options.verifyCredentialStatus ?? true\n\n const validationResults: W3cVerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n try {\n let credential: W3cJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential (otherwise it's done in the fromSerializedJwt method below)\n if (options.credential instanceof W3cJwtVerifiableCredential) {\n MessageValidator.validateSync(options.credential.credential)\n }\n\n credential =\n options.credential instanceof W3cJwtVerifiableCredential\n ? options.credential\n : W3cJwtVerifiableCredential.fromSerializedJwt(options.credential)\n\n // Verify the JWT payload (verifies whether it's not expired, etc...)\n credential.jwt.payload.validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuerVerificationMethod = await this.getVerificationMethodForJwtCredential(agentContext, {\n credential,\n purpose: ['assertionMethod'],\n })\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n let signatureResult: VerifyJwsResult | undefined\n try {\n // Verify the JWS signature\n signatureResult = await this.jwsService.verifyJws(agentContext, {\n jws: credential.jwt.serializedJwt,\n // We have pre-fetched the key based on the issuer/signer of the credential\n jwsSigner: {\n method: 'did',\n jwk: issuerPublicKey,\n didUrl: issuerVerificationMethod.id,\n },\n })\n\n if (!signatureResult.isValid) {\n validationResults.validations.signature = {\n isValid: false,\n error: new CredoError('Invalid JWS signature'),\n }\n } else {\n validationResults.validations.signature = {\n isValid: true,\n }\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the credential is signed with the 'issuer' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (credential.issuerId !== issuerVerificationMethod.controller) {\n validationResults.validations.issuerIsSigner = {\n isValid: false,\n error: new CredoError(\n `Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.issuerId}'`\n ),\n }\n } else {\n validationResults.validations.issuerIsSigner = {\n isValid: true,\n }\n }\n\n // Validate whether the `issuer` of the credential is also the signer\n const issuerIsSigner = signatureResult?.jwsSigners.some(\n (jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint\n )\n if (!issuerIsSigner) {\n validationResults.validations.issuerIsSigner = {\n isValid: false,\n error: new CredoError('Credential is not signed by the issuer of the credential'),\n }\n } else {\n validationResults.validations.issuerIsSigner = {\n isValid: true,\n }\n }\n\n // Validate credentialStatus\n if (verifyCredentialStatus && !credential.credentialStatus) {\n validationResults.validations.credentialStatus = {\n isValid: true,\n }\n } else if (verifyCredentialStatus && credential.credentialStatus) {\n validationResults.validations.credentialStatus = {\n isValid: false,\n error: new CredoError('Verifying credential status is not supported for JWT VCs'),\n }\n }\n\n validationResults.isValid = Object.values(validationResults.validations).every((v) => v.isValid)\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n /**\n * Signs a presentation including the credentials it includes\n *\n * @param presentation the presentation to be signed\n * @returns the signed presentation\n */\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cJwtSignPresentationOptions\n ): Promise<W3cJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // Get the JWT payload for the JWT based on the JWT Encoding rules form the VC-DATA-MODEL\n // https://www.w3.org/TR/vc-data-model/#jwt-encoding\n const jwtPayload = getJwtPayloadFromPresentation(options.presentation)\n\n // Set the nonce so it's included in the signature\n jwtPayload.additionalClaims.nonce = options.challenge\n jwtPayload.aud = options.domain\n\n const publicJwk = await this.resolveVerificationMethod(agentContext, options.verificationMethod, ['authentication'])\n\n const jwt = await this.jwsService.createJwsCompact(agentContext, {\n payload: jwtPayload,\n keyId: publicJwk.keyId,\n protectedHeaderOptions: {\n typ: 'JWT',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n // TODO: this re-parses and validates the presentation in the JWT, which is not necessary.\n // We should somehow create an instance of W3cJwtVerifiablePresentation directly from the JWT\n const jwtVp = W3cJwtVerifiablePresentation.fromSerializedJwt(jwt)\n\n return jwtVp\n }\n\n /**\n * Verifies a presentation including the credentials it includes\n *\n * @param presentation the presentation to be verified\n * @returns the verification result\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cJwtVerifyPresentationOptions\n ): Promise<W3cVerifyPresentationResult> {\n const validationResults: W3cVerifyPresentationResult = {\n isValid: false,\n validations: {},\n }\n\n try {\n let presentation: W3cJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cJwtVerifiablePresentation) {\n MessageValidator.validateSync(options.presentation.presentation)\n }\n\n presentation =\n options.presentation instanceof W3cJwtVerifiablePresentation\n ? options.presentation\n : W3cJwtVerifiablePresentation.fromSerializedJwt(options.presentation)\n\n // Verify the JWT payload (verifies whether it's not expired, etc...)\n presentation.jwt.payload.validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n // Make sure challenge matches nonce\n if (options.challenge !== presentation.jwt.payload.additionalClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.jwt.payload.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const proverVerificationMethod = await this.getVerificationMethodForJwtCredential(agentContext, {\n credential: presentation,\n purpose: ['authentication'],\n })\n const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod)\n\n let signatureResult: VerifyJwsResult | undefined\n try {\n // Verify the JWS signature\n signatureResult = await this.jwsService.verifyJws(agentContext, {\n jws: presentation.jwt.serializedJwt,\n allowedJwsSignerMethods: ['did'],\n jwsSigner: {\n method: 'did',\n didUrl: proverVerificationMethod.id,\n jwk: proverPublicKey,\n },\n trustedCertificates: [],\n })\n\n if (!signatureResult.isValid) {\n validationResults.validations.presentationSignature = {\n isValid: false,\n error: new CredoError('Invalid JWS signature on presentation'),\n }\n } else {\n validationResults.validations.presentationSignature = {\n isValid: true,\n }\n }\n } catch (error) {\n validationResults.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the presentation is signed with the 'holder' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (presentation.holderId && proverVerificationMethod.controller !== presentation.holderId) {\n validationResults.validations.holderIsSigner = {\n isValid: false,\n error: new CredoError(\n `Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.holderId}'`\n ),\n }\n } else {\n // If no holderId is present, this validation passes by default as there can't be\n // a mismatch between the 'holder' property and the signer of the presentation.\n validationResults.validations.holderIsSigner = {\n isValid: true,\n }\n }\n\n // To keep things simple, we only support JWT VCs in JWT VPs for now\n const credentials = asArray(presentation.presentation.verifiableCredential)\n\n // Verify all credentials in parallel, and await the result\n validationResults.validations.credentials = await Promise.all(\n credentials.map(async (credential) => {\n if (credential instanceof W3cJsonLdVerifiableCredential) {\n return {\n isValid: false,\n error: new CredoError(\n 'Credential is of format ldp_vc. presentations in jwt_vp format can only contain credentials in jwt_vc format'\n ),\n validations: {},\n }\n }\n\n const credentialResult = await this.verifyCredential(agentContext, {\n credential,\n verifyCredentialStatus: options.verifyCredentialStatus,\n trustedIssuers: options.trustedIssuers,\n })\n\n const credentialSubjectAuthentication = validateCredentialSubjectAuthentication(\n credential.credentialSubjectIds,\n proverVerificationMethod.controller\n )\n\n return {\n ...credentialResult,\n isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,\n validations: {\n ...credentialResult.validations,\n credentialSubjectAuthentication,\n },\n }\n })\n )\n\n // Deeply nested check whether all validations have passed\n validationResults.isValid = Object.values(validationResults.validations).every((v) =>\n Array.isArray(v) ? v.every((vv) => vv.isValid) : v.isValid\n )\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n private async resolveVerificationMethod(\n agentContext: AgentContext,\n verificationMethod: string,\n allowsPurposes?: DidPurpose[]\n ): Promise<PublicJwk> {\n const dids = agentContext.resolve(DidsApi)\n\n const parsedDid = parseDid(verificationMethod)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(parsedDid.did)\n const verificationMethodObject = didDocument.dereferenceKey(verificationMethod, allowsPurposes)\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethodObject)\n\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))\n ?.kmsKeyId ?? publicJwk.legacyKeyId\n\n return publicJwk\n }\n\n /**\n * This method tries to find the verification method associated with the JWT credential or presentation.\n * This verification method can then be used to verify the credential or presentation signature.\n *\n * The following methods are used to extract the verification method:\n * - verification method is resolved based on the `kid` in the protected header\n * - either as absolute reference (e.g. `did:example:123#key-1`)\n * - or as relative reference to the `iss` of the JWT (e.g. `iss` is `did:example:123` and `kid` is `#key-1`)\n * - the did document is resolved based on the `iss` field, after which the verification method is extracted based on the `alg`\n * used to sign the JWT and the specified `purpose`. Only a single verification method may be present, and in all other cases,\n * an error is thrown.\n *\n * The signer (`iss`) of the JWT is verified against the `controller` of the verificationMethod resolved in the did\n * document. This means if the `iss` of a credential is `did:example:123` and the controller of the verificationMethod\n * is `did:example:456`, an error is thrown to prevent the JWT from successfully being verified.\n *\n * In addition the JWT must conform to one of the following rules:\n * - MUST be a credential and have an `iss` field and MAY have an absolute or relative `kid`\n * - MUST not be a credential AND ONE of the following:\n * - have an `iss` field and MAY have an absolute or relative `kid`\n * - does not have an `iss` field and MUST have an absolute `kid`\n */\n private async getVerificationMethodForJwtCredential(\n agentContext: AgentContext,\n options: {\n credential: W3cJwtVerifiableCredential | W3cJwtVerifiablePresentation\n purpose?: DidPurpose[]\n }\n ) {\n const { credential, purpose } = options\n const kid = credential.jwt.header.kid\n\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n\n // The signerId is the `holder` of the presentation or the `issuer` of the credential\n // For a credential only the `iss` COULD be enough to resolve the signer key (see method comments)\n const signerId = credential.jwt.payload.iss\n\n let verificationMethod: VerificationMethod\n\n // If the kid starts with # we assume it is a relative did url, and we resolve it based on the `iss` and the `kid`\n if (kid?.startsWith('#')) {\n if (!signerId) {\n throw new CredoError(`JWT 'kid' MUST be absolute when when no 'iss' is present in JWT payload`)\n }\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, signerId)\n verificationMethod = didDocument.dereferenceKey(`${signerId}${kid}`, purpose)\n }\n // this is a full did url (todo check if it contains a #)\n else if (kid && isDid(kid)) {\n const didDocument = await didResolver.resolveDidDocument(agentContext, kid)\n\n verificationMethod = didDocument.dereferenceKey(kid, purpose)\n\n if (signerId && didDocument.id !== signerId) {\n throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${signerId}'`)\n }\n } else {\n if (!signerId) {\n throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`)\n }\n\n // Find the verificationMethod in the did document based on the alg and proofPurpose\n const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(\n credential.jwt.header.alg as KnownJwaSignatureAlgorithm\n )\n const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass)\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, signerId)\n const verificationMethods = didDocument.findVerificationMethodsByTypeAndPurpose(\n supportedVerificationMethodTypes,\n ['assertionMethod']\n )\n\n if (verificationMethods.length === 0) {\n throw new CredoError(\n `No verification methods found for signer '${signerId}' and key type '${jwkClass.name}' for alg '${credential.jwt.header.alg}'. Unable to determine which public key is associated with the credential.`\n )\n }\n if (verificationMethods.length > 1) {\n throw new CredoError(\n `Multiple verification methods found for signer '${signerId}' and key type '${jwkClass.name}' for alg '${credential.jwt.header.alg}'. Unable to determine which public key is associated with the credential.`\n )\n }\n\n verificationMethod = verificationMethods[0]\n }\n\n // Verify the controller of the verificationMethod matches the signer of the credential\n if (signerId && verificationMethod.controller !== signerId) {\n throw new CredoError(\n `Verification method controller '${verificationMethod.controller}' does not match the signer '${signerId}'`\n )\n }\n\n return verificationMethod\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"W3cJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport type { VerifyJwsResult } from '../../../crypto/JwsService'\nimport { JwsService } from '../../../crypto/JwsService'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport { asArray, isDid, MessageValidator } from '../../../utils'\nimport type { DidPurpose } from '../../dids'\nimport { DidsApi, parseDid } from '../../dids'\nimport { getPublicJwkFromVerificationMethod } from '../../dids/domain/key-type/keyDidMapping'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../../kms'\nimport { W3cJsonLdVerifiableCredential } from '../linked-data-proofs/models/W3cJsonLdVerifiableCredential'\nimport type { W3cVerifyCredentialResult, W3cVerifyPresentationResult } from '../models'\nimport { resolveJwtSigner, validateSignerIsExpectedParty } from '../resolveSigner'\nimport { validateCredentialSubjectAuthentication } from '../util'\nimport type {\n W3cJwtSignCredentialOptions,\n W3cJwtSignPresentationOptions,\n W3cJwtVerifyCredentialOptions,\n W3cJwtVerifyPresentationOptions,\n} from '../W3cCredentialServiceOptions'\nimport { getJwtPayloadFromCredential } from './credentialTransformer'\nimport { getJwtPayloadFromPresentation } from './presentationTransformer'\nimport { W3cJwtVerifiableCredential } from './W3cJwtVerifiableCredential'\nimport { W3cJwtVerifiablePresentation } from './W3cJwtVerifiablePresentation'\n\n/**\n * Supports signing and verification of credentials according to the [Verifiable Credential Data Model](https://www.w3.org/TR/vc-data-model)\n * using [Json Web Tokens](https://www.w3.org/TR/vc-data-model/#json-web-token).\n */\n@injectable()\nexport class W3cJwtCredentialService {\n private jwsService: JwsService\n\n public constructor(jwsService: JwsService) {\n this.jwsService = jwsService\n }\n\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cJwtSignCredentialOptions\n ): Promise<W3cJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // Get the JWT payload for the JWT based on the JWT Encoding rules form the VC-DATA-MODEL\n // https://www.w3.org/TR/vc-data-model/#jwt-encoding\n const jwtPayload = getJwtPayloadFromCredential(options.credential)\n\n if (!isDid(options.verificationMethod)) {\n throw new CredoError('Only did identifiers are supported as verification method')\n }\n\n const publicJwk = await this.resolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n const jwt = await this.jwsService.createJwsCompact(agentContext, {\n payload: jwtPayload,\n keyId: publicJwk.keyId,\n protectedHeaderOptions: {\n typ: 'JWT',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n // TODO: this re-parses and validates the credential in the JWT, which is not necessary.\n // We should somehow create an instance of W3cJwtVerifiableCredential directly from the JWT\n const jwtVc = W3cJwtVerifiableCredential.fromSerializedJwt(jwt)\n\n return jwtVc\n }\n\n /**\n * Verifies the signature(s) of a credential\n *\n * @param credential the credential to be verified\n * @returns the verification result\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cJwtVerifyCredentialOptions\n ): Promise<W3cVerifyCredentialResult> {\n // NOTE: this is mostly from the JSON-LD service that adds this option. Once we support\n // the same granular validation results, we can remove this and the user could just check\n // which of the validations failed. Supporting for consistency with the JSON-LD service for now.\n const verifyCredentialStatus = options.verifyCredentialStatus ?? true\n\n const validationResults: W3cVerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n try {\n let credential: W3cJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential (otherwise it's done in the fromSerializedJwt method below)\n if (options.credential instanceof W3cJwtVerifiableCredential) {\n MessageValidator.validateSync(options.credential.credential)\n }\n\n credential =\n options.credential instanceof W3cJwtVerifiableCredential\n ? options.credential\n : W3cJwtVerifiableCredential.fromSerializedJwt(options.credential)\n\n // Verify the JWT payload (verifies whether it's not expired, etc...)\n credential.jwt.payload.validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuer = await resolveJwtSigner(agentContext, {\n alg: credential.jwt.header.alg as KnownJwaSignatureAlgorithm,\n kid: credential.jwt.header.kid,\n iss: credential.jwt.payload.iss,\n purpose: ['assertionMethod'],\n })\n const issuerVerificationMethod = issuer.verificationMethod\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedCredentialSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n let signatureResult: VerifyJwsResult | undefined\n try {\n // Verify the JWS signature\n signatureResult = await this.jwsService.verifyJws(agentContext, {\n jws: credential.jwt.serializedJwt,\n // We have pre-fetched the key based on the issuer/signer of the credential\n jwsSigner: {\n method: 'did',\n jwk: issuerPublicKey,\n didUrl: issuerVerificationMethod.id,\n },\n })\n\n if (!signatureResult.isValid) {\n validationResults.validations.signature = {\n isValid: false,\n error: new CredoError('Invalid JWS signature'),\n }\n } else {\n validationResults.validations.signature = {\n isValid: true,\n }\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n const isSignedByIssuerKey = signatureResult?.jwsSigners.some(\n (jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint\n )\n validationResults.validations.issuerIsSigner = isSignedByIssuerKey\n ? validateSignerIsExpectedParty(issuer, credential.issuerId, 'issuer')\n : { isValid: false, error: new CredoError('Credential is not signed by the issuer of the credential') }\n\n // Validate credentialStatus\n if (verifyCredentialStatus && !credential.credentialStatus) {\n validationResults.validations.credentialStatus = {\n isValid: true,\n }\n } else if (verifyCredentialStatus && credential.credentialStatus) {\n validationResults.validations.credentialStatus = {\n isValid: false,\n error: new CredoError('Verifying credential status is not supported for JWT VCs'),\n }\n }\n\n validationResults.isValid = Object.values(validationResults.validations).every((v) => v.isValid)\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n /**\n * Signs a presentation including the credentials it includes\n *\n * @param presentation the presentation to be signed\n * @returns the signed presentation\n */\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cJwtSignPresentationOptions\n ): Promise<W3cJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // Get the JWT payload for the JWT based on the JWT Encoding rules form the VC-DATA-MODEL\n // https://www.w3.org/TR/vc-data-model/#jwt-encoding\n const jwtPayload = getJwtPayloadFromPresentation(options.presentation)\n\n // Set the nonce so it's included in the signature\n jwtPayload.additionalClaims.nonce = options.challenge\n jwtPayload.aud = options.domain\n\n const publicJwk = await this.resolveVerificationMethod(agentContext, options.verificationMethod, ['authentication'])\n\n const jwt = await this.jwsService.createJwsCompact(agentContext, {\n payload: jwtPayload,\n keyId: publicJwk.keyId,\n protectedHeaderOptions: {\n typ: 'JWT',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n // TODO: this re-parses and validates the presentation in the JWT, which is not necessary.\n // We should somehow create an instance of W3cJwtVerifiablePresentation directly from the JWT\n const jwtVp = W3cJwtVerifiablePresentation.fromSerializedJwt(jwt)\n\n return jwtVp\n }\n\n /**\n * Verifies a presentation including the credentials it includes\n *\n * @param presentation the presentation to be verified\n * @returns the verification result\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cJwtVerifyPresentationOptions\n ): Promise<W3cVerifyPresentationResult> {\n const validationResults: W3cVerifyPresentationResult = {\n isValid: false,\n validations: {},\n }\n\n try {\n let presentation: W3cJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cJwtVerifiablePresentation) {\n MessageValidator.validateSync(options.presentation.presentation)\n }\n\n presentation =\n options.presentation instanceof W3cJwtVerifiablePresentation\n ? options.presentation\n : W3cJwtVerifiablePresentation.fromSerializedJwt(options.presentation)\n\n // Verify the JWT payload (verifies whether it's not expired, etc...)\n presentation.jwt.payload.validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n // Make sure challenge matches nonce\n if (options.challenge !== presentation.jwt.payload.additionalClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.jwt.payload.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const prover = await resolveJwtSigner(agentContext, {\n alg: presentation.jwt.header.alg as KnownJwaSignatureAlgorithm,\n kid: presentation.jwt.header.kid,\n iss: presentation.jwt.payload.iss,\n purpose: ['authentication'],\n })\n const proverVerificationMethod = prover.verificationMethod\n const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod)\n\n let signatureResult: VerifyJwsResult | undefined\n try {\n // Verify the JWS signature\n signatureResult = await this.jwsService.verifyJws(agentContext, {\n jws: presentation.jwt.serializedJwt,\n allowedJwsSignerMethods: ['did'],\n jwsSigner: {\n method: 'did',\n didUrl: proverVerificationMethod.id,\n jwk: proverPublicKey,\n },\n trustedCertificates: [],\n })\n\n if (!signatureResult.isValid) {\n validationResults.validations.presentationSignature = {\n isValid: false,\n error: new CredoError('Invalid JWS signature on presentation'),\n }\n } else {\n validationResults.validations.presentationSignature = {\n isValid: true,\n }\n }\n } catch (error) {\n validationResults.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n validationResults.validations.holderIsSigner = validateSignerIsExpectedParty(\n prover,\n presentation.holderId,\n 'holder'\n )\n\n // To keep things simple, we only support JWT VCs in JWT VPs for now\n const credentials = asArray(presentation.presentation.verifiableCredential)\n\n // Verify all credentials in parallel, and await the result\n validationResults.validations.credentials = await Promise.all(\n credentials.map(async (credential) => {\n if (credential instanceof W3cJsonLdVerifiableCredential) {\n return {\n isValid: false,\n error: new CredoError(\n 'Credential is of format ldp_vc. presentations in jwt_vp format can only contain credentials in jwt_vc format'\n ),\n validations: {},\n }\n }\n\n const credentialResult = await this.verifyCredential(agentContext, {\n credential,\n verifyCredentialStatus: options.verifyCredentialStatus,\n trustedIssuers: options.trustedIssuers,\n })\n\n const credentialSubjectAuthentication = validateCredentialSubjectAuthentication(\n credential.credentialSubjectIds,\n prover.signer\n )\n\n return {\n ...credentialResult,\n isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,\n validations: {\n ...credentialResult.validations,\n credentialSubjectAuthentication,\n },\n }\n })\n )\n\n // Deeply nested check whether all validations have passed\n validationResults.isValid = Object.values(validationResults.validations).every((v) =>\n Array.isArray(v) ? v.every((vv) => vv.isValid) : v.isValid\n )\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n private async resolveVerificationMethod(\n agentContext: AgentContext,\n verificationMethod: string,\n allowsPurposes?: DidPurpose[]\n ): Promise<PublicJwk> {\n const dids = agentContext.resolve(DidsApi)\n\n const parsedDid = parseDid(verificationMethod)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(parsedDid.did)\n const verificationMethodObject = didDocument.dereferenceKey(verificationMethod, allowsPurposes)\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethodObject)\n\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))\n ?.kmsKeyId ?? publicJwk.legacyKeyId\n\n return publicJwk\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"W3cV2JwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cV2JwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAqCa;UACH;EAEW,YAAA,YAAY;;;;EAOlB,eACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAwCE,iBACX,cAAc,cACd,SAAS,kCACR,QAAQ;;;;;;;EAoJE,iBACX,cAAc,cACd,SAAS,kCACR,QAAQ;;;;;;;EAmCE,mBACX,cAAc,cACd,SAAS,oCACR,QAAQ;UA6HH;UAoCA"}
1
+ {"version":3,"file":"W3cV2JwtCredentialService.d.mts","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cV2JwtCredentialService.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAsCa;UACH;EAEW,YAAA,YAAY;;;;EAOlB,eACX,cAAc,cACd,SAAS,gCACR,QAAQ;;;;;;;EAwCE,iBACX,cAAc,cACd,SAAS,kCACR,QAAQ;;;;;;;EA8HE,iBACX,cAAc,cACd,SAAS,kCACR,QAAQ;;;;;;;EAmCE,mBACX,cAAc,cACd,SAAS,oCACR,QAAQ;UAgHH;UAoCA"}
@@ -13,11 +13,12 @@ import { JwsService } from "../../../crypto/JwsService.mjs";
13
13
  import { getPublicJwkFromVerificationMethod } from "../../dids/domain/key-type/keyDidMapping.mjs";
14
14
  import { TrustedIssuerContext } from "../../../agent/TrustedIssuerContext.mjs";
15
15
  import { validateVc2ContextBaseline, validateVc2CredentialStatus, validateVc2CredentialValidityPeriod } from "../validators.mjs";
16
+ import { validateSignerIsExpectedParty } from "../resolveSigner.mjs";
16
17
  import "../../../crypto/index.mjs";
17
18
  import { extractKeyFromHolderBinding } from "../../sd-jwt-vc/utils.mjs";
18
19
  import { W3cV2JwtVerifiableCredential } from "./W3cV2JwtVerifiableCredential.mjs";
19
20
  import { W3cV2JwtVerifiablePresentation } from "./W3cV2JwtVerifiablePresentation.mjs";
20
- import { extractHolderFromPresentationCredentials, getVerificationMethodForJwt, validateAndResolveVerificationMethod } from "../v2-jwt-utils.mjs";
21
+ import { extractHolderFromPresentationCredentials, getSignerForJwt, validateAndResolveVerificationMethod } from "../v2-jwt-utils.mjs";
21
22
  //#region src/modules/vc/jwt-vc/W3cV2JwtCredentialService.ts
22
23
  let W3cV2JwtCredentialService = class W3cV2JwtCredentialService {
23
24
  constructor(jwsService) {
@@ -30,7 +31,7 @@ let W3cV2JwtCredentialService = class W3cV2JwtCredentialService {
30
31
  MessageValidator.validateSync(options.credential);
31
32
  const jwtPayload = new JwtPayload({ additionalClaims: JsonTransformer.toJSON(options.credential) });
32
33
  jwtPayload.iat = nowInSeconds();
33
- jwtPayload.additionalClaims.cnf = options.holder ? (await extractKeyFromHolderBinding(agentContext, options.holder)).cnf : void 0;
34
+ jwtPayload.additionalClaims.cnf = options.holder ? (await extractKeyFromHolderBinding(agentContext, options.holder, { didPurposes: ["authentication"] })).cnf : void 0;
34
35
  const publicJwk = await validateAndResolveVerificationMethod(agentContext, options.verificationMethod, ["assertionMethod"]);
35
36
  const jwt = await this.jwsService.createJwsCompact(agentContext, {
36
37
  payload: jwtPayload,
@@ -81,9 +82,10 @@ let W3cV2JwtCredentialService = class W3cV2JwtCredentialService {
81
82
  };
82
83
  return validationResults;
83
84
  }
84
- const issuerVerificationMethod = await getVerificationMethodForJwt(agentContext, credential, ["assertionMethod"]);
85
+ const issuer = await getSignerForJwt(agentContext, credential, ["assertionMethod"]);
86
+ const issuerVerificationMethod = issuer.verificationMethod;
85
87
  const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod);
86
- await TrustedIssuerContext.ensureTrustedSigner(agentContext, {
88
+ await TrustedIssuerContext.ensureTrustedCredentialSigner(agentContext, {
87
89
  signer: {
88
90
  method: "did",
89
91
  didUrl: issuerVerificationMethod.id
@@ -114,16 +116,11 @@ let W3cV2JwtCredentialService = class W3cV2JwtCredentialService {
114
116
  error
115
117
  };
116
118
  }
117
- if (credential.resolvedCredential.issuerId !== issuerVerificationMethod.controller) validationResults.validations.issuerIsSigner = {
118
- isValid: false,
119
- error: new CredoError(`Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.resolvedCredential.issuerId}'`)
120
- };
121
- else validationResults.validations.issuerIsSigner = { isValid: true };
122
- if (!signatureResult?.jwsSigners.some((jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint)) validationResults.validations.issuerIsSigner = {
119
+ const isSignedByIssuerKey = signatureResult?.jwsSigners.some((jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint);
120
+ validationResults.validations.issuerIsSigner = isSignedByIssuerKey ? validateSignerIsExpectedParty(issuer, credential.resolvedCredential.issuerId, "issuer") : {
123
121
  isValid: false,
124
122
  error: new CredoError("Credential is not signed by the issuer of the credential")
125
123
  };
126
- else validationResults.validations.issuerIsSigner = { isValid: true };
127
124
  validationResults.isValid = Object.values(validationResults.validations).every((validation) => validation?.isValid === true);
128
125
  return validationResults;
129
126
  } catch (error) {
@@ -189,7 +186,8 @@ let W3cV2JwtCredentialService = class W3cV2JwtCredentialService {
189
186
  };
190
187
  return validationResults;
191
188
  }
192
- const proverVerificationMethod = await getVerificationMethodForJwt(agentContext, presentation, ["authentication"]);
189
+ const prover = await getSignerForJwt(agentContext, presentation, ["authentication"]);
190
+ const proverVerificationMethod = prover.verificationMethod;
193
191
  const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod);
194
192
  try {
195
193
  if (!(await this.jwsService.verifyJws(agentContext, {
@@ -212,11 +210,7 @@ let W3cV2JwtCredentialService = class W3cV2JwtCredentialService {
212
210
  error
213
211
  };
214
212
  }
215
- if (presentation.resolvedPresentation.holderId && proverVerificationMethod.controller !== presentation.resolvedPresentation.holderId) validationResults.presentation.validations.holderIsSigner = {
216
- isValid: false,
217
- error: new CredoError(`Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.resolvedPresentation.holderId}'`)
218
- };
219
- else validationResults.presentation.validations.holderIsSigner = { isValid: true };
213
+ validationResults.presentation.validations.holderIsSigner = validateSignerIsExpectedParty(prover, presentation.resolvedPresentation.holderId, "holder");
220
214
  validationResults.presentation.isValid = Object.values(validationResults.presentation.validations).every((validation) => validation.isValid);
221
215
  validationResults.isValid = validationResults.presentation.isValid;
222
216
  return validationResults;