@sphereon/oid4vci-client 0.12.0 → 0.12.1-next.19

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 (42) hide show
  1. package/dist/AccessTokenClient.js +1 -1
  2. package/dist/AccessTokenClient.js.map +1 -1
  3. package/dist/AccessTokenClientV1_0_11.js +1 -1
  4. package/dist/AccessTokenClientV1_0_11.js.map +1 -1
  5. package/dist/AuthorizationCodeClient.d.ts.map +1 -1
  6. package/dist/AuthorizationCodeClient.js +4 -1
  7. package/dist/AuthorizationCodeClient.js.map +1 -1
  8. package/dist/CredentialRequestClient.d.ts +3 -2
  9. package/dist/CredentialRequestClient.d.ts.map +1 -1
  10. package/dist/CredentialRequestClient.js.map +1 -1
  11. package/dist/CredentialRequestClientBuilder.d.ts +7 -15
  12. package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
  13. package/dist/CredentialRequestClientBuilder.js +79 -55
  14. package/dist/CredentialRequestClientBuilder.js.map +1 -1
  15. package/dist/CredentialRequestClientBuilderV1_0_13.d.ts +51 -0
  16. package/dist/CredentialRequestClientBuilderV1_0_13.d.ts.map +1 -0
  17. package/dist/CredentialRequestClientBuilderV1_0_13.js +130 -0
  18. package/dist/CredentialRequestClientBuilderV1_0_13.js.map +1 -0
  19. package/dist/OpenID4VCIClient.d.ts +1 -0
  20. package/dist/OpenID4VCIClient.d.ts.map +1 -1
  21. package/dist/OpenID4VCIClient.js +5 -5
  22. package/dist/OpenID4VCIClient.js.map +1 -1
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +1 -0
  26. package/dist/index.js.map +1 -1
  27. package/lib/AccessTokenClient.ts +1 -1
  28. package/lib/AccessTokenClientV1_0_11.ts +1 -1
  29. package/lib/AuthorizationCodeClient.ts +7 -4
  30. package/lib/CredentialRequestClient.ts +3 -2
  31. package/lib/CredentialRequestClientBuilder.ts +98 -67
  32. package/lib/CredentialRequestClientBuilderV1_0_13.ts +173 -0
  33. package/lib/OpenID4VCIClient.ts +6 -4
  34. package/lib/__tests__/CredentialRequestClient.spec.ts +8 -13
  35. package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +40 -2
  36. package/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +96 -0
  37. package/lib/__tests__/IT.spec.ts +148 -111
  38. package/lib/__tests__/MetadataMocks.ts +35 -0
  39. package/lib/__tests__/ProofOfPossessionBuilder.spec.ts +85 -0
  40. package/lib/__tests__/SdJwt.spec.ts +103 -0
  41. package/lib/index.ts +1 -0
  42. package/package.json +3 -3
