@sphereon/oid4vci-client 0.10.4-unstable.79 → 0.10.4-unstable.80

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.
@@ -29,6 +29,8 @@ import { IDENTIPROOF_ISSUER_URL, IDENTIPROOF_OID4VCI_METADATA, INITIATION_TEST,
29
29
  import { getMockData } from './data/VciDataFixtures';
30
30
 
31
31
  const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN';
32
+ const partialJWT_withoutDid = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJlYmZlYjFmNzEyZWJjNmYxYzI3N';
33
+
32
34
 
33
35
  const jwt1_0_08: Jwt = {
34
36
  header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
@@ -40,8 +42,20 @@ const jwt1_0_13: Jwt = {
40
42
  payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
41
43
  };
42
44
 
45
+ const jwt1_0_08_withoutDid: Jwt = {
46
+ header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
47
+ payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
48
+ };
49
+
50
+ const jwt1_0_13_withoutDid: Jwt = {
51
+ header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'openid4vci-proof+jwt' },
52
+ payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
53
+ };
54
+
43
55
  const kid = 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1';
44
56
 
57
+ const kid_withoutDid = 'ebfeb1f712ebc6f1c276e12ec21/keys/1';
58
+
45
59
  let keypair: KeyPair;
46
60
 
47
61
  async function proofOfPossessionCallbackFunction(args: Jwt, kid?: string): Promise<string> {
@@ -115,6 +129,43 @@ describe('Credential Request Client ', () => {
115
129
  expect(result?.successBody?.credential).toEqual(mockedVC);
116
130
  });
117
131
 
132
+ it('should get success credential response with kid without did', async function () {
133
+ const mockedVC =
134
+ 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImlkIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXSwiaXNzdWVyIjoiaHR0cHM6Ly9leGFtcGxlLmVkdS9pc3N1ZXJzLzU2NTA0OSIsImlzc3VhbmNlRGF0ZSI6IjIwMTAtMDEtMDFUMDA6MDA6MDBaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJlYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJkZWdyZWUiOnsidHlwZSI6IkJhY2hlbG9yRGVncmVlIiwibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMifX19LCJpc3MiOiJodHRwczovL2V4YW1wbGUuZWR1L2lzc3VlcnMvNTY1MDQ5IiwibmJmIjoxMjYyMzA0MDAwLCJqdGkiOiJodHRwOi8vZXhhbXBsZS5lZHUvY3JlZGVudGlhbHMvMzczMiIsInN1YiI6ImViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsImlhdCI6MTcxODM0OTI0MX0.ZtGycBKJUOav5eQYQYH10gjEcVYADNHhKDjntSa57jM2JoEj5ciW7tDEb6MJpFRUxrMk62AVi-OQ8dwW3HnZVw';
135
+ nock('https://oidc4vci.demo.spruceid.com')
136
+ .post(/credential/)
137
+ .reply(200, {
138
+ format: 'jwt-vc',
139
+ credential: mockedVC,
140
+ });
141
+ const credReqClient = CredentialRequestClientBuilder.fromCredentialOfferRequest({ request: INITIATION_TEST })
142
+ .withCredentialEndpoint('https://oidc4vci.demo.spruceid.com/credential')
143
+ .withFormat('jwt_vc')
144
+ .withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential')
145
+ .build();
146
+ const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
147
+ jwt: jwt1_0_13_withoutDid,
148
+ callbacks: {
149
+ signCallback: proofOfPossessionCallbackFunction,
150
+ },
151
+ version: OpenId4VCIVersion.VER_1_0_13,
152
+ })
153
+ // .withEndpointMetadata(metadata)
154
+ .withKid(kid_withoutDid)
155
+ .withClientId('sphereon:wallet')
156
+ .build();
157
+ const credentialRequest = await credReqClient.createCredentialRequest({
158
+ credentialType: 'OpenBadgeCredential',
159
+ proofInput: proof,
160
+ format: 'jwt',
161
+ version: OpenId4VCIVersion.VER_1_0_13,
162
+ });
163
+ expect(credentialRequest.proof?.jwt?.includes(partialJWT_withoutDid)).toBeTruthy();
164
+ expect(credentialRequest.format).toEqual('jwt_vc');
165
+ const result = await credReqClient.acquireCredentialsUsingRequest(credentialRequest);
166
+ expect(result?.successBody?.credential).toEqual(mockedVC);
167
+ });
168
+
118
169
  it('should fail with invalid url', async () => {
119
170
  const credReqClient = CredentialRequestClientBuilder.fromCredentialOfferRequest({ request: INITIATION_TEST })
120
171
  .withCredentialEndpoint('httpsf://oidc4vci.demo.spruceid.com/credential')
@@ -136,6 +187,28 @@ describe('Credential Request Client ', () => {
136
187
  Error(URL_NOT_VALID),
137
188
  );
138
189
  });
190
+
191
+ it('should fail with invalid url', async () => {
192
+ const credReqClient = CredentialRequestClientBuilder.fromCredentialOfferRequest({ request: INITIATION_TEST })
193
+ .withCredentialEndpoint('httpsf://oidc4vci.demo.spruceid.com/credential')
194
+ .withFormat('jwt_vc')
195
+ .withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential')
196
+ .build();
197
+ const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
198
+ jwt: jwt1_0_08_withoutDid,
199
+ callbacks: {
200
+ signCallback: proofOfPossessionCallbackFunction,
201
+ },
202
+ version: OpenId4VCIVersion.VER_1_0_08,
203
+ })
204
+ // .withEndpointMetadata(metadata)
205
+ .withKid(kid_withoutDid)
206
+ .withClientId('sphereon:wallet')
207
+ .build();
208
+ await expect(credReqClient.acquireCredentialsUsingRequest({ format: 'jwt_vc_json', types: ['random'], proof })).rejects.toThrow(
209
+ Error(URL_NOT_VALID),
210
+ );
211
+ });
139
212
  });
