@sphereon/oid4vci-client 0.16.1-next.4 → 0.16.1-next.402

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 (112) hide show
  1. package/README.md +0 -1
  2. package/dist/AccessTokenClient.d.ts.map +1 -1
  3. package/dist/AccessTokenClient.js +10 -9
  4. package/dist/AccessTokenClient.js.map +1 -1
  5. package/dist/AccessTokenClientV1_0_11.js +9 -8
  6. package/dist/AccessTokenClientV1_0_11.js.map +1 -1
  7. package/dist/AuthorizationCodeClient.d.ts +11 -1
  8. package/dist/AuthorizationCodeClient.d.ts.map +1 -1
  9. package/dist/AuthorizationCodeClient.js +66 -6
  10. package/dist/AuthorizationCodeClient.js.map +1 -1
  11. package/dist/AuthorizationCodeClientV1_0_11.js.map +1 -1
  12. package/dist/CredentialOfferClient.d.ts.map +1 -1
  13. package/dist/CredentialOfferClient.js +14 -15
  14. package/dist/CredentialOfferClient.js.map +1 -1
  15. package/dist/CredentialOfferClientV1_0_11.js +1 -1
  16. package/dist/CredentialOfferClientV1_0_11.js.map +1 -1
  17. package/dist/CredentialOfferClientV1_0_13.d.ts.map +1 -1
  18. package/dist/CredentialOfferClientV1_0_13.js +18 -17
  19. package/dist/CredentialOfferClientV1_0_13.js.map +1 -1
  20. package/dist/CredentialRequestClient.d.ts +37 -13
  21. package/dist/CredentialRequestClient.d.ts.map +1 -1
  22. package/dist/CredentialRequestClient.js +57 -14
  23. package/dist/CredentialRequestClient.js.map +1 -1
  24. package/dist/CredentialRequestClientBuilder.d.ts +1 -0
  25. package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
  26. package/dist/CredentialRequestClientBuilder.js +4 -0
  27. package/dist/CredentialRequestClientBuilder.js.map +1 -1
  28. package/dist/CredentialRequestClientBuilderV1_0_11.d.ts +2 -0
  29. package/dist/CredentialRequestClientBuilderV1_0_11.d.ts.map +1 -1
  30. package/dist/CredentialRequestClientBuilderV1_0_11.js +4 -0
  31. package/dist/CredentialRequestClientBuilderV1_0_11.js.map +1 -1
  32. package/dist/CredentialRequestClientBuilderV1_0_13.d.ts +2 -0
  33. package/dist/CredentialRequestClientBuilderV1_0_13.d.ts.map +1 -1
  34. package/dist/CredentialRequestClientBuilderV1_0_13.js +6 -1
  35. package/dist/CredentialRequestClientBuilderV1_0_13.js.map +1 -1
  36. package/dist/CredentialRequestClientV1_0_11.d.ts +4 -4
  37. package/dist/CredentialRequestClientV1_0_11.d.ts.map +1 -1
  38. package/dist/CredentialRequestClientV1_0_11.js +10 -0
  39. package/dist/CredentialRequestClientV1_0_11.js.map +1 -1
  40. package/dist/MetadataClient.d.ts +1 -0
  41. package/dist/MetadataClient.d.ts.map +1 -1
  42. package/dist/MetadataClient.js +13 -5
  43. package/dist/MetadataClient.js.map +1 -1
  44. package/dist/MetadataClientV1_0_11.d.ts.map +1 -1
  45. package/dist/MetadataClientV1_0_11.js +8 -1
  46. package/dist/MetadataClientV1_0_11.js.map +1 -1
  47. package/dist/MetadataClientV1_0_13.d.ts +1 -0
  48. package/dist/MetadataClientV1_0_13.d.ts.map +1 -1
  49. package/dist/MetadataClientV1_0_13.js +13 -5
  50. package/dist/MetadataClientV1_0_13.js.map +1 -1
  51. package/dist/OpenID4VCIClient.d.ts +15 -7
  52. package/dist/OpenID4VCIClient.d.ts.map +1 -1
  53. package/dist/OpenID4VCIClient.js +64 -22
  54. package/dist/OpenID4VCIClient.js.map +1 -1
  55. package/dist/OpenID4VCIClientV1_0_11.d.ts +9 -5
  56. package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -1
  57. package/dist/OpenID4VCIClientV1_0_11.js +42 -17
  58. package/dist/OpenID4VCIClientV1_0_11.js.map +1 -1
  59. package/dist/OpenID4VCIClientV1_0_13.d.ts +29 -7
  60. package/dist/OpenID4VCIClientV1_0_13.d.ts.map +1 -1
  61. package/dist/OpenID4VCIClientV1_0_13.js +117 -47
  62. package/dist/OpenID4VCIClientV1_0_13.js.map +1 -1
  63. package/dist/ProofOfPossessionBuilder.d.ts +11 -11
  64. package/dist/ProofOfPossessionBuilder.d.ts.map +1 -1
  65. package/dist/ProofOfPossessionBuilder.js.map +1 -1
  66. package/dist/functions/AccessTokenUtil.js +2 -2
  67. package/dist/functions/AccessTokenUtil.js.map +1 -1
  68. package/dist/functions/CredentialOfferCommons.d.ts +19 -0
  69. package/dist/functions/CredentialOfferCommons.d.ts.map +1 -0
  70. package/dist/functions/CredentialOfferCommons.js +50 -0
  71. package/dist/functions/CredentialOfferCommons.js.map +1 -0
  72. package/dist/functions/index.d.ts +1 -0
  73. package/dist/functions/index.d.ts.map +1 -1
  74. package/dist/functions/index.js +1 -0
  75. package/dist/functions/index.js.map +1 -1
  76. package/dist/functions/notifications.d.ts +2 -2
  77. package/dist/functions/notifications.d.ts.map +1 -1
  78. package/dist/functions/notifications.js.map +1 -1
  79. package/lib/AccessTokenClient.ts +13 -12
  80. package/lib/AccessTokenClientV1_0_11.ts +11 -11
  81. package/lib/AuthorizationCodeClient.ts +92 -4
  82. package/lib/AuthorizationCodeClientV1_0_11.ts +2 -2
  83. package/lib/CredentialOfferClient.ts +12 -21
  84. package/lib/CredentialOfferClientV1_0_11.ts +1 -1
  85. package/lib/CredentialOfferClientV1_0_13.ts +17 -23
  86. package/lib/CredentialRequestClient.ts +98 -21
  87. package/lib/CredentialRequestClientBuilder.ts +4 -0
  88. package/lib/CredentialRequestClientBuilderV1_0_11.ts +6 -0
  89. package/lib/CredentialRequestClientBuilderV1_0_13.ts +10 -1
  90. package/lib/CredentialRequestClientV1_0_11.ts +14 -4
  91. package/lib/MetadataClient.ts +13 -2
  92. package/lib/MetadataClientV1_0_11.ts +10 -1
  93. package/lib/MetadataClientV1_0_13.ts +12 -2
  94. package/lib/OpenID4VCIClient.ts +80 -13
  95. package/lib/OpenID4VCIClientV1_0_11.ts +57 -12
  96. package/lib/OpenID4VCIClientV1_0_13.ts +160 -46
  97. package/lib/ProofOfPossessionBuilder.ts +13 -13
  98. package/lib/__tests__/AccessTokenClient.spec.ts +0 -2
  99. package/lib/__tests__/CredentialRequestClient.spec.ts +53 -0
  100. package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +1 -1
  101. package/lib/__tests__/IT.spec.ts +1 -4
  102. package/lib/__tests__/MetadataClient.spec.ts +24 -2
  103. package/lib/__tests__/OpenID4VCIClient.spec.ts +44 -1
  104. package/lib/__tests__/OpenID4VCIClientV1_0_11.spec.ts +43 -0
  105. package/lib/__tests__/OpenID4VCIClientV1_0_13.spec.ts +43 -0
  106. package/lib/__tests__/SdJwt.spec.ts +16 -3
  107. package/lib/__tests__/SphereonE2E.spec.test.ts +1 -1
  108. package/lib/functions/AccessTokenUtil.ts +2 -2
  109. package/lib/functions/CredentialOfferCommons.ts +52 -0
  110. package/lib/functions/index.ts +1 -0
  111. package/lib/functions/notifications.ts +2 -2
  112. package/package.json +5 -6