@@ -1,12 +1,11 @@
1
1
  import {
2
2
  AccessTokenResponse,
3
+ CredentialIssuerMetadata,
3
4
  CredentialIssuerMetadataV1_0_13,
4
- CredentialOfferPayloadV1_0_13,
5
5
  CredentialOfferRequestWithBaseUrl,
6
6
  determineSpecVersionFromOffer,
7
7
  EndpointMetadata,
8
8
  ExperimentalSubjectIssuance,
9
- getIssuerFromCredentialOfferPayload,
10
9
  OID4VCICredentialFormat,
11
10
  OpenId4VCIVersion,
12
11
  UniformCredentialOfferRequest,
@@ -14,19 +13,21 @@ import {
14
13
  import { CredentialFormat } from '@sphereon/ssi-types';
15
14
 
16
15
  import { CredentialOfferClient } from './CredentialOfferClient';
17
- import { CredentialRequestClient } from './CredentialRequestClient';
16
+ import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
17
+ import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
18
+
19
+ type CredentialRequestClientBuilderVersionSpecific = CredentialRequestClientBuilderV1_0_11 | CredentialRequestClientBuilderV1_0_13;
20
+
21
+ function isV1_0_13(builder: CredentialRequestClientBuilderVersionSpecific): builder is CredentialRequestClientBuilderV1_0_13 {
22
+ return (builder as CredentialRequestClientBuilderV1_0_13).withCredentialIdentifier !== undefined;
23
+ }
18
24
 
19
25
  export class CredentialRequestClientBuilder {
20
- credentialEndpoint?: string;
21
- deferredCredentialEndpoint?: string;
22
- deferredCredentialAwait = false;
23
- deferredCredentialIntervalInMS = 5000;
24
- credentialIdentifier?: string;
25
- credentialTypes?: string[] = [];
26
- format?: CredentialFormat | OID4VCICredentialFormat;
27
- token?: string;
28
- version?: OpenId4VCIVersion;
29
- subjectIssuance?: ExperimentalSubjectIssuance;
26
+ private _builder: CredentialRequestClientBuilderVersionSpecific;
27
+
28
+ private constructor(builder: CredentialRequestClientBuilderVersionSpecific) {
29
+ this._builder = builder;
30
+ }
30
31
 
31
32
  public static fromCredentialIssuer({
32
33
  credentialIssuer,
@@ -41,25 +42,40 @@ export class CredentialRequestClientBuilder {
41
42
  credentialIdentifier?: string;
42
43
  credentialTypes?: string | string[];
43
44
  }): CredentialRequestClientBuilder {
44
- const issuer = credentialIssuer;
45
- const builder = new CredentialRequestClientBuilder();
46
- builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_11);
47
- builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
48
- if (metadata?.deferred_credential_endpoint) {
49
- builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
50
- }
51
- if (credentialIdentifier) {
52
- builder.withCredentialIdentifier(credentialIdentifier);
53
- }
54
- if (credentialTypes) {
55
- builder.withCredentialType(credentialTypes);
45
+ const specVersion = version ?? OpenId4VCIVersion.VER_1_0_13;
46
+ let builder;
47
+
48
+ if (specVersion >= OpenId4VCIVersion.VER_1_0_13) {
49
+ builder = CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
50
+ credentialIssuer,
51
+ metadata,
52
+ version,
53
+ credentialIdentifier,
54
+ credentialTypes,
55
+ });
56
+ } else {
57
+ if (!credentialTypes || credentialTypes.length === 0) {
58
+ throw new Error('CredentialTypes must be provided for v1_0_11');
59
+ }
60
+ builder = CredentialRequestClientBuilderV1_0_11.fromCredentialIssuer({
61
+ credentialIssuer,
62
+ metadata,
63
+ version,
64
+ credentialTypes,
65
+ });
56
66
  }
57
- return builder;
67
+
68
+ return new CredentialRequestClientBuilder(builder);
58
69
  }
59
70
 
60
71
  public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilder> {
61
72
  const offer = await CredentialOfferClient.fromURI(uri);
62
- return CredentialRequestClientBuilder.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
73
+ return CredentialRequestClientBuilder.fromCredentialOfferRequest({
74
+ request: offer,
75
+ ...offer,
76
+ metadata,
77
+ version: offer.version,
78
+ });
63
79
  }
64
80
 
65
81
  public static fromCredentialOfferRequest(opts: {
@@ -69,24 +85,17 @@ export class CredentialRequestClientBuilder {
69
85
  version?: OpenId4VCIVersion;
70
86
  metadata?: EndpointMetadata;
71
87
  }): CredentialRequestClientBuilder {
72
- const { request, metadata } = opts;
88
+ const { request } = opts;
73
89
  const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
90
+ let builder;
91
+
74
92
  if (version < OpenId4VCIVersion.VER_1_0_13) {
75
- throw new Error('Versions below v1.0.13 (draft 13) are not supported.');
76
- }
77
- const builder = new CredentialRequestClientBuilder();
78
- const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
79
- builder.withVersion(version);
80
- builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
81
- if (metadata?.deferred_credential_endpoint) {
82
- builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
83
- }
84
- const ids: string[] = (request.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids;
85
- // if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
86
- if (ids.length && ids.length === 1) {
87
- builder.withCredentialIdentifier(ids[0]);
93
+ builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest(opts);
94
+ } else {
95
+ builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest(opts);
88
96
  }
89
- return builder;
97
+
98
+ return new CredentialRequestClientBuilder(builder);
90
99
  }
91
100
 
92
101
  public static fromCredentialOffer({
@@ -96,78 +105,100 @@ export class CredentialRequestClientBuilder {
96
105
  credentialOffer: CredentialOfferRequestWithBaseUrl;
97
106
  metadata?: EndpointMetadata;
98
107
  }): CredentialRequestClientBuilder {
99
- return CredentialRequestClientBuilder.fromCredentialOfferRequest({
100
- request: credentialOffer,
101
- metadata,
102
- version: credentialOffer.version,
103
- });
108
+ const version = determineSpecVersionFromOffer(credentialOffer.credential_offer);
109
+ let builder;
110
+
111
+ if (version < OpenId4VCIVersion.VER_1_0_13) {
112
+ builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
113
+ credentialOffer,
114
+ metadata,
115
+ });
116
+ } else {
117
+ builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
118
+ credentialOffer,
119
+ metadata,
120
+ });
121
+ }
122
+
123
+ return new CredentialRequestClientBuilder(builder);
124
+ }
125
+
126
+ public getVersion(): OpenId4VCIVersion | undefined {
127
+ return this._builder.version;
104
128
  }
105
129
 
106
- public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
107
- this.credentialEndpoint = metadata.credential_endpoint;
130
+ public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13): this {
131
+ if (isV1_0_13(this._builder)) {
132
+ this._builder.withCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadataV1_0_13);
133
+ } else {
134
+ this._builder.withCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadata);
135
+ }
108
136
  return this;
