@sphereon/oid4vci-client 0.12.1-next.2 → 0.12.1-next.22

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 (60) hide show
  1. package/dist/AccessTokenClient.d.ts.map +1 -1
  2. package/dist/AccessTokenClient.js +7 -5
  3. package/dist/AccessTokenClient.js.map +1 -1
  4. package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -1
  5. package/dist/AccessTokenClientV1_0_11.js +7 -5
  6. package/dist/AccessTokenClientV1_0_11.js.map +1 -1
  7. package/dist/CredentialRequestClient.d.ts +3 -2
  8. package/dist/CredentialRequestClient.d.ts.map +1 -1
  9. package/dist/CredentialRequestClient.js.map +1 -1
  10. package/dist/CredentialRequestClientBuilder.d.ts +7 -15
  11. package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
  12. package/dist/CredentialRequestClientBuilder.js +79 -55
  13. package/dist/CredentialRequestClientBuilder.js.map +1 -1
  14. package/dist/CredentialRequestClientBuilderV1_0_13.d.ts +51 -0
  15. package/dist/CredentialRequestClientBuilderV1_0_13.d.ts.map +1 -0
  16. package/dist/CredentialRequestClientBuilderV1_0_13.js +130 -0
  17. package/dist/CredentialRequestClientBuilderV1_0_13.js.map +1 -0
  18. package/dist/OpenID4VCIClient.d.ts +3 -1
  19. package/dist/OpenID4VCIClient.d.ts.map +1 -1
  20. package/dist/OpenID4VCIClient.js +31 -16
  21. package/dist/OpenID4VCIClient.js.map +1 -1
  22. package/dist/OpenID4VCIClientV1_0_11.d.ts +3 -2
  23. package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -1
  24. package/dist/OpenID4VCIClientV1_0_11.js +26 -10
  25. package/dist/OpenID4VCIClientV1_0_11.js.map +1 -1
  26. package/dist/OpenID4VCIClientV1_0_13.d.ts +2 -1
  27. package/dist/OpenID4VCIClientV1_0_13.d.ts.map +1 -1
  28. package/dist/OpenID4VCIClientV1_0_13.js +26 -12
  29. package/dist/OpenID4VCIClientV1_0_13.js.map +1 -1
  30. package/dist/functions/AccessTokenUtil.d.ts +5 -0
  31. package/dist/functions/AccessTokenUtil.d.ts.map +1 -0
  32. package/dist/functions/AccessTokenUtil.js +55 -0
  33. package/dist/functions/AccessTokenUtil.js.map +1 -0
  34. package/dist/functions/index.d.ts +2 -0
  35. package/dist/functions/index.d.ts.map +1 -1
  36. package/dist/functions/index.js +2 -0
  37. package/dist/functions/index.js.map +1 -1
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/lib/AccessTokenClient.ts +5 -4
  43. package/lib/AccessTokenClientV1_0_11.ts +6 -3
  44. package/lib/CredentialRequestClient.ts +3 -2
  45. package/lib/CredentialRequestClientBuilder.ts +98 -67
  46. package/lib/CredentialRequestClientBuilderV1_0_13.ts +173 -0
  47. package/lib/OpenID4VCIClient.ts +33 -6
  48. package/lib/OpenID4VCIClientV1_0_11.ts +32 -5
  49. package/lib/OpenID4VCIClientV1_0_13.ts +30 -5
  50. package/lib/__tests__/CredentialRequestClient.spec.ts +8 -13
  51. package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +40 -2
  52. package/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +96 -0
  53. package/lib/__tests__/IT.spec.ts +148 -111
  54. package/lib/__tests__/MetadataMocks.ts +35 -0
  55. package/lib/__tests__/ProofOfPossessionBuilder.spec.ts +85 -0
  56. package/lib/__tests__/SdJwt.spec.ts +103 -0
  57. package/lib/functions/AccessTokenUtil.ts +45 -0
  58. package/lib/functions/index.ts +2 -0
  59. package/lib/index.ts +1 -0
  60. 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
