@sphereon/oid4vci-client 0.15.2-unstable.8 → 0.16.1-next.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AccessTokenClient.d.ts +7 -5
- package/dist/AccessTokenClient.d.ts.map +1 -1
- package/dist/AccessTokenClient.js +25 -5
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AccessTokenClientV1_0_11.d.ts +7 -5
- package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -1
- package/dist/AccessTokenClientV1_0_11.js +25 -5
- package/dist/AccessTokenClientV1_0_11.js.map +1 -1
- package/dist/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/AuthorizationCodeClient.js +3 -2
- package/dist/AuthorizationCodeClient.js.map +1 -1
- package/dist/AuthorizationCodeClientV1_0_11.js +1 -1
- package/dist/AuthorizationCodeClientV1_0_11.js.map +1 -1
- package/dist/CredentialRequestClient.d.ts +6 -4
- package/dist/CredentialRequestClient.d.ts.map +1 -1
- package/dist/CredentialRequestClient.js +23 -5
- package/dist/CredentialRequestClient.js.map +1 -1
- package/dist/CredentialRequestClientV1_0_11.d.ts +5 -3
- package/dist/CredentialRequestClientV1_0_11.d.ts.map +1 -1
- package/dist/CredentialRequestClientV1_0_11.js +32 -4
- package/dist/CredentialRequestClientV1_0_11.js.map +1 -1
- package/dist/MetadataClient.d.ts +1 -0
- package/dist/MetadataClient.d.ts.map +1 -1
- package/dist/MetadataClient.js +5 -4
- package/dist/MetadataClient.js.map +1 -1
- package/dist/MetadataClientV1_0_13.d.ts +1 -0
- package/dist/MetadataClientV1_0_13.d.ts.map +1 -1
- package/dist/MetadataClientV1_0_13.js +5 -9
- package/dist/MetadataClientV1_0_13.js.map +1 -1
- package/dist/OpenID4VCIClient.d.ts +10 -10
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +11 -17
- package/dist/OpenID4VCIClient.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts +10 -9
- package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.js +14 -7
- package/dist/OpenID4VCIClientV1_0_11.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_13.d.ts +10 -9
- package/dist/OpenID4VCIClientV1_0_13.d.ts.map +1 -1
- package/dist/OpenID4VCIClientV1_0_13.js +11 -6
- package/dist/OpenID4VCIClientV1_0_13.js.map +1 -1
- package/dist/ProofOfPossessionBuilder.d.ts +2 -1
- package/dist/ProofOfPossessionBuilder.d.ts.map +1 -1
- package/dist/ProofOfPossessionBuilder.js.map +1 -1
- package/dist/functions/AccessTokenUtil.d.ts.map +1 -1
- package/dist/functions/AccessTokenUtil.js +2 -2
- package/dist/functions/AccessTokenUtil.js.map +1 -1
- package/dist/functions/dpopUtil.d.ts +10 -0
- package/dist/functions/dpopUtil.d.ts.map +1 -0
- package/dist/functions/dpopUtil.js +30 -0
- package/dist/functions/dpopUtil.js.map +1 -0
- package/dist/functions/notifications.d.ts.map +1 -1
- package/dist/functions/notifications.js +3 -3
- package/dist/functions/notifications.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/lib/AccessTokenClient.ts +44 -7
- package/lib/AccessTokenClientV1_0_11.ts +44 -7
- package/lib/AuthorizationCodeClient.ts +4 -3
- package/lib/AuthorizationCodeClientV1_0_11.ts +3 -3
- package/lib/CredentialRequestClient.ts +49 -7
- package/lib/CredentialRequestClientV1_0_11.ts +48 -5
- package/lib/MetadataClient.ts +2 -1
- package/lib/MetadataClientV1_0_13.ts +2 -7
- package/lib/OpenID4VCIClient.ts +26 -28
- package/lib/OpenID4VCIClientV1_0_11.ts +25 -14
- package/lib/OpenID4VCIClientV1_0_13.ts +23 -13
- package/lib/ProofOfPossessionBuilder.ts +1 -1
- package/lib/__tests__/AccessTokenClient.spec.ts +4 -11
- package/lib/__tests__/SphereonE2E.spec.test.ts +3 -3
- package/lib/functions/AccessTokenUtil.ts +2 -2
- package/lib/functions/dpopUtil.ts +35 -0
- package/lib/functions/notifications.ts +2 -4
- package/lib/index.ts +0 -1
- package/package.json +5 -4
- package/dist/IssuerSessionClient.d.ts +0 -3
- package/dist/IssuerSessionClient.d.ts.map +0 -1
- package/dist/IssuerSessionClient.js +0 -28
- package/dist/IssuerSessionClient.js.map +0 -1
- package/lib/IssuerSessionClient.ts +0 -17
- package/lib/__tests__/IssuerSessionClient.spec.ts +0 -64
package/lib/OpenID4VCIClient.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { CreateDPoPClientOpts, JWK } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
3
|
+
AccessTokenRequestOpts,
|
|
2
4
|
AccessTokenResponse,
|
|
3
5
|
Alg,
|
|
4
6
|
AuthorizationRequestOpts,
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
CredentialsSupportedLegacy,
|
|
16
18
|
DefaultURISchemes,
|
|
17
19
|
determineVersionsFromIssuerMetadata,
|
|
20
|
+
DPoPResponseParams,
|
|
18
21
|
EndpointMetadataResultV1_0_11,
|
|
19
22
|
EndpointMetadataResultV1_0_13,
|
|
20
23
|
ExperimentalSubjectIssuance,
|
|
@@ -22,8 +25,7 @@ import {
|
|
|
22
25
|
getIssuerFromCredentialOfferPayload,
|
|
23
26
|
getSupportedCredentials,
|
|
24
27
|
getTypesFromCredentialSupported,
|
|
25
|
-
getTypesFromObject,
|
|
26
|
-
JWK,
|
|
28
|
+
getTypesFromObject,
|
|
27
29
|
KID_JWK_X5C_ERROR,
|
|
28
30
|
NotificationRequest,
|
|
29
31
|
NotificationResult,
|
|
@@ -31,7 +33,7 @@ import {
|
|
|
31
33
|
OpenId4VCIVersion,
|
|
32
34
|
PKCEOpts,
|
|
33
35
|
ProofOfPossessionCallbacks,
|
|
34
|
-
toAuthorizationResponsePayload
|
|
36
|
+
toAuthorizationResponsePayload,
|
|
35
37
|
} from '@sphereon/oid4vci-common';
|
|
36
38
|
import { CredentialFormat } from '@sphereon/ssi-types';
|
|
37
39
|
import Debug from 'debug';
|
|
@@ -49,7 +51,6 @@ import { OpenID4VCIClientStateV1_0_11 } from './OpenID4VCIClientV1_0_11';
|
|
|
49
51
|
import { OpenID4VCIClientStateV1_0_13 } from './OpenID4VCIClientV1_0_13';
|
|
50
52
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
51
53
|
import { generateMissingPKCEOpts, sendNotification } from './functions';
|
|
52
|
-
import { acquireIssuerSessionId } from './IssuerSessionClient';
|
|
53
54
|
|
|
54
55
|
const debug = Debug('sphereon:oid4vci');
|
|
55
56
|
|
|
@@ -269,16 +270,13 @@ export class OpenID4VCIClient {
|
|
|
269
270
|
this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce });
|
|
270
271
|
}
|
|
271
272
|
|
|
272
|
-
public async acquireAccessToken(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
additionalRequestParams?: Record<string, any>;
|
|
280
|
-
asOpts?: AuthorizationServerOpts;
|
|
281
|
-
}): Promise<AccessTokenResponse> {
|
|
273
|
+
public async acquireAccessToken(
|
|
274
|
+
opts?: Omit<AccessTokenRequestOpts, 'credentialOffer' | 'credentialIssuer' | 'metadata' | 'additionalParams'> & {
|
|
275
|
+
clientId?: string;
|
|
276
|
+
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
277
|
+
additionalRequestParams?: Record<string, any>;
|
|
278
|
+
},
|
|
279
|
+
): Promise<AccessTokenResponse & { params?: DPoPResponseParams }> {
|
|
282
280
|
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
|
|
283
281
|
let { redirectUri } = opts ?? {};
|
|
284
282
|
if (opts?.authorizationResponse) {
|
|
@@ -337,6 +335,7 @@ export class OpenID4VCIClient {
|
|
|
337
335
|
code,
|
|
338
336
|
redirectUri,
|
|
339
337
|
asOpts,
|
|
338
|
+
...(opts?.createDPoPOpts && { createDPoPOpts: opts.createDPoPOpts }),
|
|
340
339
|
...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
|
|
341
340
|
});
|
|
342
341
|
|
|
@@ -356,20 +355,11 @@ export class OpenID4VCIClient {
|
|
|
356
355
|
);
|
|
357
356
|
}
|
|
358
357
|
this._state.accessTokenResponse = response.successBody;
|
|
358
|
+
this._state.dpopResponseParams = response.params;
|
|
359
359
|
this._state.accessToken = response.successBody.access_token;
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
return this.accessTokenResponse;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
public async acquireIssuerSessionId() : Promise<IssuerSessionResponse | undefined> {
|
|
366
|
-
if(!this._state.endpointMetadata) {
|
|
367
|
-
return Promise.reject('endpointMetadata no loaded, retrieveServerMetadata()')
|
|
368
|
-
}
|
|
369
|
-
if(!('session_endpoint' in this._state.endpointMetadata) || !this._state.endpointMetadata.session_endpoint) {
|
|
370
|
-
return undefined
|
|
371
|
-
}
|
|
372
|
-
return acquireIssuerSessionId({sessionEndpoint: this._state.endpointMetadata.session_endpoint})
|
|
362
|
+
return { ...this.accessTokenResponse, ...(this.dpopResponseParams && { params: this.dpopResponseParams }) };
|
|
373
363
|
}
|
|
374
364
|
|
|
375
365
|
public async acquireCredentials({
|
|
@@ -383,6 +373,7 @@ export class OpenID4VCIClient {
|
|
|
383
373
|
jti,
|
|
384
374
|
deferredCredentialAwait,
|
|
385
375
|
deferredCredentialIntervalInMS,
|
|
376
|
+
createDPoPOpts,
|
|
386
377
|
}: {
|
|
387
378
|
credentialTypes: string | string[];
|
|
388
379
|
context?: string[];
|
|
@@ -395,7 +386,8 @@ export class OpenID4VCIClient {
|
|
|
395
386
|
deferredCredentialAwait?: boolean;
|
|
396
387
|
deferredCredentialIntervalInMS?: number;
|
|
397
388
|
experimentalHolderIssuanceSupported?: boolean;
|
|
398
|
-
|
|
389
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
390
|
+
}): Promise<CredentialResponse & { params?: DPoPResponseParams; access_token: string }> {
|
|
399
391
|
if ([jwk, kid].filter((v) => v !== undefined).length > 1) {
|
|
400
392
|
throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== undefined}, kid: ${kid !== undefined}`);
|
|
401
393
|
}
|
|
@@ -498,7 +490,9 @@ export class OpenID4VCIClient {
|
|
|
498
490
|
context,
|
|
499
491
|
format,
|
|
500
492
|
subjectIssuance,
|
|
493
|
+
createDPoPOpts,
|
|
501
494
|
});
|
|
495
|
+
this._state.dpopResponseParams = response.params;
|
|
502
496
|
if (response.errorBody) {
|
|
503
497
|
debug(`Credential request error:\r\n${JSON.stringify(response.errorBody)}`);
|
|
504
498
|
throw Error(
|
|
@@ -514,7 +508,7 @@ export class OpenID4VCIClient {
|
|
|
514
508
|
} for issuer ${this.getIssuer()} failed as there was no success response body`,
|
|
515
509
|
);
|
|
516
510
|
}
|
|
517
|
-
return { ...response.successBody, access_token: response.access_token };
|
|
511
|
+
return { ...response.successBody, ...(this.dpopResponseParams && { params: this.dpopResponseParams }), access_token: response.access_token };
|
|
518
512
|
}
|
|
519
513
|
|
|
520
514
|
public async exportState(): Promise<string> {
|
|
@@ -560,7 +554,7 @@ export class OpenID4VCIClient {
|
|
|
560
554
|
issuerSupportedFlowTypes(): AuthzFlowType[] {
|
|
561
555
|
return (
|
|
562
556
|
this.credentialOffer?.supportedFlows ??
|
|
563
|
-
(this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server
|
|
557
|
+
((this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server)
|
|
564
558
|
? [AuthzFlowType.AUTHORIZATION_CODE_FLOW]
|
|
565
559
|
: [])
|
|
566
560
|
);
|
|
@@ -636,6 +630,10 @@ export class OpenID4VCIClient {
|
|
|
636
630
|
return this._state.accessTokenResponse!;
|
|
637
631
|
}
|
|
638
632
|
|
|
633
|
+
get dpopResponseParams(): DPoPResponseParams | undefined {
|
|
634
|
+
return this._state.dpopResponseParams;
|
|
635
|
+
}
|
|
636
|
+
|
|
639
637
|
public getIssuer(): string {
|
|
640
638
|
this.assertIssuerData();
|
|
641
639
|
return this._state.credentialIssuer;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { CreateDPoPClientOpts, JWK } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
3
|
+
AccessTokenRequestOpts,
|
|
2
4
|
AccessTokenResponse,
|
|
3
5
|
Alg,
|
|
4
6
|
AuthorizationRequestOpts,
|
|
@@ -13,13 +15,13 @@ import {
|
|
|
13
15
|
CredentialResponse,
|
|
14
16
|
CredentialsSupportedLegacy,
|
|
15
17
|
DefaultURISchemes,
|
|
18
|
+
DPoPResponseParams,
|
|
16
19
|
EndpointMetadataResultV1_0_11,
|
|
17
20
|
getClientIdFromCredentialOfferPayload,
|
|
18
21
|
getIssuerFromCredentialOfferPayload,
|
|
19
22
|
getSupportedCredentials,
|
|
20
23
|
getTypesFromCredentialSupported,
|
|
21
24
|
getTypesFromObject,
|
|
22
|
-
JWK,
|
|
23
25
|
KID_JWK_X5C_ERROR,
|
|
24
26
|
OID4VCICredentialFormat,
|
|
25
27
|
OpenId4VCIVersion,
|
|
@@ -36,7 +38,7 @@ import { CredentialOfferClientV1_0_11 } from './CredentialOfferClientV1_0_11';
|
|
|
36
38
|
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
|
|
37
39
|
import { MetadataClientV1_0_11 } from './MetadataClientV1_0_11';
|
|
38
40
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
39
|
-
import { generateMissingPKCEOpts } from './functions
|
|
41
|
+
import { generateMissingPKCEOpts } from './functions';
|
|
40
42
|
|
|
41
43
|
const debug = Debug('sphereon:oid4vci');
|
|
42
44
|
|
|
@@ -49,6 +51,7 @@ export interface OpenID4VCIClientStateV1_0_11 {
|
|
|
49
51
|
alg?: Alg | string;
|
|
50
52
|
endpointMetadata?: EndpointMetadataResultV1_0_11;
|
|
51
53
|
accessTokenResponse?: AccessTokenResponse;
|
|
54
|
+
dpopResponseParams?: DPoPResponseParams;
|
|
52
55
|
authorizationRequestOpts?: AuthorizationRequestOpts;
|
|
53
56
|
authorizationCodeResponse?: AuthorizationResponse;
|
|
54
57
|
pkce: PKCEOpts;
|
|
@@ -253,16 +256,13 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
253
256
|
this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce });
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
public async acquireAccessToken(
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
additionalRequestParams?: Record<string, any>;
|
|
264
|
-
asOpts?: AuthorizationServerOpts;
|
|
265
|
-
}): Promise<AccessTokenResponse> {
|
|
259
|
+
public async acquireAccessToken(
|
|
260
|
+
opts?: Omit<AccessTokenRequestOpts, 'credentialOffer' | 'credentialIssuer' | 'metadata' | 'additionalParams'> & {
|
|
261
|
+
clientId?: string;
|
|
262
|
+
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
263
|
+
additionalRequestParams?: Record<string, any>;
|
|
264
|
+
},
|
|
265
|
+
): Promise<AccessTokenResponse & { params?: DPoPResponseParams }> {
|
|
266
266
|
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
|
|
267
267
|
let { redirectUri } = opts ?? {};
|
|
268
268
|
if (opts?.authorizationResponse) {
|
|
@@ -320,6 +320,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
320
320
|
code,
|
|
321
321
|
redirectUri,
|
|
322
322
|
asOpts,
|
|
323
|
+
...(opts?.createDPoPOpts && { createDPoPOpts: opts.createDPoPOpts }),
|
|
323
324
|
...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
|
|
324
325
|
});
|
|
325
326
|
|
|
@@ -339,9 +340,11 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
339
340
|
);
|
|
340
341
|
}
|
|
341
342
|
this._state.accessTokenResponse = response.successBody;
|
|
343
|
+
this._state.dpopResponseParams = response.params;
|
|
344
|
+
this._state.accessToken = response.successBody.access_token;
|
|
342
345
|
}
|
|
343
346
|
|
|
344
|
-
return this.accessTokenResponse;
|
|
347
|
+
return { ...this.accessTokenResponse, ...(this.dpopResponseParams && { params: this.dpopResponseParams }) };
|
|
345
348
|
}
|
|
346
349
|
|
|
347
350
|
public async acquireCredentials({
|
|
@@ -355,6 +358,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
355
358
|
jti,
|
|
356
359
|
deferredCredentialAwait,
|
|
357
360
|
deferredCredentialIntervalInMS,
|
|
361
|
+
createDPoPOpts,
|
|
358
362
|
}: {
|
|
359
363
|
credentialTypes: string | string[];
|
|
360
364
|
context?: string[];
|
|
@@ -366,6 +370,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
366
370
|
jti?: string;
|
|
367
371
|
deferredCredentialAwait?: boolean;
|
|
368
372
|
deferredCredentialIntervalInMS?: number;
|
|
373
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
369
374
|
}): Promise<CredentialResponse> {
|
|
370
375
|
if ([jwk, kid].filter((v) => v !== undefined).length > 1) {
|
|
371
376
|
throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== undefined}, kid: ${kid !== undefined}`);
|
|
@@ -445,7 +450,9 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
445
450
|
credentialTypes,
|
|
446
451
|
context,
|
|
447
452
|
format,
|
|
453
|
+
createDPoPOpts,
|
|
448
454
|
});
|
|
455
|
+
this._state.dpopResponseParams = response.params;
|
|
449
456
|
if (response.errorBody) {
|
|
450
457
|
debug(`Credential request error:\r\n${JSON.stringify(response.errorBody)}`);
|
|
451
458
|
throw Error(
|
|
@@ -461,7 +468,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
461
468
|
} for issuer ${this.getIssuer()} failed as there was no success response body`,
|
|
462
469
|
);
|
|
463
470
|
}
|
|
464
|
-
return response.successBody;
|
|
471
|
+
return { ...response.successBody, ...(this.dpopResponseParams && { params: this.dpopResponseParams }) };
|
|
465
472
|
}
|
|
466
473
|
|
|
467
474
|
public async exportState(): Promise<string> {
|
|
@@ -576,6 +583,10 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
576
583
|
return this._state.accessTokenResponse!;
|
|
577
584
|
}
|
|
578
585
|
|
|
586
|
+
get dpopResponseParams(): DPoPResponseParams | undefined {
|
|
587
|
+
return this._state.dpopResponseParams;
|
|
588
|
+
}
|
|
589
|
+
|
|
579
590
|
public getIssuer(): string {
|
|
580
591
|
this.assertIssuerData();
|
|
581
592
|
return this._state.credentialIssuer;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { CreateDPoPClientOpts, JWK } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
3
|
+
AccessTokenRequestOpts,
|
|
2
4
|
AccessTokenResponse,
|
|
3
5
|
Alg,
|
|
4
6
|
AuthorizationRequestOpts,
|
|
@@ -11,13 +13,13 @@ import {
|
|
|
11
13
|
CredentialOfferRequestWithBaseUrl,
|
|
12
14
|
CredentialResponse,
|
|
13
15
|
DefaultURISchemes,
|
|
16
|
+
DPoPResponseParams,
|
|
14
17
|
EndpointMetadataResultV1_0_13,
|
|
15
18
|
ExperimentalSubjectIssuance,
|
|
16
19
|
getClientIdFromCredentialOfferPayload,
|
|
17
20
|
getIssuerFromCredentialOfferPayload,
|
|
18
21
|
getSupportedCredentials,
|
|
19
22
|
getTypesFromCredentialSupported,
|
|
20
|
-
JWK,
|
|
21
23
|
KID_JWK_X5C_ERROR,
|
|
22
24
|
NotificationRequest,
|
|
23
25
|
NotificationResult,
|
|
@@ -50,6 +52,7 @@ export interface OpenID4VCIClientStateV1_0_13 {
|
|
|
50
52
|
alg?: Alg | string;
|
|
51
53
|
endpointMetadata?: EndpointMetadataResultV1_0_13;
|
|
52
54
|
accessTokenResponse?: AccessTokenResponse;
|
|
55
|
+
dpopResponseParams?: DPoPResponseParams;
|
|
53
56
|
authorizationRequestOpts?: AuthorizationRequestOpts;
|
|
54
57
|
authorizationCodeResponse?: AuthorizationResponse;
|
|
55
58
|
pkce: PKCEOpts;
|
|
@@ -258,16 +261,13 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
258
261
|
this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce });
|
|
259
262
|
}
|
|
260
263
|
|
|
261
|
-
public async acquireAccessToken(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
additionalRequestParams?: Record<string, any>;
|
|
269
|
-
asOpts?: AuthorizationServerOpts;
|
|
270
|
-
}): Promise<AccessTokenResponse> {
|
|
264
|
+
public async acquireAccessToken(
|
|
265
|
+
opts?: Omit<AccessTokenRequestOpts, 'credentialOffer' | 'credentialIssuer' | 'metadata' | 'additionalParams'> & {
|
|
266
|
+
clientId?: string;
|
|
267
|
+
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
268
|
+
additionalRequestParams?: Record<string, any>;
|
|
269
|
+
},
|
|
270
|
+
): Promise<AccessTokenResponse & { params?: DPoPResponseParams }> {
|
|
271
271
|
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
|
|
272
272
|
let { redirectUri } = opts ?? {};
|
|
273
273
|
if (opts?.authorizationResponse) {
|
|
@@ -324,6 +324,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
324
324
|
code,
|
|
325
325
|
redirectUri,
|
|
326
326
|
asOpts,
|
|
327
|
+
...(opts?.createDPoPOpts && { createDPoPOpts: opts.createDPoPOpts }),
|
|
327
328
|
...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
|
|
328
329
|
});
|
|
329
330
|
|
|
@@ -343,10 +344,11 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
343
344
|
);
|
|
344
345
|
}
|
|
345
346
|
this._state.accessTokenResponse = response.successBody;
|
|
347
|
+
this._state.dpopResponseParams = response.params;
|
|
346
348
|
this._state.accessToken = response.successBody.access_token;
|
|
347
349
|
}
|
|
348
350
|
|
|
349
|
-
return this.accessTokenResponse;
|
|
351
|
+
return { ...this.accessTokenResponse, ...(this.dpopResponseParams && { params: this.dpopResponseParams }) };
|
|
350
352
|
}
|
|
351
353
|
|
|
352
354
|
public async acquireCredentials({
|
|
@@ -361,6 +363,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
361
363
|
jti,
|
|
362
364
|
deferredCredentialAwait,
|
|
363
365
|
deferredCredentialIntervalInMS,
|
|
366
|
+
createDPoPOpts,
|
|
364
367
|
}: {
|
|
365
368
|
credentialIdentifier?: string;
|
|
366
369
|
credentialTypes?: string | string[];
|
|
@@ -374,6 +377,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
374
377
|
deferredCredentialAwait?: boolean;
|
|
375
378
|
deferredCredentialIntervalInMS?: number;
|
|
376
379
|
experimentalHolderIssuanceSupported?: boolean;
|
|
380
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
377
381
|
}): Promise<CredentialResponse & { access_token: string }> {
|
|
378
382
|
if ([jwk, kid].filter((v) => v !== undefined).length > 1) {
|
|
379
383
|
throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== undefined}, kid: ${kid !== undefined}`);
|
|
@@ -471,7 +475,9 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
471
475
|
const response = await credentialRequestClient.acquireCredentialsUsingProof({
|
|
472
476
|
proofInput: proofBuilder,
|
|
473
477
|
...(credentialIdentifier ? { credentialIdentifier, subjectIssuance } : { format, context, credentialTypes, subjectIssuance }),
|
|
478
|
+
createDPoPOpts,
|
|
474
479
|
});
|
|
480
|
+
this._state.dpopResponseParams = response.params;
|
|
475
481
|
if (response.errorBody) {
|
|
476
482
|
debug(`Credential request error:\r\n${JSON.stringify(response.errorBody)}`);
|
|
477
483
|
throw Error(
|
|
@@ -487,7 +493,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
487
493
|
} for issuer ${this.getIssuer()} failed as there was no success response body`,
|
|
488
494
|
);
|
|
489
495
|
}
|
|
490
|
-
return { ...response.successBody, access_token: response.access_token };
|
|
496
|
+
return { ...response.successBody, ...(this.dpopResponseParams && { params: this.dpopResponseParams }), access_token: response.access_token };
|
|
491
497
|
}
|
|
492
498
|
|
|
493
499
|
public async exportState(): Promise<string> {
|
|
@@ -604,6 +610,10 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
604
610
|
return this._state.accessTokenResponse!;
|
|
605
611
|
}
|
|
606
612
|
|
|
613
|
+
get dpopResponseParams(): DPoPResponseParams | undefined {
|
|
614
|
+
return this._state.dpopResponseParams;
|
|
615
|
+
}
|
|
616
|
+
|
|
607
617
|
public getIssuer(): string {
|
|
608
618
|
this.assertIssuerData();
|
|
609
619
|
return this._state.credentialIssuer;
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AccessTokenRequest,
|
|
3
|
-
AccessTokenResponse,
|
|
4
|
-
GrantTypes,
|
|
5
|
-
OpenIDResponse,
|
|
6
|
-
PRE_AUTH_CODE_LITERAL,
|
|
7
|
-
WellKnownEndpoints,
|
|
8
|
-
} from '@sphereon/oid4vci-common';
|
|
1
|
+
import { AccessTokenRequest, AccessTokenResponse, GrantTypes, PRE_AUTH_CODE_LITERAL, WellKnownEndpoints } from '@sphereon/oid4vci-common';
|
|
9
2
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
10
3
|
// @ts-ignore
|
|
11
4
|
import nock from 'nock';
|
|
@@ -50,7 +43,7 @@ describe('AccessTokenClient should', () => {
|
|
|
50
43
|
};
|
|
51
44
|
nock(MOCK_URL).post(/.*/).reply(200, JSON.stringify(body));
|
|
52
45
|
|
|
53
|
-
const accessTokenResponse
|
|
46
|
+
const accessTokenResponse = await accessTokenClient.acquireAccessTokenUsingRequest({
|
|
54
47
|
accessTokenRequest,
|
|
55
48
|
pinMetadata: {
|
|
56
49
|
isPinRequired: true,
|
|
@@ -88,7 +81,7 @@ describe('AccessTokenClient should', () => {
|
|
|
88
81
|
};
|
|
89
82
|
nock(MOCK_URL).post(/.*/).reply(200, JSON.stringify(body));
|
|
90
83
|
|
|
91
|
-
const accessTokenResponse
|
|
84
|
+
const accessTokenResponse = await accessTokenClient.acquireAccessTokenUsingRequest({
|
|
92
85
|
accessTokenRequest,
|
|
93
86
|
asOpts: { as: MOCK_URL },
|
|
94
87
|
});
|
|
@@ -227,7 +220,7 @@ describe('AccessTokenClient should', () => {
|
|
|
227
220
|
.post(/.*/)
|
|
228
221
|
.reply(200, {});
|
|
229
222
|
|
|
230
|
-
const response
|
|
223
|
+
const response = await accessTokenClient.acquireAccessToken({
|
|
231
224
|
credentialOffer: INITIATION_TEST,
|
|
232
225
|
pin: '1234',
|
|
233
226
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as crypto from 'crypto';
|
|
2
2
|
|
|
3
|
+
import { uuidv4 } from '@sphereon/oid4vc-common';
|
|
3
4
|
import { Alg, Jwt, ProofOfPossessionCallbacks } from '@sphereon/oid4vci-common';
|
|
4
5
|
import { CredentialMapper } from '@sphereon/ssi-types';
|
|
5
6
|
import * as didts from '@transmute/did-key.js';
|
|
6
7
|
import { fetch } from 'cross-fetch';
|
|
7
8
|
import debug from 'debug';
|
|
8
9
|
import { importJWK, JWK, SignJWT } from 'jose';
|
|
9
|
-
import { v4 } from 'uuid';
|
|
10
10
|
|
|
11
11
|
import { OpenID4VCIClientV1_0_11 } from '..';
|
|
12
12
|
|
|
@@ -94,7 +94,7 @@ async function getCredentialOffer(format: 'ldp_vc' | 'jwt_vc_json'): Promise<Cre
|
|
|
94
94
|
credentials: ['GuestCredential'],
|
|
95
95
|
grants: {
|
|
96
96
|
'urn:ietf:params:oauth:grant-type:pre-authorized_code': {
|
|
97
|
-
'pre-authorized_code':
|
|
97
|
+
'pre-authorized_code': uuidv4().substring(0, 10),
|
|
98
98
|
user_pin_required: false,
|
|
99
99
|
},
|
|
100
100
|
},
|
|
@@ -165,7 +165,7 @@ describe('ismapolis bug report #63, https://github.com/Sphereon-Opensource/OID4V
|
|
|
165
165
|
format: 'jwt_vc_json',
|
|
166
166
|
alg: Alg.ES256K,
|
|
167
167
|
kid: didDocument.verificationMethod[0].id,
|
|
168
|
-
jti:
|
|
168
|
+
jti: uuidv4(),
|
|
169
169
|
});
|
|
170
170
|
console.log(JSON.stringify(credentialResponse.credential));
|
|
171
171
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { uuidv4 } from '@sphereon/oid4vc-common';
|
|
1
2
|
import { AccessTokenRequest, AccessTokenRequestOpts, Jwt, OpenId4VCIVersion } from '@sphereon/oid4vci-common';
|
|
2
|
-
import { v4 } from 'uuid';
|
|
3
3
|
|
|
4
4
|
import { ProofOfPossessionBuilder } from '../ProofOfPossessionBuilder';
|
|
5
5
|
|
|
@@ -35,7 +35,7 @@ export const createJwtBearerClientAssertion = async (
|
|
|
35
35
|
iss: clientId,
|
|
36
36
|
sub: clientId,
|
|
37
37
|
aud: credentialIssuer,
|
|
38
|
-
jti:
|
|
38
|
+
jti: uuidv4(),
|
|
39
39
|
exp: Date.now() / 1000 + 60,
|
|
40
40
|
iat: Date.now() / 1000 - 60,
|
|
41
41
|
},
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { dpopTokenRequestNonceError } from '@sphereon/oid4vc-common';
|
|
2
|
+
import { OpenIDResponse } from 'oid4vci-common';
|
|
3
|
+
|
|
4
|
+
export type RetryRequestWithDPoPNonce = { ok: true; dpopNonce: string } | { ok: false };
|
|
5
|
+
|
|
6
|
+
export function shouldRetryTokenRequestWithDPoPNonce(response: OpenIDResponse<unknown, unknown>): RetryRequestWithDPoPNonce {
|
|
7
|
+
if (!response.errorBody || response.errorBody.error !== dpopTokenRequestNonceError) {
|
|
8
|
+
return { ok: false };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const dPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
12
|
+
if (!dPoPNonce) {
|
|
13
|
+
throw new Error('Missing required DPoP-Nonce header.');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return { ok: true, dpopNonce: dPoPNonce };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function shouldRetryResourceRequestWithDPoPNonce(response: OpenIDResponse<unknown, unknown>): RetryRequestWithDPoPNonce {
|
|
20
|
+
if (!response.errorBody || response.origResponse.status !== 401) {
|
|
21
|
+
return { ok: false };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const wwwAuthenticateHeader = response.origResponse.headers.get('WWW-Authenticate');
|
|
25
|
+
if (!wwwAuthenticateHeader?.includes(dpopTokenRequestNonceError)) {
|
|
26
|
+
return { ok: false };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const dPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
30
|
+
if (!dPoPNonce) {
|
|
31
|
+
throw new Error('Missing required DPoP-Nonce header.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { ok: true, dpopNonce: dPoPNonce };
|
|
35
|
+
}
|
|
@@ -19,12 +19,10 @@ export async function sendNotification(
|
|
|
19
19
|
const error = response.errorBody?.error !== undefined;
|
|
20
20
|
const result = {
|
|
21
21
|
error,
|
|
22
|
-
response: error ?
|
|
22
|
+
response: error ? response.errorBody : undefined,
|
|
23
23
|
};
|
|
24
24
|
if (error) {
|
|
25
|
-
LOG.warning(
|
|
26
|
-
`Notification endpoint returned an error for event '${request.event}' and id ${request.notification_id}: ${await response.errorBody?.json()}`,
|
|
27
|
-
);
|
|
25
|
+
LOG.warning(`Notification endpoint returned an error for event '${request.event}' and id ${request.notification_id}: ${response.errorBody}`);
|
|
28
26
|
} else {
|
|
29
27
|
LOG.debug(`Notification endpoint returned success for event '${request.event}' and id ${request.notification_id}`);
|
|
30
28
|
}
|
package/lib/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/oid4vci-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1-next.13+282e7a1",
|
|
4
4
|
"description": "OpenID for Verifiable Credential Issuance (OpenID4VCI) client",
|
|
5
5
|
"source": "lib/index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
"build": "tsc"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@sphereon/
|
|
19
|
-
"@sphereon/
|
|
18
|
+
"@sphereon/oid4vc-common": "0.16.1-next.13+282e7a1",
|
|
19
|
+
"@sphereon/oid4vci-common": "0.16.1-next.13+282e7a1",
|
|
20
|
+
"@sphereon/ssi-types": "0.29.0",
|
|
20
21
|
"cross-fetch": "^3.1.8",
|
|
21
22
|
"debug": "^4.3.5"
|
|
22
23
|
},
|
|
@@ -69,5 +70,5 @@
|
|
|
69
70
|
"OIDC4VCI",
|
|
70
71
|
"OID4VCI"
|
|
71
72
|
],
|
|
72
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "282e7a1c6b9becaf12b81302a5c84d34f525ae7a"
|
|
73
74
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IssuerSessionClient.d.ts","sourceRoot":"","sources":["../lib/IssuerSessionClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAwB,MAAM,0BAA0B,CAAC;AAInH,eAAO,MAAM,sBAAsB,SAAgB,0BAA0B,KAAG,OAAO,CAAC,qBAAqB,CAY5G,CAAA"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.acquireIssuerSessionId = void 0;
|
|
13
|
-
const oid4vci_common_1 = require("@sphereon/oid4vci-common");
|
|
14
|
-
const index_1 = require("./index");
|
|
15
|
-
const acquireIssuerSessionId = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
index_1.LOG.debug(`acquiring issuer session endpoint from endpoint ${opts.sessionEndpoint}`);
|
|
17
|
-
const sessionResponse = yield (0, oid4vci_common_1.post)(opts.sessionEndpoint);
|
|
18
|
-
if (sessionResponse.errorBody !== undefined) {
|
|
19
|
-
return Promise.reject(`an error occurred while requesting a issuer session token from endpoint ${opts.sessionEndpoint}:
|
|
20
|
-
${sessionResponse.errorBody.error} - ${sessionResponse.errorBody.error_description}`);
|
|
21
|
-
}
|
|
22
|
-
if (sessionResponse.successBody === undefined || !Object.keys(sessionResponse.successBody).includes('session_id')) {
|
|
23
|
-
return Promise.reject(`an error occurred while requesting a issuer session token from endpoint ${opts.sessionEndpoint}, missing session_token response`);
|
|
24
|
-
}
|
|
25
|
-
return sessionResponse.successBody;
|
|
26
|
-
});
|
|
27
|
-
exports.acquireIssuerSessionId = acquireIssuerSessionId;
|
|
28
|
-
//# sourceMappingURL=IssuerSessionClient.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IssuerSessionClient.js","sourceRoot":"","sources":["../lib/IssuerSessionClient.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAAmH;AAEnH,mCAA8B;AAEvB,MAAM,sBAAsB,GAAG,CAAO,IAAgC,EAAkC,EAAE;IAC/G,WAAG,CAAC,KAAK,CAAC,mDAAmD,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;IACpF,MAAM,eAAe,GAAG,MAAM,IAAA,qBAAI,EAAC,IAAI,CAAC,eAAe,CAA0C,CAAA;IACjG,IAAI,eAAe,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,OAAO,CAAC,MAAM,CAAC,2EAA2E,IAAI,CAAC,eAAe;OAClH,eAAe,CAAC,SAAS,CAAC,KAAK,MAAM,eAAe,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAA;IACxF,CAAC;IACD,IAAI,eAAe,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAClH,OAAO,OAAO,CAAC,MAAM,CAAC,2EAA2E,IAAI,CAAC,eAAe,kCAAkC,CAAC,CAAA;IAE1J,CAAC;IACD,OAAO,eAAe,CAAC,WAAW,CAAA;AACpC,CAAC,CAAA,CAAA;AAZY,QAAA,sBAAsB,0BAYlC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { IssuerSessionIdRequestOpts, IssuerSessionResponse, OpenIDResponse, post } from '@sphereon/oid4vci-common';
|
|
2
|
-
|
|
3
|
-
import { LOG } from './index';
|
|
4
|
-
|
|
5
|
-
export const acquireIssuerSessionId = async (opts: IssuerSessionIdRequestOpts): Promise<IssuerSessionResponse> => {
|
|
6
|
-
LOG.debug(`acquiring issuer session endpoint from endpoint ${opts.sessionEndpoint}`)
|
|
7
|
-
const sessionResponse = await post(opts.sessionEndpoint) as OpenIDResponse<IssuerSessionResponse>
|
|
8
|
-
if (sessionResponse.errorBody !== undefined) {
|
|
9
|
-
return Promise.reject(`an error occurred while requesting a issuer session token from endpoint ${opts.sessionEndpoint}:
|
|
10
|
-
${sessionResponse.errorBody.error} - ${sessionResponse.errorBody.error_description}`)
|
|
11
|
-
}
|
|
12
|
-
if (sessionResponse.successBody === undefined || !Object.keys(sessionResponse.successBody).includes('session_id')) {
|
|
13
|
-
return Promise.reject(`an error occurred while requesting a issuer session token from endpoint ${opts.sessionEndpoint}, missing session_token response`)
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
return sessionResponse.successBody
|
|
17
|
-
}
|