109
137
  }
110
138
 
111
139
  public withCredentialEndpoint(credentialEndpoint: string): this {
112
- this.credentialEndpoint = credentialEndpoint;
140
+ this._builder.withCredentialEndpoint(credentialEndpoint);
113
141
  return this;
114
142
  }
115
143
 
116
- public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
117
- this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
144
+ public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13): this {
145
+ if (isV1_0_13(this._builder)) {
146
+ this._builder.withDeferredCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadataV1_0_13);
147
+ } else {
148
+ this._builder.withDeferredCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadata);
149
+ }
118
150
  return this;
119
151
  }
120
152
 
121
153
  public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
122
- this.deferredCredentialEndpoint = deferredCredentialEndpoint;
154
+ this._builder.withDeferredCredentialEndpoint(deferredCredentialEndpoint);
123
155
  return this;
124
156
  }
125
157
 
126
158
  public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
127
- this.deferredCredentialAwait = deferredCredentialAwait;
128
- this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
159
+ this._builder.withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS);
129
160
  return this;
130
161
  }
131
162
 
132
163
  public withCredentialIdentifier(credentialIdentifier: string): this {
133
- this.credentialIdentifier = credentialIdentifier;
164
+ if (this._builder.version === undefined || this._builder.version < OpenId4VCIVersion.VER_1_0_13) {
165
+ throw new Error('Version of spec should be equal or higher than v1_0_13');
166
+ }
167
+ (this._builder as CredentialRequestClientBuilderV1_0_13).withCredentialIdentifier(credentialIdentifier);
134
168
  return this;
135
169
  }
136
170
 
137
171
  public withCredentialType(credentialTypes: string | string[]): this {
138
- this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
172
+ this._builder.withCredentialType(credentialTypes);
139
173
  return this;
140
174
  }