+ }
@@ -3,6 +3,7 @@ import {
3
3
  Alg,
4
4
  AuthorizationRequestOpts,
5
5
  AuthorizationResponse,
6
+ AuthorizationServerOpts,
6
7
  AuthzFlowType,
7
8
  CodeChallengeMethod,
8
9
  CredentialConfigurationSupported,
@@ -41,8 +42,8 @@ import { createAuthorizationRequestUrl } from './AuthorizationCodeClient';
41
42
  import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
42
43
  import { CredentialOfferClient } from './CredentialOfferClient';
43
44
  import { CredentialRequestOpts } from './CredentialRequestClient';
44
- import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder';
45
45
  import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
46
+ import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
46
47
  import { MetadataClient } from './MetadataClient';
47
48
  import { OpenID4VCIClientStateV1_0_11 } from './OpenID4VCIClientV1_0_11';
48
49
  import { OpenID4VCIClientStateV1_0_13 } from './OpenID4VCIClientV1_0_13';
@@ -273,8 +274,10 @@ export class OpenID4VCIClient {
273
274
  authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
274
275
  code?: string; // Directly pass in a code from an auth response
275
276
  redirectUri?: string;
277
+ additionalRequestParams?: Record<string, any>;
278
+ asOpts?: AuthorizationServerOpts;
276
279
  }): Promise<AccessTokenResponse> {
277
- const { pin, clientId } = opts ?? {};
280
+ const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
278
281
  let { redirectUri } = opts ?? {};
279
282
  if (opts?.authorizationResponse) {
280
283
  this._state.authorizationCodeResponse = { ...toAuthorizationResponsePayload(opts.authorizationResponse) };
@@ -288,6 +291,26 @@ export class OpenID4VCIClient {
288
291
  }
289
292
  this.assertIssuerData();
290
293
 
294
+ const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
295
+ const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
296
+ const clientAssertionType =
297
+ asOpts.clientOpts?.clientAssertionType ??
298
+ (kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
299
+ ? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
300
+ : undefined);
301
+ if (this.isEBSI() || (clientId && kid)) {
302
+ if (!clientId) {
303
+ throw Error(`Client id expected for EBSI`);
304
+ }
305
+ asOpts.clientOpts = {
306
+ ...asOpts.clientOpts,
307
+ clientId,
308
+ ...(kid && { kid }),
309
+ ...(clientAssertionType && { clientAssertionType }),
310
+ signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
311
+ };
312
+ }
313
+
291
314
  if (clientId) {
292
315
  this._state.clientId = clientId;
293
316
  }
@@ -311,7 +334,8 @@ export class OpenID4VCIClient {
311
334
  ...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
312
335
  code,
313
336
  redirectUri,
314
- asOpts: { clientId: this.clientId },
337
+ asOpts,
338
+ ...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
315
339
  });
316
340
 
317
341
  if (response.errorBody) {
@@ -368,7 +392,7 @@ export class OpenID4VCIClient {
368
392
  if (jwk) this._state.jwk = jwk;
369
393
  if (kid) this._state.kid = kid;
370
394
 
371
- let requestBuilder: CredentialRequestClientBuilder | CredentialRequestClientBuilderV1_0_11;
395
+ let requestBuilder: CredentialRequestClientBuilderV1_0_13 | CredentialRequestClientBuilderV1_0_11;
372
396
  if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
373
397
  requestBuilder = this.credentialOffer
374
398
  ? CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
@@ -383,11 +407,11 @@ export class OpenID4VCIClient {
383
407
  });
384
408
  } else {
385
409
  requestBuilder = this.credentialOffer
386
- ? CredentialRequestClientBuilder.fromCredentialOffer({
410
+ ? CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
387
411
  credentialOffer: this.credentialOffer,
388
412
  metadata: this.endpointMetadata,
389
413
  })
390
- : CredentialRequestClientBuilder.fromCredentialIssuer({
414
+ : CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
391
415
  credentialIssuer: this.getIssuer(),
392
416
  credentialTypes,
393
417
  metadata: this.endpointMetadata,
@@ -646,6 +670,9 @@ export class OpenID4VCIClient {
646
670
  }
647
671
  // this.assertIssuerData();
648
672
  return (
673
+ this.clientId?.includes('ebsi') ||
674
+ this._state.kid?.includes('did:ebsi:') ||
675
+ this.getIssuer().includes('ebsi') ||
649
676
  this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ||
650
677
  this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes('ebsi.eu')
651
678
  );
@@ -3,6 +3,7 @@ import {
3
3
  Alg,
4
4
  AuthorizationRequestOpts,
5
5
  AuthorizationResponse,
6
+ AuthorizationServerOpts,
6
7
  AuthzFlowType,
7
8
  CodeChallengeMethod,
8
9
  CredentialConfigurationSupported,
@@ -259,6 +260,7 @@ export class OpenID4VCIClientV1_0_11 {
259
260
  authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
260
261
  code?: string; // Directly pass in a code from an auth response
261
262
  redirectUri?: string;
263
+ asOpts?: AuthorizationServerOpts;
262
264
  }): Promise<AccessTokenResponse> {
263
265
  const { pin, clientId } = opts ?? {};
264
266
  let { redirectUri } = opts ?? {};
@@ -288,6 +290,25 @@ export class OpenID4VCIClientV1_0_11 {
288
290
  if (this._state.authorizationRequestOpts?.redirectUri && !redirectUri) {
289
291
  redirectUri = this._state.authorizationRequestOpts.redirectUri;
290
292
  }
293
+ const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
294
+ const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
295
+ const clientAssertionType =
296
+ asOpts.clientOpts?.clientAssertionType ??
297
+ (kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
298
+ ? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
299
+ : undefined);
300
+ if (this.isEBSI() || (clientId && kid)) {
301
+ if (!clientId) {
302
+ throw Error(`Client id expected for EBSI`);
303
+ }
304
+ asOpts.clientOpts = {
305
+ ...asOpts.clientOpts,
306
+ clientId,
307
+ ...(kid && { kid }),
308
+ ...(clientAssertionType && { clientAssertionType }),
309
+ signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
310
+ };
311
+ }
291
312
 
292
313
  const response = await accessTokenClient.acquireAccessToken({
293
314
  credentialOffer: this.credentialOffer,
@@ -297,7 +318,7 @@ export class OpenID4VCIClientV1_0_11 {
297
318
  ...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
298
319
  code,
299
320
  redirectUri,
300
- asOpts: { clientId: this.clientId },
321
+ asOpts,
301
322
  });
302
323
 
303
324
  if (response.errorBody) {
@@ -584,8 +605,8 @@ export class OpenID4VCIClientV1_0_11 {
584
605
  */
585
606
  public isEBSI() {
586
607
  if (
587
- (this.credentialOffer?.credential_offer as CredentialOfferPayloadV1_0_11)['credentials'] &&
588
- (this.credentialOffer?.credential_offer as CredentialOfferPayloadV1_0_11).credentials.find(
608
+ this.credentialOffer &&
609
+ (this.credentialOffer?.credential_offer as CredentialOfferPayloadV1_0_11)?.credentials?.find(
589
610
  (cred) =>
590
611
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
591
612
  // @ts-ignore
@@ -594,8 +615,14 @@ export class OpenID4VCIClientV1_0_11 {
594
615
  ) {
595
616
  return true;
596
617
  }
597
- this.assertIssuerData();
598
- return this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') === true;
618
+ // this.assertIssuerData();
619
+ return (
620
+ this.clientId?.includes('ebsi') ||
621
+ this._state.kid?.includes('did:ebsi:') ||
622
+ this.getIssuer().includes('ebsi') ||
623
+ this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ||
624
+ this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes('ebsi.eu')
625
+ );
599
626
  }
600
627
 
601
628
  private assertIssuerData(): void {
@@ -3,6 +3,7 @@ import {
3
3
  Alg,
4
4
  AuthorizationRequestOpts,
5
5
  AuthorizationResponse,
6
+ AuthorizationServerOpts,
6
7
  AuthzFlowType,
7
8
  CodeChallengeMethod,
8
9
  CredentialConfigurationSupportedV1_0_13,
@@ -36,8 +37,7 @@ import { CredentialRequestOpts } from './CredentialRequestClient';
36
37
  import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder';
37
38
  import { MetadataClientV1_0_13 } from './MetadataClientV1_0_13';
38
39
  import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
39
- import { generateMissingPKCEOpts } from './functions';
40
- import { sendNotification } from './functions';
40
+ import { generateMissingPKCEOpts, sendNotification } from './functions';
41
41
 
42
42
  const debug = Debug('sphereon:oid4vci');
43
43
 
@@ -265,6 +265,7 @@ export class OpenID4VCIClientV1_0_13 {
265
265
  authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
266
266
  code?: string; // Directly pass in a code from an auth response
267
267
  redirectUri?: string;
268
+ asOpts?: AuthorizationServerOpts;
268
269
  }): Promise<AccessTokenResponse> {
269
270
  const { pin, clientId } = opts ?? {};
270
271
  let { redirectUri } = opts ?? {};
@@ -279,6 +280,25 @@ export class OpenID4VCIClientV1_0_13 {
279
280
  this._state.pkce.codeVerifier = opts.codeVerifier;
280
281
  }
281
282
  this.assertIssuerData();
283
+ const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
284
+ const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
285
+ const clientAssertionType =
286
+ asOpts.clientOpts?.clientAssertionType ??
287
+ (kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
288
+ ? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
289
+ : undefined);
290
+ if (this.isEBSI() || (clientId && kid)) {
291
+ if (!clientId) {
292
+ throw Error(`Client id expected for EBSI`);
293
+ }
294
+ asOpts.clientOpts = {
295
+ ...asOpts.clientOpts,
296
+ clientId,
297
+ ...(kid && { kid }),
298
+ ...(clientAssertionType && { clientAssertionType }),
299
+ signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
300
+ };
301
+ }
282
302
 
283
303
  if (clientId) {
284
304
  this._state.clientId = clientId;
@@ -302,7 +322,7 @@ export class OpenID4VCIClientV1_0_13 {
302
322
  ...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
303
323
  code,
304
324
  redirectUri,
305
- asOpts: { clientId: this.clientId },
325
+ asOpts,
306
326
  });
307
327
 
308
328
  if (response.errorBody) {
@@ -636,8 +656,13 @@ export class OpenID4VCIClientV1_0_13 {
636
656
  }
637
657
  }
638
658
 
639
- this.assertIssuerData();
640
- return this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ?? false;
659
+ return (
660
+ this.clientId?.includes('ebsi') ||
661
+ this._state.kid?.includes('did:ebsi:') ||
662
+ this.getIssuer().includes('ebsi') ||
663
+ this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ||
664
+ this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes('ebsi.eu')
665
+ );
641
666
  }
642
667
 
643
668
  private assertIssuerData(): void {