140
213
 
141
214
  describe('Credential Request Client with Walt.id ', () => {
@@ -29,11 +29,14 @@ import { IDENTIPROOF_AS_METADATA, IDENTIPROOF_AS_URL, IDENTIPROOF_ISSUER_URL, ID
29
29
  export const UNIT_TEST_TIMEOUT = 30000;
30
30
 
31
31
  const ISSUER_URL = 'https://issuer.research.identiproof.io';
32
- const jwt = {
32
+ const jwtDid = {
33
33
  header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'openid4vci-proof+jwt' },
34
34
  payload: { iss: 'test-clientId', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: ISSUER_URL },
35
35
  };
36
-
36
+ const jwtWithoutDid = {
37
+ header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'openid4vci-proof+jwt' },
38
+ payload: { iss: 'test-clientId', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: ISSUER_URL },
39
+ };
37
40
  describe('OID4VCI-Client should', () => {
38
41
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
39
42
  async function proofOfPossessionCallbackFunction(_args: Jwt, _kid?: string): Promise<string> {
@@ -202,7 +205,7 @@ describe('OID4VCI-Client should', () => {
202
205
  // Types of parameters 'args' and 'args' are incompatible.
203
206
  // Property 'kid' is missing in type '{ header: unknown; payload: unknown; }' but required in type 'ProofOfPossessionCallbackArgs'.
204
207
  const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
205
- jwt,
208
+ jwt: jwtDid,
206
209
  callbacks: {
207
210
  signCallback: proofOfPossessionCallbackFunction,
208
211
  },
@@ -221,6 +224,66 @@ describe('OID4VCI-Client should', () => {
221
224
  UNIT_TEST_TIMEOUT,
222
225
  );
223
226
 
227
+ it(
228
+ 'succeed with a full flow with a not-did-kid without the client v1_0_11',
229
+ async () => {
230
+ /* Convert the URI into an object */
231
+ const credentialOffer: CredentialOfferRequestWithBaseUrl = await CredentialOfferClientV1_0_11.fromURI(INITIATE_QR_V1_0_08);
232
+
233
+ expect(credentialOffer.baseUrl).toEqual('openid-initiate-issuance://');
234
+ expect(credentialOffer.original_credential_offer).toEqual({
235
+ credential_type: ['OpenBadgeCredentialUrl'],
236
+ issuer: ISSUER_URL,
237
+ 'pre-authorized_code':
238
+ '4jLs9xZHEfqcoow0kHE7d1a8hUk6Sy-5bVSV2MqBUGUgiFFQi-ImL62T-FmLIo8hKA1UdMPH0lM1xAgcFkJfxIw9L-lI3mVs0hRT8YVwsEM1ma6N3wzuCdwtMU4bcwKp',
239
+ user_pin_required: 'true',
240
+ });
241
+
242
+ nock(ISSUER_URL)
243
+ .post(/token.*/)
244
+ .reply(200, JSON.stringify(mockedAccessTokenResponse));
245
+
246
+ /* The actual access token calls */
247
+ const accessTokenClient: AccessTokenClientV1_0_11 = new AccessTokenClientV1_0_11();
248
+ const accessTokenResponse = await accessTokenClient.acquireAccessToken({ credentialOffer: credentialOffer, pin: '1234' });
249
+ expect(accessTokenResponse.successBody).toEqual(mockedAccessTokenResponse);
250
+ // Get the credential
251
+ nock(ISSUER_URL)
252
+ .post(/credential/)
253
+ .reply(200, {
254
+ format: 'jwt-vc',
255
+ credential: mockedVC,
256
+ });
257
+ const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({ credentialOffer: credentialOffer })
258
+ .withFormat('jwt_vc')
259
+
260
+ .withTokenFromResponse(accessTokenResponse.successBody!)
261
+ .build();
262
+
263
+ //TS2322: Type '(args: ProofOfPossessionCallbackArgs) => Promise<string>'
264
+ // is not assignable to type 'ProofOfPossessionCallback'.
265
+ // Types of parameters 'args' and 'args' are incompatible.
266
+ // Property 'kid' is missing in type '{ header: unknown; payload: unknown; }' but required in type 'ProofOfPossessionCallbackArgs'.
267
+ const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
268
+ jwt: jwtWithoutDid,
269
+ callbacks: {
270
+ signCallback: proofOfPossessionCallbackFunction,
271
+ },
272
+ version: OpenId4VCIVersion.VER_1_0_11,
273
+ })
274
+ .withEndpointMetadata({
275
+ issuer: 'https://issuer.research.identiproof.io',
276
+ credential_endpoint: 'https://issuer.research.identiproof.io/credential',
277
+ token_endpoint: 'https://issuer.research.identiproof.io/token',
278
+ })
279
+ .withKid('ebfeb1f712ebc6f1c276e12ec21/keys/1')
280
+ .build();
281
+ const credResponse = await credReqClient.acquireCredentialsUsingProof({ proofInput: proof });
282
+ expect(credResponse.successBody?.credential).toEqual(mockedVC);
283
+ },
284
+ UNIT_TEST_TIMEOUT,
285
+ );
286
+
224
287
  it(
225
288
  'succeed with a full flow without the client v1_0_13',
226
289
  async () => {
@@ -266,7 +329,7 @@ describe('OID4VCI-Client should', () => {
266
329
  // Types of parameters 'args' and 'args' are incompatible.
267
330
  // Property 'kid' is missing in type '{ header: unknown; payload: unknown; }' but required in type 'ProofOfPossessionCallbackArgs'.
268
331
  const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
269
- jwt,
332
+ jwt: jwtDid,
270
333
  callbacks: {
271
334
  signCallback: proofOfPossessionCallbackFunction,
272
335
  },
@@ -287,6 +350,73 @@ describe('OID4VCI-Client should', () => {
287
350
  },
288
351
  UNIT_TEST_TIMEOUT,
289
352
  );
353
+
354
+ it(
355
+ 'succeed with a full flow with a not-did-kid without the client v1_0_13',
356
+ async () => {
357
+ /* Convert the URI into an object */
358
+ const credentialOffer: CredentialOfferRequestWithBaseUrl = await CredentialOfferClient.fromURI(INITIATE_QR_V1_0_13);
359
+ const preAuthorizedCode = 'oaKazRN8I0IbtZ0C7JuMn5';
360
+ expect(credentialOffer.baseUrl).toEqual('openid-credential-offer://');
361
+ expect((credentialOffer.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids).toEqual(['OpenBadgeCredentialUrl']);
362
+ expect(credentialOffer.original_credential_offer.grants).toEqual({
363
+ 'urn:ietf:params:oauth:grant-type:pre-authorized_code': {
364
+ 'pre-authorized_code': preAuthorizedCode,
365
+ tx_code: {
366
+ input_mode: 'text',
367
+ description: 'Please enter the serial number of your physical drivers license',
368
+ length: preAuthorizedCode.length,
369
+ },
370
+ },
371
+ });
372
+
373
+ nock(ISSUER_URL)
374
+ .post(/token.*/)
375
+ .reply(200, JSON.stringify(mockedAccessTokenResponse));
376
+
377
+ /* The actual access token calls */
378
+ const accessTokenClient: AccessTokenClient = new AccessTokenClient();
379
+ const accessTokenResponse = await accessTokenClient.acquireAccessToken({ credentialOffer: credentialOffer, pin: '1234' });
380
+ expect(accessTokenResponse.successBody).toEqual(mockedAccessTokenResponse);
381
+ // Get the credential
382
+ nock(ISSUER_URL)
383
+ .post(/credential/)
384
+ .reply(200, {
385
+ format: 'jwt-vc',
386
+ credential: mockedVC,
387
+ });
388
+ const credReqClient = CredentialRequestClientBuilder.fromCredentialOffer({ credentialOffer: credentialOffer })
389
+ .withFormat('jwt_vc')
390
+
391
+ .withTokenFromResponse(accessTokenResponse.successBody!)
392
+ .build();
393
+
394
+ //TS2322: Type '(args: ProofOfPossessionCallbackArgs) => Promise<string>'
395
+ // is not assignable to type 'ProofOfPossessionCallback'.
396
+ // Types of parameters 'args' and 'args' are incompatible.
397
+ // Property 'kid' is missing in type '{ header: unknown; payload: unknown; }' but required in type 'ProofOfPossessionCallbackArgs'.
398
+ const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
399
+ jwt: jwtWithoutDid,
400
+ callbacks: {
401
+ signCallback: proofOfPossessionCallbackFunction,
402
+ },
403
+ version: OpenId4VCIVersion.VER_1_0_11,
404
+ })
405
+ .withEndpointMetadata({
406
+ issuer: 'https://issuer.research.identiproof.io',
407
+ credential_endpoint: 'https://issuer.research.identiproof.io/credential',
408
+ token_endpoint: 'https://issuer.research.identiproof.io/token',
409
+ })
410
+ .withKid('ebfeb1f712ebc6f1c276e12ec21/keys/1')
411
+ .build();
412
+ const credResponse = await credReqClient.acquireCredentialsUsingProof({
413
+ proofInput: proof,
414
+ credentialType: credentialOffer.original_credential_offer.credential_configuration_ids[0],
415
+ });
416
+ expect(credResponse.successBody?.credential).toEqual(mockedVC);
417
+ },
418
+ UNIT_TEST_TIMEOUT,
419
+ );
290
420
  });
291
421
 
292
422
  describe('OIDVCI-Client for v1_0_13 should', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/oid4vci-client",
3
- "version": "0.10.4-unstable.79+3b45bb1",
3
+ "version": "0.10.4-unstable.80+85e42c5",
4
4
  "description": "OpenID for Verifiable Credential Issuance (OpenID4VCI) client",
5
5
  "source": "lib/index.ts",
6
6
  "main": "dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "build": "tsc"
16
16
  },
17
17
  "dependencies": {
18
- "@sphereon/oid4vci-common": "0.10.4-unstable.79+3b45bb1",
18
+ "@sphereon/oid4vci-common": "0.10.4-unstable.80+85e42c5",
19
19
  "@sphereon/ssi-types": "^0.23.0",
20
20
  "cross-fetch": "^3.1.8",
21
21
  "debug": "^4.3.4"
@@ -69,5 +69,5 @@
69
69
  "OIDC4VCI",
70
70
  "OID4VCI"
71
71
  ],
72
- "gitHead": "3b45bb1785e39a672b320157f09a98b4222e8235"
72
+ "gitHead": "85e42c51795ce4317d4e2d935b0e02f7b6fb4792"
73
73
  }