141
175
 
142
176
  public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
143
- this.format = format;
177
+ this._builder.withFormat(format);
144
178
  return this;
145
179
  }
146
180
 
147
181
  public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
148
- this.subjectIssuance = subjectIssuance;
182
+ this._builder.withSubjectIssuance(subjectIssuance);
149
183
  return this;
150
184
  }
151
185
 
152
186
  public withToken(accessToken: string): this {
153
- this.token = accessToken;
187
+ this._builder.withToken(accessToken);
154
188
  return this;
155
189
  }
156
190
 
157
191
  public withTokenFromResponse(response: AccessTokenResponse): this {
158
- this.token = response.access_token;
192
+ this._builder.withTokenFromResponse(response);
159
193
  return this;
160
194
  }
161
195
 
162
196
  public withVersion(version: OpenId4VCIVersion): this {
163
- this.version = version;
197
+ this._builder.withVersion(version);
164
198
  return this;
165
199
  }
166
200
 
167
- public build(): CredentialRequestClient {
168
- if (!this.version) {
169
- this.withVersion(OpenId4VCIVersion.VER_1_0_11);
170
- }
171
- return new CredentialRequestClient(this);
201
+ public build() {
202
+ return this._builder.build();
172
203
  }
173
204
  }
@@ -0,0 +1,173 @@
1
+ import {
2
+ AccessTokenResponse,
3
+ CredentialIssuerMetadataV1_0_13,
4
+ CredentialOfferPayloadV1_0_13,
5
+ CredentialOfferRequestWithBaseUrl,
6
+ determineSpecVersionFromOffer,
7
+ EndpointMetadata,
8
+ ExperimentalSubjectIssuance,
9
+ getIssuerFromCredentialOfferPayload,
10
+ OID4VCICredentialFormat,
11
+ OpenId4VCIVersion,
12
+ UniformCredentialOfferRequest,
13
+ } from '@sphereon/oid4vci-common';
14
+ import { CredentialFormat } from '@sphereon/ssi-types';
15
+
16
+ import { CredentialOfferClient } from './CredentialOfferClient';
17
+ import { CredentialRequestClient } from './CredentialRequestClient';
18
+
19
+ export class CredentialRequestClientBuilderV1_0_13 {
20
+ credentialEndpoint?: string;
21
+ deferredCredentialEndpoint?: string;
22
+ deferredCredentialAwait = false;
23
+ deferredCredentialIntervalInMS = 5000;
24
+ credentialIdentifier?: string;
25
+ credentialTypes?: string[] = [];
26
+ format?: CredentialFormat | OID4VCICredentialFormat;
27
+ token?: string;
28
+ version?: OpenId4VCIVersion;
29
+ subjectIssuance?: ExperimentalSubjectIssuance;
30
+
31
+ public static fromCredentialIssuer({
32
+ credentialIssuer,
33
+ metadata,
34
+ version,
35
+ credentialIdentifier,
36
+ credentialTypes,
37
+ }: {
38
+ credentialIssuer: string;
39
+ metadata?: EndpointMetadata;
40
+ version?: OpenId4VCIVersion;
41
+ credentialIdentifier?: string;
42
+ credentialTypes?: string | string[];
43
+ }): CredentialRequestClientBuilderV1_0_13 {
44
+ const issuer = credentialIssuer;
45
+ const builder = new CredentialRequestClientBuilderV1_0_13();
46
+ builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_13);
47
+ builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
48
+ if (metadata?.deferred_credential_endpoint) {
49
+ builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
50
+ }
51
+ if (credentialIdentifier) {
52
+ builder.withCredentialIdentifier(credentialIdentifier);
53
+ }
54
+ if (credentialTypes) {
55
+ builder.withCredentialType(credentialTypes);
56
+ }
57
+ return builder;
58
+ }
59
+
60
+ public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilderV1_0_13> {
61
+ const offer = await CredentialOfferClient.fromURI(uri);
62
+ return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
63
+ }
64
+
65
+ public static fromCredentialOfferRequest(opts: {
66
+ request: UniformCredentialOfferRequest;
67
+ scheme?: string;
68
+ baseUrl?: string;
69
+ version?: OpenId4VCIVersion;
70
+ metadata?: EndpointMetadata;
71
+ }): CredentialRequestClientBuilderV1_0_13 {
72
+ const { request, metadata } = opts;
73
+ const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
74
+ if (version < OpenId4VCIVersion.VER_1_0_13) {
75
+ throw new Error('Versions below v1.0.13 (draft 13) are not supported.');
76
+ }
77
+ const builder = new CredentialRequestClientBuilderV1_0_13();
78
+ const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
79
+ builder.withVersion(version);
80
+ builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
81
+ if (metadata?.deferred_credential_endpoint) {
82
+ builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
83
+ }
84
+ const ids: string[] = (request.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids;
85
+ // if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
86
+ if (ids.length && ids.length === 1) {
87
+ builder.withCredentialIdentifier(ids[0]);
88
+ }
89
+ return builder;
90
+ }
91
+
92
+ public static fromCredentialOffer({
93
+ credentialOffer,
94
+ metadata,
95
+ }: {
96
+ credentialOffer: CredentialOfferRequestWithBaseUrl;
97
+ metadata?: EndpointMetadata;
98
+ }): CredentialRequestClientBuilderV1_0_13 {
99
+ return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
100
+ request: credentialOffer,
101
+ metadata,
102
+ version: credentialOffer.version,
103
+ });
104
+ }
105
+
106
+ public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
107
+ this.credentialEndpoint = metadata.credential_endpoint;
108
+ return this;
109
+ }
110
+
111
+ public withCredentialEndpoint(credentialEndpoint: string): this {
112
+ this.credentialEndpoint = credentialEndpoint;
113
+ return this;
114
+ }
115
+
116
+ public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
117
+ this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
118
+ return this;
119
+ }
120
+
121
+ public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
122
+ this.deferredCredentialEndpoint = deferredCredentialEndpoint;
123
+ return this;
124
+ }
125
+
126
+ public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
127
+ this.deferredCredentialAwait = deferredCredentialAwait;
128
+ this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
129
+ return this;
130
+ }
131
+
132
+ public withCredentialIdentifier(credentialIdentifier: string): this {
133
+ this.credentialIdentifier = credentialIdentifier;
134
+ return this;
135
+ }
136
+
137
+ public withCredentialType(credentialTypes: string | string[]): this {
138
+ this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
139
+ return this;
140
+ }
141
+
142
+ public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
143
+ this.format = format;
144
+ return this;
145
+ }
146
+
147
+ public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
148
+ this.subjectIssuance = subjectIssuance;
149
+ return this;
150
+ }
151
+
152
+ public withToken(accessToken: string): this {
153
+ this.token = accessToken;
154
+ return this;
155
+ }
156
+
157
+ public withTokenFromResponse(response: AccessTokenResponse): this {
158
+ this.token = response.access_token;
159
+ return this;
160
+ }
161
+
162
+ public withVersion(version: OpenId4VCIVersion): this {
163
+ this.version = version;
164
+ return this;
165
+ }
166
+
167
+ public build(): CredentialRequestClient {
168
+ if (!this.version) {
169
+ this.withVersion(OpenId4VCIVersion.VER_1_0_11);
170
+ }
171
+ return new CredentialRequestClient(this);
172
+ }
173
+ }
@@ -41,7 +41,7 @@ import { createAuthorizationRequestUrl } from './AuthorizationCodeClient';
41
41
  import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