@@ -2,8 +2,10 @@ import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereo
2
2
  import {
3
3
  acquireDeferredCredential,
4
4
  CredentialRequestV1_0_13,
5
+ CredentialRequestWithoutProofV1_0_13,
5
6
  CredentialResponse,
6
7
  DPoPResponseParams,
8
+ ExperimentalSubjectIssuance,
7
9
  getCredentialRequestForVersion,
8
10
  getUniformFormat,
9
11
  isDeferredCredentialResponse,
@@ -16,7 +18,6 @@ import {
16
18
  UniformCredentialRequest,
17
19
  URL_NOT_VALID,
18
20
  } from '@sphereon/oid4vci-common';
19
- import { ExperimentalSubjectIssuance } from '@sphereon/oid4vci-common/dist/experimental/holder-vci';
20
21
  import { CredentialFormat } from '@sphereon/ssi-types';
21
22
  import Debug from 'debug';
22
23
 
@@ -40,10 +41,20 @@ export interface CredentialRequestOpts {
40
41
  token: string;
41
42
  version: OpenId4VCIVersion;
42
43
  subjectIssuance?: ExperimentalSubjectIssuance;
44
+ issuerState?: string;
43
45
  }
44
46
 
45
- export async function buildProof<DIDDoc>(
46
- proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession,
47
+ export type CreateCredentialRequestOpts = {
48
+ credentialIdentifier?: string;
49
+ credentialTypes?: string | string[];
50
+ context?: string[];
51
+ format?: CredentialFormat | OID4VCICredentialFormat;
52
+ subjectIssuance?: ExperimentalSubjectIssuance;
53
+ version: OpenId4VCIVersion;
54
+ };
55
+
56
+ export async function buildProof(
57
+ proofInput: ProofOfPossessionBuilder | ProofOfPossession,
47
58
  opts: {
48
59
  version: OpenId4VCIVersion;
49
60
  cNonce?: string;
@@ -85,8 +96,35 @@ export class CredentialRequestClient {
85
96
  this._credentialRequestOpts = { ...builder };
86
97
  }
87
98
 
88
- public async acquireCredentialsUsingProof<DIDDoc>(opts: {
89
- proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
99
+ /**
100
+ * Typically you should not use this method, as it omits a proof from the request.
101
+ * There are certain issuers that in specific circumstances can do without this proof, because they have other means of user binding
102
+ * like using DPoP together with an authorization code flow. These are however rare, so you should be using the acquireCredentialsUsingProof normally
103
+ * @param opts
104
+ */
105
+ public async acquireCredentialsWithoutProof(opts: {
106
+ credentialIdentifier?: string;
107
+ credentialTypes?: string | string[];
108
+ context?: string[];
109
+ format?: CredentialFormat | OID4VCICredentialFormat;
110
+ subjectIssuance?: ExperimentalSubjectIssuance;
111
+ createDPoPOpts?: CreateDPoPClientOpts;
112
+ }): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
113
+ const { credentialIdentifier, credentialTypes, format, context, subjectIssuance } = opts;
114
+
115
+ const request = await this.createCredentialRequestWithoutProof({
116
+ credentialTypes,
117
+ context,
118
+ format,
119
+ version: this.version(),
120
+ credentialIdentifier,
121
+ subjectIssuance,
122
+ });
123
+ return await this.acquireCredentialsUsingRequestWithoutProof(request, opts.createDPoPOpts);
124
+ }
125
+
126
+ public async acquireCredentialsUsingProof(opts: {
127
+ proofInput: ProofOfPossessionBuilder | ProofOfPossession;
90
128
  credentialIdentifier?: string;
91
129
  credentialTypes?: string | string[];
92
130
  context?: string[];
@@ -108,9 +146,23 @@ export class CredentialRequestClient {
108
146
  return await this.acquireCredentialsUsingRequest(request, opts.createDPoPOpts);
109
147
  }
110
148
 
149
+ public async acquireCredentialsUsingRequestWithoutProof(
150
+ uniformRequest: UniformCredentialRequest,
151
+ createDPoPOpts?: CreateDPoPClientOpts,
152
+ ): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
153
+ return await this.acquireCredentialsUsingRequestImpl(uniformRequest, createDPoPOpts);
154
+ }
155
+
111
156
  public async acquireCredentialsUsingRequest(
112
157
  uniformRequest: UniformCredentialRequest,
113
158
  createDPoPOpts?: CreateDPoPClientOpts,
159
+ ): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
160
+ return await this.acquireCredentialsUsingRequestImpl(uniformRequest, createDPoPOpts);
161
+ }
162
+
163
+ private async acquireCredentialsUsingRequestImpl(
164
+ uniformRequest: UniformCredentialRequest & { proof?: ProofOfPossession },
165
+ createDPoPOpts?: CreateDPoPClientOpts,
114
166
  ): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
115
167
  if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
116
168
  throw new Error('Versions below v1.0.13 (draft 13) are not supported by the V13 credential request client.');
@@ -194,24 +246,35 @@ export class CredentialRequestClient {
194
246
  });
195
247
  }
196
248
 
197
- public async createCredentialRequest<DIDDoc>(opts: {
198
- proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
199
- credentialIdentifier?: string;
200
- credentialTypes?: string | string[];
201
- context?: string[];
202
- format?: CredentialFormat | OID4VCICredentialFormat;
203
- subjectIssuance?: ExperimentalSubjectIssuance;
204
- version: OpenId4VCIVersion;
205
- }): Promise<CredentialRequestV1_0_13> {
249
+ public async createCredentialRequestWithoutProof(opts: CreateCredentialRequestOpts): Promise<CredentialRequestWithoutProofV1_0_13> {
250
+ return await this.createCredentialRequestImpl(opts);
251
+ }
252
+
253
+ public async createCredentialRequest(
254
+ opts: CreateCredentialRequestOpts & {
255
+ proofInput: ProofOfPossessionBuilder | ProofOfPossession;
256
+ },
257
+ ): Promise<CredentialRequestV1_0_13> {
258
+ return await this.createCredentialRequestImpl(opts);
259
+ }
260
+
261
+ private async createCredentialRequestImpl(
262
+ opts: CreateCredentialRequestOpts & {
263
+ proofInput?: ProofOfPossessionBuilder | ProofOfPossession;
264
+ },
265
+ ): Promise<CredentialRequestV1_0_13> {
206
266
  const { proofInput, credentialIdentifier: credential_identifier } = opts;
207
- const proof = await buildProof(proofInput, opts);
267
+ let proof: ProofOfPossession | undefined = undefined;
268
+ if (proofInput) {
269
+ proof = await buildProof(proofInput, opts);
270
+ }
208
271
  if (credential_identifier) {
209
272
  if (opts.format || opts.credentialTypes || opts.context) {
210
273
  throw Error(`You cannot mix credential_identifier with format, credential types and/or context`);
211
274
  }
212
275
  return {
213
276
  credential_identifier,
214
- proof,
277
+ ...(proof && { proof }),
215
278
  };
216
279
  }
217
280
  const formatSelection = opts.format ?? this.credentialRequestOpts.format;
@@ -231,6 +294,7 @@ export class CredentialRequestClient {
231
294
  if (types.length === 0) {
232
295
  throw Error(`Credential type(s) need to be provided`);
233
296
  }
297
+ const issuer_state = this.credentialRequestOpts.issuerState;
234
298
 
235
299
  // TODO: we should move format specific logic
236
300
  if (format === 'jwt_vc_json' || format === 'jwt_vc') {
@@ -239,7 +303,8 @@ export class CredentialRequestClient {
239
303
  type: types,
240
304
  },
241
305
  format,
242
- proof,
306
+ ...(issuer_state && { issuer_state }),
307
+ ...(proof && { proof }),
243
308
  ...opts.subjectIssuance,
244
309
  };
245
310
  } else if (format === 'jwt_vc_json-ld' || format === 'ldp_vc') {
@@ -249,7 +314,8 @@ export class CredentialRequestClient {
249
314
 
250
315
  return {
251
316
  format,
252
- proof,
317
+ ...(issuer_state && { issuer_state }),
318
+ ...(proof && { proof }),
253
319
  ...opts.subjectIssuance,
254
320
 
255
321
  credential_definition: {
@@ -261,16 +327,27 @@ export class CredentialRequestClient {
261
327
  if (types.length > 1) {
262
328
  throw Error(`Only a single credential type is supported for ${format}`);
263
329
  }
264
- // fixme: this isn't up to the CredentialRequest that we see in the version v1_0_13
265
330
  return {
266
331
  format,
267
- proof,
332
+ ...(issuer_state && { issuer_state }),
333
+ ...(proof && { proof }),
268
334
  vct: types[0],
269
335
  ...opts.subjectIssuance,
270
336
  };
337
+ } else if (format === 'mso_mdoc') {
338
+ if (types.length > 1) {
339
+ throw Error(`Only a single credential type is supported for ${format}`);
340
+ }
341
+ return {
342
+ format,
343
+ ...(issuer_state && { issuer_state }),
344
+ ...(proof && { proof }),
345
+ doctype: types[0],
346
+ ...opts.subjectIssuance,
347
+ };
271
348
  }
272
349
 
273
- throw new Error(`Unsupported format: ${format}`);
350
+ throw new Error(`Unsupported credential format: ${format}`);
274
351
  }
275
352
 
276
353
  private version(): OpenId4VCIVersion {
@@ -168,6 +168,10 @@ export class CredentialRequestClientBuilder {
168
168
  return this;
169
169
  }
170
170
 
171
+ public withIssuerState(issuerState?: string): this {
172
+ this._builder.withIssuerState(issuerState);
173
+ return this;
174
+ }
171
175
  public withCredentialType(credentialTypes: string | string[]): this {
172
176
  this._builder.withCredentialType(credentialTypes);
173
177
  return this;
@@ -28,6 +28,7 @@ export class CredentialRequestClientBuilderV1_0_11 {
28
28
  token?: string;
29
29
  version?: OpenId4VCIVersion;
30
30
  subjectIssuance?: ExperimentalSubjectIssuance;
31
+ issuerState?: string;
31
32
 
32
33
  public static fromCredentialIssuer({
33
34
  credentialIssuer,
@@ -98,6 +99,11 @@ export class CredentialRequestClientBuilderV1_0_11 {
98
99
  });
99
100
  }
100
101
 
102
+ public withIssuerState(issuerState?: string): this {
103
+ this.issuerState = issuerState;
104
+ return this;
105
+ }
106
+
101
107
  public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
102
108
  this.credentialEndpoint = metadata.credential_endpoint;
103
109
  return this;
@@ -27,6 +27,7 @@ export class CredentialRequestClientBuilderV1_0_13 {
27
27
  token?: string;
28
28
  version?: OpenId4VCIVersion;
29
29
  subjectIssuance?: ExperimentalSubjectIssuance;
30
+ issuerState?: string;
30
31
 
31
32
  public static fromCredentialIssuer({
32
33
  credentialIssuer,
@@ -86,6 +87,7 @@ export class CredentialRequestClientBuilderV1_0_13 {
86
87
  if (ids.length && ids.length === 1) {
87
88
  builder.withCredentialIdentifier(ids[0]);
88
89
  }
90
+
89
91
  return builder;
90
92
  }
91
93
 
@@ -96,11 +98,13 @@ export class CredentialRequestClientBuilderV1_0_13 {
96
98
  credentialOffer: CredentialOfferRequestWithBaseUrl;
97
99
  metadata?: EndpointMetadata;
98
100
  }): CredentialRequestClientBuilderV1_0_13 {
99
- return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
101
+ const builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
100
102
  request: credentialOffer,
101
103
  metadata,
102
104
  version: credentialOffer.version,
103
105
  });
106
+
107
+ return builder;
104
108
  }
105
109
 
106
110
  public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
@@ -113,6 +117,11 @@ export class CredentialRequestClientBuilderV1_0_13 {
113
117
  return this;
114
118
  }
115
119
 
120
+ public withIssuerState(issuerState?: string): this {
121
+ this.issuerState = issuerState;
122
+ return this;
123
+ }
124
+
116
125
  public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
117
126
  this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
118
127
  return this;
@@ -62,8 +62,8 @@ export class CredentialRequestClientV1_0_11 {
62
62
  this._credentialRequestOpts = { ...builder };
63
63
  }
64
64
 
65
- public async acquireCredentialsUsingProof<DIDDoc>(opts: {
66
- proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
65
+ public async acquireCredentialsUsingProof(opts: {
66
+ proofInput: ProofOfPossessionBuilder | ProofOfPossession;
67
67
  credentialTypes?: string | string[];
68
68
  context?: string[];
69
69
  format?: CredentialFormat | OID4VCICredentialFormat;
@@ -153,8 +153,8 @@ export class CredentialRequestClientV1_0_11 {
153
153
  });
154
154
  }
155
155
 
156
- public async createCredentialRequest<DIDDoc>(opts: {
157
- proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
156
+ public async createCredentialRequest(opts: {
157
+ proofInput: ProofOfPossessionBuilder | ProofOfPossession;
158
158
  credentialTypes?: string | string[];
159
159
  context?: string[];
160
160
  format?: CredentialFormat | OID4VCICredentialFormat;
@@ -215,6 +215,16 @@ export class CredentialRequestClientV1_0_11 {
215
215
  proof,
216
216
  vct: types[0],
217
217
  };
218
+ } else if (format === 'mso_mdoc') {
219
+ if (types.length > 1) {
220
+ throw Error(`Only a single credential type is supported for ${format}`);
221
+ }
222
+
223
+ return {
224
+ format,
225
+ proof,
226
+ doctype: types[0],
227
+ };
218
228
  }
219
229
 
220
230
  throw new Error(`Unsupported format: ${format}`);
@@ -19,7 +19,7 @@ import Debug from 'debug';
19
19
 
20
20
  import { MetadataClientV1_0_11 } from './MetadataClientV1_0_11';
21
21
  import { MetadataClientV1_0_13 } from './MetadataClientV1_0_13';
22
- import { retrieveWellknown } from './functions/OpenIDUtils';
22
+ import { retrieveWellknown } from './functions';
23
23
 
24
24
  const debug = Debug('sphereon:oid4vci:metadata');
25
25
 
@@ -70,6 +70,7 @@ export class MetadataClient {
70
70
  let credential_endpoint: string | undefined;
71
71
  let deferred_credential_endpoint: string | undefined;
72
72
  let authorization_endpoint: string | undefined;
73
+ let authorization_challenge_endpoint: string | undefined;
73
74
  let authorizationServerType: AuthorizationServerType = 'OID4VCI';
74
75
  let authorization_servers: string[] | undefined = [issuer];
75
76
  let authorization_server: string | undefined = undefined;
@@ -84,6 +85,7 @@ export class MetadataClient {
84
85
  if (credentialIssuerMetadata.token_endpoint) {
85
86
  token_endpoint = credentialIssuerMetadata.token_endpoint;
86
87
  }
88
+ authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
87
89
  if (credentialIssuerMetadata.authorization_servers) {
88
90
  authorization_servers = credentialIssuerMetadata.authorization_servers as string[];
89
91
  } else if (credentialIssuerMetadata.authorization_server) {
@@ -130,8 +132,14 @@ export class MetadataClient {
130
132
  );
131
133
  }
132
134
  authorization_endpoint = authMetadata.authorization_endpoint;
135
+ if (authorization_challenge_endpoint && authMetadata.authorization_challenge_endpoint !== authorization_challenge_endpoint) {
136
+ throw Error(
137
+ `Credential issuer has a different authorization_challenge_endpoint (${authorization_challenge_endpoint}) from the Authorization Server (${authMetadata.authorization_challenge_endpoint})`,
138
+ );
139
+ }
140
+ authorization_challenge_endpoint = authMetadata.authorization_challenge_endpoint;
133
141
  if (!authMetadata.token_endpoint) {
134
- throw Error(`Authorization Sever ${authorization_servers} did not provide a token_endpoint`);
142
+ throw Error(`Authorization Server ${authorization_servers} did not provide a token_endpoint`);
135
143
  } else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
136
144
  throw Error(
137
145
  `Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`,
@@ -185,6 +193,7 @@ export class MetadataClient {
185
193
  : (authMetadata as CredentialIssuerMetadataV1_0_13);
186
194
  }
187
195
  debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
196
+
188
197
  return {
189
198
  issuer,
190
199
  token_endpoint,
@@ -192,6 +201,7 @@ export class MetadataClient {
192
201
  deferred_credential_endpoint,
193
202
  ...(authorization_server ? { authorization_server } : { authorization_servers: authorization_servers }),
194
203
  authorization_endpoint,
204
+ authorization_challenge_endpoint,
195
205
  authorizationServerType,
196
206
  credentialIssuerMetadata: authorization_server
197
207
  ? (credentialIssuerMetadata as IssuerMetadataV1_0_08 & Partial<AuthorizationServerMetadata>)
@@ -204,6 +214,7 @@ export class MetadataClient {
204
214
  * Retrieve only the OID4VCI metadata for the issuer. So no OIDC/OAuth2 metadata
205
215
  *
206
216
  * @param issuerHost The issuer hostname
217
+ * @param opts
207
218
  */
208
219
  public static async retrieveOpenID4VCIServerMetadata(
209
220
  issuerHost: string,
@@ -50,6 +50,7 @@ export class MetadataClientV1_0_11 {
50
50
  let credential_endpoint: string | undefined;
51
51
  let deferred_credential_endpoint: string | undefined;
52
52
  let authorization_endpoint: string | undefined;
53
+ let authorization_challenge_endpoint: string | undefined;
53
54
  let authorizationServerType: AuthorizationServerType = 'OID4VCI';
54
55
  let authorization_server: string = issuer;
55
56
  const oid4vciResponse = await MetadataClientV1_0_11.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations
@@ -61,6 +62,7 @@ export class MetadataClientV1_0_11 {
61
62
  if (credentialIssuerMetadata.token_endpoint) {
62
63
  token_endpoint = credentialIssuerMetadata.token_endpoint;
63
64
  }
65
+ authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
64
66
  if (credentialIssuerMetadata.authorization_server) {
65
67
  authorization_server = credentialIssuerMetadata.authorization_server;
66
68
  }
@@ -105,8 +107,14 @@ export class MetadataClientV1_0_11 {
105
107
  );
106
108
  }
107
109
  authorization_endpoint = authMetadata.authorization_endpoint;
110
+ if (authorization_challenge_endpoint && authMetadata.authorization_challenge_endpoint !== authorization_challenge_endpoint) {
111
+ throw Error(
112
+ `Credential issuer has a different authorization_challenge_endpoint (${authorization_challenge_endpoint}) from the Authorization Server (${authMetadata.authorization_challenge_endpoint})`,
113
+ );
114
+ }
115
+ authorization_challenge_endpoint = authMetadata.authorization_challenge_endpoint;
108
116
  if (!authMetadata.token_endpoint) {
109
- throw Error(`Authorization Sever ${authorization_server} did not provide a token_endpoint`);
117
+ throw Error(`Authorization Server ${authorization_server} did not provide a token_endpoint`);
110
118
  } else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
111
119
  throw Error(
112
120
  `Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`,
@@ -165,6 +173,7 @@ export class MetadataClientV1_0_11 {
165
173
  deferred_credential_endpoint,
166
174
  authorization_server,
167
175
  authorization_endpoint,
176
+ authorization_challenge_endpoint,
168
177
  authorizationServerType,
169
178
  credentialIssuerMetadata: credentialIssuerMetadata as unknown as Partial<AuthorizationServerMetadata> & IssuerMetadataV1_0_08,
170
179
  authorizationServerMetadata: authMetadata,
@@ -12,7 +12,7 @@ import {
12
12
  } from '@sphereon/oid4vci-common';
13
13
  import Debug from 'debug';
14
14
 
15
- import { retrieveWellknown } from './functions/OpenIDUtils';
15
+ import { retrieveWellknown } from './functions';
16
16
 
17
17
  const debug = Debug('sphereon:oid4vci:metadata');
18
18
 
@@ -50,6 +50,7 @@ export class MetadataClientV1_0_13 {
50
50
  let credential_endpoint: string | undefined;
51
51
  let deferred_credential_endpoint: string | undefined;
52
52
  let authorization_endpoint: string | undefined;
53
+ let authorization_challenge_endpoint: string | undefined;
53
54
  let authorizationServerType: AuthorizationServerType = 'OID4VCI';
54
55
  let authorization_servers: string[] = [issuer];
55
56
  const oid4vciResponse = await MetadataClientV1_0_13.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations
@@ -61,6 +62,7 @@ export class MetadataClientV1_0_13 {
61
62
  if (credentialIssuerMetadata.token_endpoint) {
62
63
  token_endpoint = credentialIssuerMetadata.token_endpoint;
63
64
  }
65
+ authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
64
66
  if (credentialIssuerMetadata.authorization_servers) {
65
67
  authorization_servers = credentialIssuerMetadata.authorization_servers;
66
68
  }
@@ -104,8 +106,14 @@ export class MetadataClientV1_0_13 {
104
106
  );
105
107
  }
106
108
  authorization_endpoint = authMetadata.authorization_endpoint;
109
+ if (authorization_challenge_endpoint && authMetadata.authorization_challenge_endpoint !== authorization_challenge_endpoint) {
110
+ throw Error(
111
+ `Credential issuer has a different authorization_challenge_endpoint (${authorization_challenge_endpoint}) from the Authorization Server (${authMetadata.authorization_challenge_endpoint})`,
112
+ );
113
+ }
114
+ authorization_challenge_endpoint = authMetadata.authorization_challenge_endpoint;
107
115
  if (!authMetadata.token_endpoint) {
108
- throw Error(`Authorization Sever ${authorization_servers} did not provide a token_endpoint`);
116
+ throw Error(`Authorization Server ${authorization_servers} did not provide a token_endpoint`);
109
117
  } else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
110
118
  throw Error(
111
119
  `Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`,
@@ -164,6 +172,7 @@ export class MetadataClientV1_0_13 {
164
172
  deferred_credential_endpoint,
165
173
  authorization_server: authorization_servers[0],
166
174
  authorization_endpoint,
175
+ authorization_challenge_endpoint,
167
176
  authorizationServerType,
168
177
  credentialIssuerMetadata: credentialIssuerMetadata,
169
178
  authorizationServerMetadata: authMetadata,
@@ -174,6 +183,7 @@ export class MetadataClientV1_0_13 {
174
183
  * Retrieve only the OID4VCI metadata for the issuer. So no OIDC/OAuth2 metadata
175
184
  *
176
185
  * @param issuerHost The issuer hostname
186
+ * @param opts
177
187
  */
178
188
  public static async retrieveOpenID4VCIServerMetadata(
179
189
  issuerHost: string,