@sphereon/ssi-sdk.credential-vcdm1-jwt-provider 0.33.1-feature.jose.vcdm.59
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/LICENSE +201 -0
- package/dist/index.cjs +297 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +38 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +266 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
- package/src/__tests__/issue-verify-flow-jwt.test.ts +125 -0
- package/src/agent/CredentialProviderJWT.ts +287 -0
- package/src/index.ts +1 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// src/agent/CredentialProviderJWT.ts
|
|
5
|
+
import { pickSigningKey, preProcessCredentialPayload, preProcessPresentation } from "@sphereon/ssi-sdk.credential-vcdm";
|
|
6
|
+
import canonicalize from "canonicalize";
|
|
7
|
+
import { createVerifiableCredentialJwt, createVerifiablePresentationJwt, normalizeCredential, normalizePresentation, verifyCredential as verifyCredentialJWT, verifyPresentation as verifyPresentationJWT } from "did-jwt-vc";
|
|
8
|
+
import { decodeJWT } from "did-jwt";
|
|
9
|
+
import Debug from "debug";
|
|
10
|
+
import { asArray, intersect } from "@sphereon/ssi-sdk.core";
|
|
11
|
+
import { isVcdm1Credential } from "@sphereon/ssi-types";
|
|
12
|
+
var debug = Debug("sphereon:ssi-sdk:credential-jwt");
|
|
13
|
+
var CredentialProviderJWT = class {
|
|
14
|
+
static {
|
|
15
|
+
__name(this, "CredentialProviderJWT");
|
|
16
|
+
}
|
|
17
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.matchKeyForType} */
|
|
18
|
+
matchKeyForType(key) {
|
|
19
|
+
return this.matchKeyForJWT(key);
|
|
20
|
+
}
|
|
21
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.getTypeProofFormat} */
|
|
22
|
+
getTypeProofFormat() {
|
|
23
|
+
return "jwt";
|
|
24
|
+
}
|
|
25
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.canIssueCredentialType} */
|
|
26
|
+
canIssueCredentialType(args) {
|
|
27
|
+
return args.proofFormat === "jwt";
|
|
28
|
+
}
|
|
29
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.canVerifyDocumentType */
|
|
30
|
+
canVerifyDocumentType(args) {
|
|
31
|
+
const { document } = args;
|
|
32
|
+
const jwt = typeof document === "string" ? document : document?.proof?.jwt;
|
|
33
|
+
if (!jwt) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const { payload } = decodeJWT(jwt);
|
|
37
|
+
if ("vc" in payload) {
|
|
38
|
+
return isVcdm1Credential(payload.vc);
|
|
39
|
+
} else if ("vp" in payload) {
|
|
40
|
+
return isVcdm1Credential(payload.vp);
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.createVerifiableCredential} */
|
|
45
|
+
async createVerifiableCredential(args, context) {
|
|
46
|
+
let { keyRef, removeOriginalFields, ...otherOptions } = args;
|
|
47
|
+
const { credential, issuer } = preProcessCredentialPayload(args);
|
|
48
|
+
let identifier;
|
|
49
|
+
try {
|
|
50
|
+
identifier = await context.agent.didManagerGet({
|
|
51
|
+
did: issuer
|
|
52
|
+
});
|
|
53
|
+
} catch (e) {
|
|
54
|
+
throw new Error(`invalid_argument: ${credential.issuer} must be a DID managed by this agent. ${e}`);
|
|
55
|
+
}
|
|
56
|
+
const key = await pickSigningKey({
|
|
57
|
+
identifier,
|
|
58
|
+
kmsKeyRef: keyRef
|
|
59
|
+
}, context);
|
|
60
|
+
debug("Signing VC with", identifier.did);
|
|
61
|
+
let alg = "ES256";
|
|
62
|
+
if (key.type === "Ed25519") {
|
|
63
|
+
alg = "EdDSA";
|
|
64
|
+
} else if (key.type === "Secp256k1") {
|
|
65
|
+
alg = "ES256K";
|
|
66
|
+
}
|
|
67
|
+
const signer = this.wrapSigner(context, key, alg);
|
|
68
|
+
const jwt = await createVerifiableCredentialJwt(credential, {
|
|
69
|
+
did: identifier.did,
|
|
70
|
+
signer,
|
|
71
|
+
alg,
|
|
72
|
+
...key.meta.verificationMethod.id && {
|
|
73
|
+
kid: key.meta.verificationMethod.id
|
|
74
|
+
}
|
|
75
|
+
}, {
|
|
76
|
+
removeOriginalFields,
|
|
77
|
+
...otherOptions
|
|
78
|
+
});
|
|
79
|
+
debug(jwt);
|
|
80
|
+
return normalizeCredential(jwt);
|
|
81
|
+
}
|
|
82
|
+
/** {@inheritdoc ICredentialVerifier.verifyCredential} */
|
|
83
|
+
async verifyCredential(args, context) {
|
|
84
|
+
let { credential, policies, ...otherOptions } = args;
|
|
85
|
+
let verifiedCredential;
|
|
86
|
+
let verificationResult = {
|
|
87
|
+
verified: false
|
|
88
|
+
};
|
|
89
|
+
let jwt = typeof credential === "string" ? credential : asArray(credential.proof)[0].jwt;
|
|
90
|
+
let errorCode, message;
|
|
91
|
+
const resolver = {
|
|
92
|
+
resolve: /* @__PURE__ */ __name((didUrl) => context.agent.resolveDid({
|
|
93
|
+
didUrl,
|
|
94
|
+
options: otherOptions?.resolutionOptions
|
|
95
|
+
}), "resolve")
|
|
96
|
+
};
|
|
97
|
+
try {
|
|
98
|
+
verificationResult = await verifyCredentialJWT(jwt, resolver, {
|
|
99
|
+
...otherOptions,
|
|
100
|
+
policies: {
|
|
101
|
+
...policies,
|
|
102
|
+
nbf: policies?.nbf ?? policies?.issuanceDate,
|
|
103
|
+
iat: policies?.iat ?? policies?.issuanceDate,
|
|
104
|
+
exp: policies?.exp ?? policies?.expirationDate,
|
|
105
|
+
aud: policies?.aud ?? policies?.audience
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
verifiedCredential = verificationResult.verifiableCredential;
|
|
109
|
+
if (typeof credential !== "string" && asArray(credential.proof)[0].type === "JwtProof2020") {
|
|
110
|
+
const credentialCopy = JSON.parse(JSON.stringify(credential));
|
|
111
|
+
delete credentialCopy.proof.jwt;
|
|
112
|
+
const verifiedCopy = JSON.parse(JSON.stringify(verifiedCredential));
|
|
113
|
+
delete verifiedCopy.proof.jwt;
|
|
114
|
+
if (canonicalize(credentialCopy) !== canonicalize(verifiedCopy)) {
|
|
115
|
+
verificationResult.verified = false;
|
|
116
|
+
verificationResult.error = new Error("invalid_credential: Credential JSON does not match JWT payload");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
} catch (e) {
|
|
120
|
+
errorCode = e.errorCode;
|
|
121
|
+
message = e.message;
|
|
122
|
+
}
|
|
123
|
+
if (verificationResult.verified) {
|
|
124
|
+
return verificationResult;
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
verified: false,
|
|
128
|
+
error: {
|
|
129
|
+
message,
|
|
130
|
+
errorCode: errorCode ? errorCode : message?.split(":")[0]
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.createVerifiablePresentation} */
|
|
135
|
+
async createVerifiablePresentation(args, context) {
|
|
136
|
+
const { presentation, holder } = preProcessPresentation(args);
|
|
137
|
+
let { domain, challenge, removeOriginalFields, keyRef, now, ...otherOptions } = args;
|
|
138
|
+
let identifier;
|
|
139
|
+
try {
|
|
140
|
+
identifier = await context.agent.didManagerGet({
|
|
141
|
+
did: holder
|
|
142
|
+
});
|
|
143
|
+
} catch (e) {
|
|
144
|
+
throw new Error("invalid_argument: presentation.holder must be a DID managed by this agent");
|
|
145
|
+
}
|
|
146
|
+
const key = await pickSigningKey({
|
|
147
|
+
identifier,
|
|
148
|
+
kmsKeyRef: keyRef
|
|
149
|
+
}, context);
|
|
150
|
+
debug("Signing VP with", identifier.did);
|
|
151
|
+
let alg = "ES256";
|
|
152
|
+
if (key.type === "Ed25519") {
|
|
153
|
+
alg = "EdDSA";
|
|
154
|
+
} else if (key.type === "Secp256k1") {
|
|
155
|
+
alg = "ES256K";
|
|
156
|
+
}
|
|
157
|
+
const signer = this.wrapSigner(context, key, alg);
|
|
158
|
+
const jwt = await createVerifiablePresentationJwt(presentation, {
|
|
159
|
+
did: identifier.did,
|
|
160
|
+
signer,
|
|
161
|
+
alg
|
|
162
|
+
}, {
|
|
163
|
+
removeOriginalFields,
|
|
164
|
+
challenge,
|
|
165
|
+
domain,
|
|
166
|
+
...otherOptions
|
|
167
|
+
});
|
|
168
|
+
debug(jwt);
|
|
169
|
+
return normalizePresentation(jwt);
|
|
170
|
+
}
|
|
171
|
+
/** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.verifyPresentation} */
|
|
172
|
+
async verifyPresentation(args, context) {
|
|
173
|
+
let { presentation, domain, challenge, fetchRemoteContexts, policies, ...otherOptions } = args;
|
|
174
|
+
let jwt;
|
|
175
|
+
if (typeof presentation === "string") {
|
|
176
|
+
jwt = presentation;
|
|
177
|
+
} else {
|
|
178
|
+
jwt = asArray(presentation.proof)[0].jwt;
|
|
179
|
+
}
|
|
180
|
+
const resolver = {
|
|
181
|
+
resolve: /* @__PURE__ */ __name((didUrl) => context.agent.resolveDid({
|
|
182
|
+
didUrl,
|
|
183
|
+
options: otherOptions?.resolutionOptions
|
|
184
|
+
}), "resolve")
|
|
185
|
+
};
|
|
186
|
+
let audience = domain;
|
|
187
|
+
if (!audience) {
|
|
188
|
+
const { payload } = await decodeJWT(jwt);
|
|
189
|
+
if (payload.aud) {
|
|
190
|
+
const intendedAudience = asArray(payload.aud);
|
|
191
|
+
const managedDids = await context.agent.didManagerFind();
|
|
192
|
+
const filtered = managedDids.filter((identifier) => intendedAudience.includes(identifier.did));
|
|
193
|
+
if (filtered.length > 0) {
|
|
194
|
+
audience = filtered[0].did;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
let message, errorCode;
|
|
199
|
+
try {
|
|
200
|
+
const result = await verifyPresentationJWT(jwt, resolver, {
|
|
201
|
+
challenge,
|
|
202
|
+
domain,
|
|
203
|
+
audience,
|
|
204
|
+
policies: {
|
|
205
|
+
...policies,
|
|
206
|
+
nbf: policies?.nbf ?? policies?.issuanceDate,
|
|
207
|
+
iat: policies?.iat ?? policies?.issuanceDate,
|
|
208
|
+
exp: policies?.exp ?? policies?.expirationDate,
|
|
209
|
+
aud: policies?.aud ?? policies?.audience
|
|
210
|
+
},
|
|
211
|
+
...otherOptions
|
|
212
|
+
});
|
|
213
|
+
if (result) {
|
|
214
|
+
return {
|
|
215
|
+
verified: true,
|
|
216
|
+
verifiablePresentation: result
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
} catch (e) {
|
|
220
|
+
message = e.message;
|
|
221
|
+
errorCode = e.errorCode;
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
verified: false,
|
|
225
|
+
error: {
|
|
226
|
+
message,
|
|
227
|
+
errorCode: errorCode ? errorCode : message?.split(":")[0]
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Checks if a key is suitable for signing JWT payloads.
|
|
233
|
+
* @param key - the key to check
|
|
234
|
+
* @param context - the Veramo agent context, unused here
|
|
235
|
+
*
|
|
236
|
+
* @beta
|
|
237
|
+
*/
|
|
238
|
+
matchKeyForJWT(key) {
|
|
239
|
+
switch (key.type) {
|
|
240
|
+
case "Ed25519":
|
|
241
|
+
case "Secp256r1":
|
|
242
|
+
return true;
|
|
243
|
+
case "Secp256k1":
|
|
244
|
+
return intersect(key.meta?.algorithms ?? [], [
|
|
245
|
+
"ES256K",
|
|
246
|
+
"ES256K-R"
|
|
247
|
+
]).length > 0;
|
|
248
|
+
default:
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
wrapSigner(context, key, algorithm) {
|
|
253
|
+
return async (data) => {
|
|
254
|
+
const result = await context.agent.keyManagerSign({
|
|
255
|
+
keyRef: key.kid,
|
|
256
|
+
data,
|
|
257
|
+
algorithm
|
|
258
|
+
});
|
|
259
|
+
return result;
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
export {
|
|
264
|
+
CredentialProviderJWT
|
|
265
|
+
};
|
|
266
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agent/CredentialProviderJWT.ts"],"sourcesContent":["import type { IAgentContext, IIdentifier, IKey, IKeyManager, IVerifyResult, VerifiableCredential, VerifierAgentContext } from '@veramo/core'\nimport {\n type ICanIssueCredentialTypeArgs,\n type ICanVerifyDocumentTypeArgs,\n type ICreateVerifiableCredentialLDArgs,\n type ICreateVerifiablePresentationLDArgs,\n type IVcdmCredentialProvider,\n type IVcdmIssuerAgentContext,\n IVerifyCredentialLDArgs,\n IVerifyPresentationLDArgs,\n pickSigningKey,\n preProcessCredentialPayload,\n preProcessPresentation,\n} from '@sphereon/ssi-sdk.credential-vcdm'\n\nimport canonicalize from 'canonicalize'\n\nimport {\n createVerifiableCredentialJwt,\n createVerifiablePresentationJwt,\n normalizeCredential,\n normalizePresentation,\n verifyCredential as verifyCredentialJWT,\n verifyPresentation as verifyPresentationJWT,\n // @ts-ignore\n} from 'did-jwt-vc'\n\nimport { type Resolvable } from 'did-resolver'\n\nimport { decodeJWT } from 'did-jwt'\n\nimport Debug from 'debug'\nimport { asArray, intersect, VerifiableCredentialSP, VerifiablePresentationSP } from '@sphereon/ssi-sdk.core'\nimport { isVcdm1Credential } from '@sphereon/ssi-types'\n\nconst debug = Debug('sphereon:ssi-sdk:credential-jwt')\n\n/**\n * A handler that implements the {@link IVcdmCredentialProvider} methods.\n *\n * @beta This API may change without a BREAKING CHANGE notice.\n */\nexport class CredentialProviderJWT implements IVcdmCredentialProvider {\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.matchKeyForType} */\n matchKeyForType(key: IKey): boolean {\n return this.matchKeyForJWT(key)\n }\n\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.getTypeProofFormat} */\n getTypeProofFormat(): string {\n return 'jwt'\n }\n\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.canIssueCredentialType} */\n canIssueCredentialType(args: ICanIssueCredentialTypeArgs): boolean {\n return args.proofFormat === 'jwt'\n }\n\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.canVerifyDocumentType */\n canVerifyDocumentType(args: ICanVerifyDocumentTypeArgs): boolean {\n const { document } = args\n const jwt = typeof document === 'string' ? document : (<VerifiableCredential>document)?.proof?.jwt\n if (!jwt) {\n return false\n }\n const { payload } = decodeJWT(jwt)\n if ('vc' in payload) {\n return isVcdm1Credential(payload.vc)\n } else if ('vp' in payload) {\n return isVcdm1Credential(payload.vp)\n }\n return false\n }\n\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.createVerifiableCredential} */\n async createVerifiableCredential(args: ICreateVerifiableCredentialLDArgs, context: IVcdmIssuerAgentContext): Promise<VerifiableCredentialSP> {\n let { keyRef, removeOriginalFields, ...otherOptions } = args\n\n const { credential, issuer } = preProcessCredentialPayload(args)\n let identifier: IIdentifier\n try {\n identifier = await context.agent.didManagerGet({ did: issuer })\n } catch (e) {\n throw new Error(`invalid_argument: ${credential.issuer} must be a DID managed by this agent. ${e}`)\n }\n\n const key = await pickSigningKey({ identifier, kmsKeyRef: keyRef }, context)\n\n debug('Signing VC with', identifier.did)\n let alg = 'ES256'\n if (key.type === 'Ed25519') {\n alg = 'EdDSA'\n } else if (key.type === 'Secp256k1') {\n alg = 'ES256K'\n }\n\n const signer = this.wrapSigner(context, key, alg)\n const jwt = await createVerifiableCredentialJwt(\n credential as any,\n { did: identifier.did, signer, alg, ...(key.meta.verificationMethod.id && { kid: key.meta.verificationMethod.id }) },\n { removeOriginalFields, ...otherOptions },\n )\n //FIXME: flagging this as a potential privacy leak.\n debug(jwt)\n return normalizeCredential(jwt)\n }\n\n /** {@inheritdoc ICredentialVerifier.verifyCredential} */\n async verifyCredential(args: IVerifyCredentialLDArgs, context: VerifierAgentContext): Promise<IVerifyResult> {\n let { credential, policies, ...otherOptions } = args\n let verifiedCredential: VerifiableCredential\n let verificationResult: IVerifyResult = { verified: false }\n let jwt: string = typeof credential === 'string' ? credential : asArray(credential.proof)[0].jwt\n let errorCode, message\n const resolver = {\n resolve: (didUrl: string) =>\n context.agent.resolveDid({\n didUrl,\n options: otherOptions?.resolutionOptions,\n }),\n } as Resolvable\n try {\n // needs broader credential as well to check equivalence with jwt\n verificationResult = await verifyCredentialJWT(jwt, resolver, {\n ...otherOptions,\n policies: {\n ...policies,\n nbf: policies?.nbf ?? policies?.issuanceDate,\n iat: policies?.iat ?? policies?.issuanceDate,\n exp: policies?.exp ?? policies?.expirationDate,\n aud: policies?.aud ?? policies?.audience,\n },\n })\n verifiedCredential = verificationResult.verifiableCredential\n\n // if credential was presented with other fields, make sure those fields match what's in the JWT\n if (typeof credential !== 'string' && asArray(credential.proof)[0].type === 'JwtProof2020') {\n const credentialCopy = JSON.parse(JSON.stringify(credential))\n delete credentialCopy.proof.jwt\n\n const verifiedCopy = JSON.parse(JSON.stringify(verifiedCredential))\n delete verifiedCopy.proof.jwt\n\n if (canonicalize(credentialCopy) !== canonicalize(verifiedCopy)) {\n verificationResult.verified = false\n verificationResult.error = new Error('invalid_credential: Credential JSON does not match JWT payload')\n }\n }\n } catch (e: any) {\n errorCode = e.errorCode\n message = e.message\n }\n if (verificationResult.verified) {\n return verificationResult\n }\n return {\n verified: false,\n error: {\n message,\n errorCode: errorCode ? errorCode : message?.split(':')[0],\n },\n }\n }\n\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.createVerifiablePresentation} */\n async createVerifiablePresentation(args: ICreateVerifiablePresentationLDArgs, context: IVcdmIssuerAgentContext): Promise<VerifiablePresentationSP> {\n const { presentation, holder } = preProcessPresentation(args)\n let { domain, challenge, removeOriginalFields, keyRef, now, ...otherOptions } = args\n\n let identifier: IIdentifier\n try {\n identifier = await context.agent.didManagerGet({ did: holder })\n } catch (e) {\n throw new Error('invalid_argument: presentation.holder must be a DID managed by this agent')\n }\n const key = await pickSigningKey({ identifier, kmsKeyRef: keyRef }, context)\n\n debug('Signing VP with', identifier.did)\n let alg = 'ES256'\n if (key.type === 'Ed25519') {\n alg = 'EdDSA'\n } else if (key.type === 'Secp256k1') {\n alg = 'ES256K'\n }\n\n const signer = this.wrapSigner(context, key, alg)\n const jwt = await createVerifiablePresentationJwt(\n presentation as any,\n { did: identifier.did, signer, alg },\n { removeOriginalFields, challenge, domain, ...otherOptions },\n )\n //FIXME: flagging this as a potential privacy leak.\n debug(jwt)\n return normalizePresentation(jwt)\n }\n\n /** {@inheritdoc @veramo/credential-w3c#AbstractCredentialProvider.verifyPresentation} */\n async verifyPresentation(args: IVerifyPresentationLDArgs, context: VerifierAgentContext): Promise<IVerifyResult> {\n let { presentation, domain, challenge, fetchRemoteContexts, policies, ...otherOptions } = args\n let jwt: string\n if (typeof presentation === 'string') {\n jwt = presentation\n } else {\n jwt = asArray(presentation.proof)[0].jwt\n }\n const resolver = {\n resolve: (didUrl: string) =>\n context.agent.resolveDid({\n didUrl,\n options: otherOptions?.resolutionOptions,\n }),\n } as Resolvable\n\n let audience = domain\n if (!audience) {\n const { payload } = await decodeJWT(jwt)\n if (payload.aud) {\n // automatically add a managed DID as audience if one is found\n const intendedAudience = asArray(payload.aud)\n const managedDids = await context.agent.didManagerFind()\n const filtered = managedDids.filter((identifier) => intendedAudience.includes(identifier.did))\n if (filtered.length > 0) {\n audience = filtered[0].did\n }\n }\n }\n\n let message, errorCode\n try {\n const result = await verifyPresentationJWT(jwt, resolver, {\n challenge,\n domain,\n audience,\n policies: {\n ...policies,\n nbf: policies?.nbf ?? policies?.issuanceDate,\n iat: policies?.iat ?? policies?.issuanceDate,\n exp: policies?.exp ?? policies?.expirationDate,\n aud: policies?.aud ?? policies?.audience,\n },\n ...otherOptions,\n })\n if (result) {\n return {\n verified: true,\n verifiablePresentation: result,\n }\n }\n } catch (e: any) {\n message = e.message\n errorCode = e.errorCode\n }\n return {\n verified: false,\n error: {\n message,\n errorCode: errorCode ? errorCode : message?.split(':')[0],\n },\n }\n }\n\n /**\n * Checks if a key is suitable for signing JWT payloads.\n * @param key - the key to check\n * @param context - the Veramo agent context, unused here\n *\n * @beta\n */\n matchKeyForJWT(key: IKey): boolean {\n switch (key.type) {\n case 'Ed25519':\n case 'Secp256r1':\n return true\n case 'Secp256k1':\n return intersect(key.meta?.algorithms ?? [], ['ES256K', 'ES256K-R']).length > 0\n default:\n return false\n }\n }\n\n wrapSigner(context: IAgentContext<Pick<IKeyManager, 'keyManagerSign'>>, key: IKey, algorithm?: string) {\n return async (data: string | Uint8Array): Promise<string> => {\n const result = await context.agent.keyManagerSign({ keyRef: key.kid, data: <string>data, algorithm })\n return result\n }\n }\n}\n"],"mappings":"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","names":["pickSigningKey","preProcessCredentialPayload","preProcessPresentation","canonicalize","createVerifiableCredentialJwt","createVerifiablePresentationJwt","normalizeCredential","normalizePresentation","verifyCredential","verifyCredentialJWT","verifyPresentation","verifyPresentationJWT","decodeJWT","Debug","asArray","intersect","isVcdm1Credential","debug","Debug","CredentialProviderJWT","matchKeyForType","key","matchKeyForJWT","getTypeProofFormat","canIssueCredentialType","args","proofFormat","canVerifyDocumentType","document","jwt","proof","payload","decodeJWT","isVcdm1Credential","vc","vp","createVerifiableCredential","context","keyRef","removeOriginalFields","otherOptions","credential","issuer","preProcessCredentialPayload","identifier","agent","didManagerGet","did","e","Error","pickSigningKey","kmsKeyRef","alg","type","signer","wrapSigner","createVerifiableCredentialJwt","meta","verificationMethod","id","kid","normalizeCredential","verifyCredential","policies","verifiedCredential","verificationResult","verified","asArray","errorCode","message","resolver","resolve","didUrl","resolveDid","options","resolutionOptions","verifyCredentialJWT","nbf","issuanceDate","iat","exp","expirationDate","aud","audience","verifiableCredential","credentialCopy","JSON","parse","stringify","verifiedCopy","canonicalize","error","split","createVerifiablePresentation","presentation","holder","preProcessPresentation","domain","challenge","now","createVerifiablePresentationJwt","normalizePresentation","verifyPresentation","fetchRemoteContexts","intendedAudience","managedDids","didManagerFind","filtered","filter","includes","length","result","verifyPresentationJWT","verifiablePresentation","intersect","algorithms","algorithm","data","keyManagerSign"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sphereon/ssi-sdk.credential-vcdm1-jwt-provider",
|
|
3
|
+
"description": "Plugin for working with JWT Verifiable Credentials & Presentations.",
|
|
4
|
+
"version": "0.33.1-feature.jose.vcdm.59+5f24a990",
|
|
5
|
+
"source": "src/index.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
"react-native": "./dist/index.js",
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"require": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup --config ../../tsup.config.ts --tsconfig ../../tsconfig.tsup.json"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@sphereon/ssi-sdk.core": "0.33.1-feature.jose.vcdm.59+5f24a990",
|
|
26
|
+
"@sphereon/ssi-sdk.credential-vcdm": "0.33.1-feature.jose.vcdm.59+5f24a990",
|
|
27
|
+
"@sphereon/ssi-types": "0.33.1-feature.jose.vcdm.59+5f24a990",
|
|
28
|
+
"@veramo/core": "4.2.0",
|
|
29
|
+
"@veramo/utils": "4.2.0",
|
|
30
|
+
"canonicalize": "^2.0.0",
|
|
31
|
+
"debug": "^4.3.3",
|
|
32
|
+
"did-jwt-vc": "3.1.3",
|
|
33
|
+
"did-resolver": "^4.1.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@sphereon/ssi-sdk-ext.did-provider-key": "0.28.1-feature.jose.vcdm.25",
|
|
37
|
+
"@sphereon/ssi-sdk-ext.key-manager": "0.28.1-feature.jose.vcdm.25",
|
|
38
|
+
"@sphereon/ssi-sdk-ext.kms-local": "0.28.1-feature.jose.vcdm.25",
|
|
39
|
+
"@sphereon/ssi-sdk.agent-config": "0.33.1-feature.jose.vcdm.59+5f24a990",
|
|
40
|
+
"@types/debug": "4.1.8",
|
|
41
|
+
"@veramo/did-manager": "4.2.0",
|
|
42
|
+
"@veramo/did-provider-ethr": "4.2.0",
|
|
43
|
+
"@veramo/did-resolver": "4.2.0",
|
|
44
|
+
"@veramo/key-manager": "4.2.0",
|
|
45
|
+
"ethr-did-resolver": "^11.0.3",
|
|
46
|
+
"typescript": "5.8.3",
|
|
47
|
+
"vitest": "^3.1.2"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"dist/**/*",
|
|
51
|
+
"src/**/*",
|
|
52
|
+
"README.md",
|
|
53
|
+
"LICENSE"
|
|
54
|
+
],
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/decentralized-identity/veramo.git",
|
|
61
|
+
"directory": "packages/credential-jwt"
|
|
62
|
+
},
|
|
63
|
+
"author": "Nick Reynolds <nicholas.s.reynolds@gmail.com>",
|
|
64
|
+
"keywords": [
|
|
65
|
+
"Sphereon",
|
|
66
|
+
"DID",
|
|
67
|
+
"Verifiable Credential",
|
|
68
|
+
"JWT",
|
|
69
|
+
"veramo-plugin"
|
|
70
|
+
],
|
|
71
|
+
"license": "Apache-2.0",
|
|
72
|
+
"moduleDirectories": [
|
|
73
|
+
"node_modules",
|
|
74
|
+
"src"
|
|
75
|
+
],
|
|
76
|
+
"gitHead": "5f24a9904d53b07534cdaf71f2874f8e64b4c845"
|
|
77
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, it } from 'vitest'
|
|
2
|
+
import type { CredentialPayload, IDIDManager, IIdentifier, IResolver, TAgent } from '@veramo/core'
|
|
3
|
+
import { createAgent } from '@sphereon/ssi-sdk.agent-config'
|
|
4
|
+
import { type IVcdmCredentialPlugin, VcdmCredentialPlugin } from '@sphereon/ssi-sdk.credential-vcdm'
|
|
5
|
+
import { DIDManager, MemoryDIDStore } from '@veramo/did-manager'
|
|
6
|
+
import { getDidKeyResolver, SphereonKeyDidProvider } from '@sphereon/ssi-sdk-ext.did-provider-key'
|
|
7
|
+
import { DIDResolverPlugin } from '@veramo/did-resolver'
|
|
8
|
+
import { EthrDIDProvider } from '@veramo/did-provider-ethr'
|
|
9
|
+
import { Resolver } from 'did-resolver'
|
|
10
|
+
import { getResolver as ethrDidResolver } from 'ethr-did-resolver'
|
|
11
|
+
|
|
12
|
+
import 'cross-fetch/polyfill'
|
|
13
|
+
import { CredentialProviderJWT } from '../agent/CredentialProviderJWT'
|
|
14
|
+
import { type ISphereonKeyManager, MemoryKeyStore, MemoryPrivateKeyStore, SphereonKeyManager } from '@sphereon/ssi-sdk-ext.key-manager'
|
|
15
|
+
import { SphereonKeyManagementSystem } from '@sphereon/ssi-sdk-ext.kms-local'
|
|
16
|
+
|
|
17
|
+
const infuraProjectId = '3586660d179141e3801c3895de1c2eba'
|
|
18
|
+
|
|
19
|
+
describe('@sphereon/ssi-sdk.credential-vcdm1-jwt-provider full flow', () => {
|
|
20
|
+
let didKeyIdentifier: IIdentifier
|
|
21
|
+
let didEthrIdentifier: IIdentifier
|
|
22
|
+
let agent: TAgent<IResolver & ISphereonKeyManager & IDIDManager & IVcdmCredentialPlugin>
|
|
23
|
+
const jwt = new CredentialProviderJWT()
|
|
24
|
+
|
|
25
|
+
beforeAll(async () => {
|
|
26
|
+
agent = await createAgent<IResolver & ISphereonKeyManager & IDIDManager & IVcdmCredentialPlugin>({
|
|
27
|
+
plugins: [
|
|
28
|
+
new SphereonKeyManager({
|
|
29
|
+
store: new MemoryKeyStore(),
|
|
30
|
+
kms: {
|
|
31
|
+
local: new SphereonKeyManagementSystem(new MemoryPrivateKeyStore()),
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
new DIDManager({
|
|
35
|
+
providers: {
|
|
36
|
+
'did:key': new SphereonKeyDidProvider({ defaultKms: 'local' }),
|
|
37
|
+
'did:ethr': new EthrDIDProvider({
|
|
38
|
+
defaultKms: 'local',
|
|
39
|
+
network: 'mainnet',
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
store: new MemoryDIDStore(),
|
|
43
|
+
defaultProvider: 'did:key',
|
|
44
|
+
}),
|
|
45
|
+
new DIDResolverPlugin({
|
|
46
|
+
resolver: new Resolver({
|
|
47
|
+
...getDidKeyResolver(),
|
|
48
|
+
...ethrDidResolver({ infuraProjectId }),
|
|
49
|
+
}),
|
|
50
|
+
}),
|
|
51
|
+
new VcdmCredentialPlugin({ issuers: [jwt] }),
|
|
52
|
+
],
|
|
53
|
+
})
|
|
54
|
+
didKeyIdentifier = await agent.didManagerCreate()
|
|
55
|
+
didEthrIdentifier = await agent.didManagerCreate({ provider: 'did:ethr' })
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('issues and verifies JWT credential', async () => {
|
|
59
|
+
const credential: CredentialPayload = {
|
|
60
|
+
issuer: { id: didEthrIdentifier.did },
|
|
61
|
+
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://example.com/1/2/3'],
|
|
62
|
+
type: ['VerifiableCredential', 'Custom'],
|
|
63
|
+
issuanceDate: new Date().toISOString(),
|
|
64
|
+
credentialSubject: {
|
|
65
|
+
id: 'did:web:example.com',
|
|
66
|
+
you: 'Rock',
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
const verifiableCredential = await agent.createVerifiableCredential({
|
|
70
|
+
credential,
|
|
71
|
+
proofFormat: 'jwt',
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
expect(verifiableCredential).toBeDefined()
|
|
75
|
+
|
|
76
|
+
const result = await agent.verifyCredential({
|
|
77
|
+
credential: verifiableCredential,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
expect(result.verified).toBe(true)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('issues credential and verifies presentation', async () => {
|
|
84
|
+
const credential: CredentialPayload = {
|
|
85
|
+
issuer: { id: didEthrIdentifier.did },
|
|
86
|
+
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://veramo.io/contexts/profile/v1'],
|
|
87
|
+
type: ['VerifiableCredential', 'Profile'],
|
|
88
|
+
issuanceDate: new Date().toISOString(),
|
|
89
|
+
credentialSubject: {
|
|
90
|
+
id: didKeyIdentifier.did,
|
|
91
|
+
name: 'Martin, the great',
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
const verifiableCredential1 = await agent.createVerifiableCredential({
|
|
95
|
+
credential,
|
|
96
|
+
proofFormat: 'jwt',
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
const verifiablePresentation = await agent.createVerifiablePresentation({
|
|
100
|
+
presentation: {
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
verifiableCredential: [verifiableCredential1],
|
|
103
|
+
holder: didEthrIdentifier.did,
|
|
104
|
+
},
|
|
105
|
+
challenge: 'SUCCESS',
|
|
106
|
+
proofFormat: 'jwt',
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
expect(verifiablePresentation).toBeDefined()
|
|
110
|
+
|
|
111
|
+
const result = await agent.verifyPresentation({
|
|
112
|
+
presentation: verifiablePresentation,
|
|
113
|
+
challenge: 'SUCCESS',
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
expect(result.verified).toBe(true)
|
|
117
|
+
|
|
118
|
+
const failResult = await agent.verifyPresentation({
|
|
119
|
+
presentation: verifiablePresentation,
|
|
120
|
+
challenge: 'FAILED',
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
expect(failResult.verified).toBe(false)
|
|
124
|
+
})
|
|
125
|
+
})
|