42
42
  import { CredentialOfferClient } from './CredentialOfferClient';
43
43
  import { CredentialRequestOpts } from './CredentialRequestClient';
44
- import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder';
44
+ import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
45
45
  import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
46
46
  import { MetadataClient } from './MetadataClient';
47
47
  import { OpenID4VCIClientStateV1_0_11 } from './OpenID4VCIClientV1_0_11';
@@ -273,6 +273,7 @@ export class OpenID4VCIClient {
273
273
  authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
274
274
  code?: string; // Directly pass in a code from an auth response
275
275
  redirectUri?: string;
276
+ additionalRequestParams?: Record<string, any>;
276
277
  }): Promise<AccessTokenResponse> {
277
278
  const { pin, clientId } = opts ?? {};
278
279
  let { redirectUri } = opts ?? {};
@@ -312,6 +313,7 @@ export class OpenID4VCIClient {
312
313
  code,
313
314
  redirectUri,
314
315
  asOpts: { clientId: this.clientId },
316
+ ...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
315
317
  });
316
318
 
317
319
  if (response.errorBody) {
@@ -368,7 +370,7 @@ export class OpenID4VCIClient {
368
370
  if (jwk) this._state.jwk = jwk;
369
371
  if (kid) this._state.kid = kid;
370
372
 
371
- let requestBuilder: CredentialRequestClientBuilder | CredentialRequestClientBuilderV1_0_11;
373
+ let requestBuilder: CredentialRequestClientBuilderV1_0_13 | CredentialRequestClientBuilderV1_0_11;
372
374
  if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
373
375
  requestBuilder = this.credentialOffer
374
376
  ? CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
@@ -383,11 +385,11 @@ export class OpenID4VCIClient {
383
385
  });
384
386
  } else {
385
387
  requestBuilder = this.credentialOffer
386
- ? CredentialRequestClientBuilder.fromCredentialOffer({
388
+ ? CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
387
389
  credentialOffer: this.credentialOffer,
388
390
  metadata: this.endpointMetadata,
389
391
  })
390
- : CredentialRequestClientBuilder.fromCredentialIssuer({
392
+ : CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
391
393
  credentialIssuer: this.getIssuer(),
392
394
  credentialTypes,
393
395
  metadata: this.endpointMetadata,
@@ -20,13 +20,8 @@ import * as jose from 'jose';
20
20
  // @ts-ignore
21
21
  import nock from 'nock';
22
22
 
23
- import {
24
- CredentialOfferClientV1_0_11,
25
- CredentialRequestClientBuilder,
26
- CredentialRequestClientBuilderV1_0_11,
27
- MetadataClientV1_0_11,
28
- ProofOfPossessionBuilder,
29
- } from '..';
23
+ import { CredentialOfferClient, MetadataClient, ProofOfPossessionBuilder } from '..';
24
+ import { CredentialRequestClientBuilder } from '../CredentialRequestClientBuilder';
30
25
 
31
26
  import { IDENTIPROOF_ISSUER_URL, IDENTIPROOF_OID4VCI_METADATA, INITIATION_TEST, WALT_OID4VCI_METADATA } from './MetadataMocks';
32
27
  import { getMockData } from './data/VciDataFixtures';
@@ -154,14 +149,14 @@ describe('Credential Request Client with Walt.id ', () => {
154
149
  nock.cleanAll();
155
150
  const WALT_IRR_URI =
156
151
  'openid-initiate-issuance://?issuer=https%3A%2F%2Fjff.walt.id%2Fissuer-api%2Foidc%2F&credential_type=OpenBadgeCredential&pre-authorized_code=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhOTUyZjUxNi1jYWVmLTQ4YjMtODIxYy00OTRkYzgyNjljZjAiLCJwcmUtYXV0aG9yaXplZCI6dHJ1ZX0.YE5DlalcLC2ChGEg47CQDaN1gTxbaQqSclIVqsSAUHE&user_pin_required=false';
157
- const credentialOffer = await CredentialOfferClientV1_0_11.fromURI(WALT_IRR_URI);
152
+ const credentialOffer = await CredentialOfferClient.fromURI(WALT_IRR_URI);
158
153
 
159
154
  const request = credentialOffer.credential_offer;
160
- const metadata = await MetadataClientV1_0_11.retrieveAllMetadata(getIssuerFromCredentialOfferPayload(request) as string);
155
+ const metadata = await MetadataClient.retrieveAllMetadata(getIssuerFromCredentialOfferPayload(request) as string);
161
156
  expect(metadata.credential_endpoint).toEqual(WALT_OID4VCI_METADATA.credential_endpoint);
162
157
  expect(metadata.token_endpoint).toEqual(WALT_OID4VCI_METADATA.token_endpoint);
163
158
 
164
- const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
159
+ const credReqClient = CredentialRequestClientBuilder.fromCredentialOffer({
165
160
  credentialOffer,
166
161
  metadata,
167
162
  }).build();
@@ -205,7 +200,7 @@ describe('Credential Request Client with different issuers ', () => {
205
200
  const IRR_URI =
206
201
  'openid-initiate-issuance://?issuer=https%3A%2F%2Fjff.walt.id%2Fissuer-api%2Fdefault%2Foidc%2F&credential_type=OpenBadgeCredential&pre-authorized_code=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwMTc4OTNjYy04ZTY3LTQxNzItYWZlOS1lODcyYmYxNDBlNWMiLCJwcmUtYXV0aG9yaXplZCI6dHJ1ZX0.ODfq2AIhOcB61dAb3zMrXBJjPJaf53zkeHh_AssYyYA&user_pin_required=false';
207
202
  const credentialOffer = await (
208
- await CredentialRequestClientBuilderV1_0_11.fromURI({
203
+ await CredentialRequestClientBuilder.fromURI({
209
204
  uri: IRR_URI,
210
205
  metadata: getMockData('walt')?.metadata as unknown as EndpointMetadata,
211
206
  })
@@ -250,7 +245,7 @@ describe('Credential Request Client with different issuers ', () => {
250
245
  const IRR_URI =
251
246
  'openid-initiate-issuance://?issuer=https://launchpad.mattrlabs.com&credential_type=OpenBadgeCredential&pre-authorized_code=g0UCOj6RAN5AwHU6gczm_GzB4_lH6GW39Z0Dl2DOOiO';
252
247
  const credentialOffer = await (
253
- await CredentialRequestClientBuilderV1_0_11.fromURI({
248
+ await CredentialRequestClientBuilder.fromURI({
254
249
  uri: IRR_URI,
255
250
  metadata: getMockData('mattr')?.metadata as unknown as EndpointMetadata,
256
251
  })
@@ -273,7 +268,7 @@ describe('Credential Request Client with different issuers ', () => {
273
268
  const IRR_URI =
274
269
  'openid-initiate-issuance://?issuer=https://oidc4vc.diwala.io&credential_type=OpenBadgeCredential&pre-authorized_code=eyJhbGciOiJIUzI1NiJ9.eyJjcmVkZW50aWFsX3R5cGUiOiJPcGVuQmFkZ2VDcmVkZW50aWFsIiwiZXhwIjoxNjgxOTg0NDY3fQ.fEAHKz2nuWfiYHw406iNxr-81pWkNkbi31bWsYSf6Ng';
275
270
  const credentialOffer = await (
276
- await CredentialRequestClientBuilderV1_0_11.fromURI({
271
+ await CredentialRequestClientBuilder.fromURI({
277
272
  uri: IRR_URI,
278
273
  metadata: getMockData('diwala')?.metadata as unknown as EndpointMetadata,
279
274
  })
@@ -11,11 +11,13 @@ import {
11
11
  } from '@sphereon/oid4vci-common';
12
12
  import * as jose from 'jose';
13
13
 
14
- import { CredentialRequestClientBuilder, ProofOfPossessionBuilder } from '..';
14
+ import { CredentialRequestOpts, ProofOfPossessionBuilder } from '..';
15
+ import { CredentialRequestClientBuilder } from '../CredentialRequestClientBuilder';
15
16
 
16
17
  import { IDENTIPROOF_ISSUER_URL, IDENTIPROOF_OID4VCI_METADATA, INITIATION_TEST_URI, WALT_ISSUER_URL, WALT_OID4VCI_METADATA } from './MetadataMocks';
17
18
 
18
19
  const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN';
20
+ const partialJWT_withoutDid = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJlYmZlYjFmNzEyZWJjNmYxYzI3N';
19
21
 
20
22
  /*const jwtv1_0_08: Jwt = {
21
23
  header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
@@ -27,8 +29,15 @@ const jwtv1_0_11: Jwt = {
27
29
  payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
28
30
  };
29
31
 
32
+ const jwtv1_0_13_withoutDid: Jwt = {
33
+ header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'openid4vci-proof+jwt' },
34
+ payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
35
+ };
36
+
30
37
  const kid = 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1';
31
38
 
39
+ const kid_withoutDid = 'ebfeb1f712ebc6f1c276e12ec21/keys/1';
40
+
32
41
  let keypair: KeyPair;
33
42
 
34
43
  beforeAll(async () => {
@@ -81,7 +90,7 @@ describe('Credential Request Client Builder', () => {
81
90
  .build();
82
91
  expect(credReqClient.credentialRequestOpts.credentialEndpoint).toBe('https://oidc4vci.demo.spruceid.com/credential');
83
92
  expect(credReqClient.credentialRequestOpts.format).toBe('jwt_vc');
84
- expect(credReqClient.credentialRequestOpts.credentialIdentifier).toStrictEqual('credentialType');
93
+ expect((credReqClient.credentialRequestOpts as CredentialRequestOpts).credentialIdentifier).toStrictEqual('credentialType');
85
94
  expect(credReqClient.credentialRequestOpts.token).toBe('token');
86
95
  });
87
96
 
@@ -115,6 +124,35 @@ describe('Credential Request Client Builder', () => {
115
124
  }
116
125
  });
117
126
 
127
+ it('should build credential request correctly without did', async () => {
128
+ const credReqClient = (await CredentialRequestClientBuilder.fromURI({ uri: INITIATION_TEST_URI }))
129
+ .withCredentialEndpoint('https://oidc4vci.demo.spruceid.com/credential')
130
+ .withFormat('jwt_vc')
131
+ .withCredentialType('OpenBadgeCredential')
132
+ .build();
133
+ const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
134
+ jwt: jwtv1_0_13_withoutDid,
135
+ callbacks: {
136
+ signCallback: proofOfPossessionCallbackFunction,
137
+ verifyCallback: proofOfPossessionVerifierCallbackFunction,
138
+ },
139
+ version: OpenId4VCIVersion.VER_1_0_13,
140
+ })
141
+ .withClientId('sphereon:wallet')
142
+ .withKid(kid_withoutDid)
143
+ .build();
144
+ await proofOfPossessionVerifierCallbackFunction({ ...proof, kid: kid_withoutDid });
145
+ const credentialRequest: CredentialRequestV1_0_13 = await credReqClient.createCredentialRequest({
146
+ proofInput: proof,
147
+ credentialTypes: 'OpenBadgeCredential',
148
+ version: OpenId4VCIVersion.VER_1_0_13,
149
+ });
150
+ expect(credentialRequest.proof?.jwt).toContain(partialJWT_withoutDid);
151
+ if ('types' in credentialRequest) {
152
+ expect(credentialRequest.types).toStrictEqual(['OpenBadgeCredential']);
153
+ }
154
+ });
155
+
118
156
  it('should build correctly from metadata', async () => {
119
157
  const credReqClient = (
120
158
  await CredentialRequestClientBuilder.fromURI({