@sphereon/oid4vci-client 0.10.4-unstable.2 → 0.10.4-unstable.21

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 (98) hide show
  1. package/dist/AccessTokenClient.d.ts +5 -5
  2. package/dist/AccessTokenClient.d.ts.map +1 -1
  3. package/dist/AccessTokenClient.js +42 -22
  4. package/dist/AccessTokenClient.js.map +1 -1
  5. package/dist/AccessTokenClientV1_0_11.d.ts +29 -0
  6. package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -0
  7. package/dist/AccessTokenClientV1_0_11.js +212 -0
  8. package/dist/AccessTokenClientV1_0_11.js.map +1 -0
  9. package/dist/AuthorizationCodeClient.d.ts +4 -4
  10. package/dist/AuthorizationCodeClient.d.ts.map +1 -1
  11. package/dist/AuthorizationCodeClient.js +14 -3
  12. package/dist/AuthorizationCodeClient.js.map +1 -1
  13. package/dist/AuthorizationCodeClientV1_0_11.d.ts +9 -0
  14. package/dist/AuthorizationCodeClientV1_0_11.d.ts.map +1 -0
  15. package/dist/AuthorizationCodeClientV1_0_11.js +132 -0
  16. package/dist/AuthorizationCodeClientV1_0_11.js.map +1 -0
  17. package/dist/CredentialOfferClient.d.ts.map +1 -1
  18. package/dist/CredentialOfferClient.js +14 -25
  19. package/dist/CredentialOfferClient.js.map +1 -1
  20. package/dist/CredentialOfferClientV1_0_11.d.ts +10 -0
  21. package/dist/CredentialOfferClientV1_0_11.d.ts.map +1 -0
  22. package/dist/CredentialOfferClientV1_0_11.js +103 -0
  23. package/dist/CredentialOfferClientV1_0_11.js.map +1 -0
  24. package/dist/CredentialRequestClient.d.ts +1 -1
  25. package/dist/CredentialRequestClient.d.ts.map +1 -1
  26. package/dist/CredentialRequestClient.js +9 -6
  27. package/dist/CredentialRequestClient.js.map +1 -1
  28. package/dist/CredentialRequestClientBuilder.d.ts +3 -3
  29. package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
  30. package/dist/CredentialRequestClientBuilder.js +2 -2
  31. package/dist/CredentialRequestClientBuilder.js.map +1 -1
  32. package/dist/CredentialRequestClientBuilderV1_0_11.d.ts +46 -0
  33. package/dist/CredentialRequestClientBuilderV1_0_11.d.ts.map +1 -0
  34. package/dist/CredentialRequestClientBuilderV1_0_11.js +117 -0
  35. package/dist/CredentialRequestClientBuilderV1_0_11.js.map +1 -0
  36. package/dist/CredentialRequestClientV1_0_11.d.ts +44 -0
  37. package/dist/CredentialRequestClientV1_0_11.d.ts.map +1 -0
  38. package/dist/CredentialRequestClientV1_0_11.js +151 -0
  39. package/dist/CredentialRequestClientV1_0_11.js.map +1 -0
  40. package/dist/MetadataClient.d.ts +5 -15
  41. package/dist/MetadataClient.d.ts.map +1 -1
  42. package/dist/MetadataClient.js +13 -33
  43. package/dist/MetadataClient.js.map +1 -1
  44. package/dist/MetadataClientV1_0_11.d.ts +31 -0
  45. package/dist/MetadataClientV1_0_11.d.ts.map +1 -0
  46. package/dist/MetadataClientV1_0_11.js +182 -0
  47. package/dist/MetadataClientV1_0_11.js.map +1 -0
  48. package/dist/OpenID4VCIClient.d.ts +5 -17
  49. package/dist/OpenID4VCIClient.d.ts.map +1 -1
  50. package/dist/OpenID4VCIClient.js +3 -74
  51. package/dist/OpenID4VCIClient.js.map +1 -1
  52. package/dist/OpenID4VCIClientV1_0_11.d.ts +107 -0
  53. package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -0
  54. package/dist/OpenID4VCIClientV1_0_11.js +462 -0
  55. package/dist/OpenID4VCIClientV1_0_11.js.map +1 -0
  56. package/dist/functions/OpenIDUtils.d.ts +12 -0
  57. package/dist/functions/OpenIDUtils.d.ts.map +1 -0
  58. package/dist/functions/OpenIDUtils.js +37 -0
  59. package/dist/functions/OpenIDUtils.js.map +1 -0
  60. package/dist/index.d.ts +8 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +8 -1
  63. package/dist/index.js.map +1 -1
  64. package/lib/AccessTokenClient.ts +54 -22
  65. package/lib/AccessTokenClientV1_0_11.ts +255 -0
  66. package/lib/AuthorizationCodeClient.ts +31 -11
  67. package/lib/AuthorizationCodeClientV1_0_11.ts +167 -0
  68. package/lib/CredentialOfferClient.ts +13 -25
  69. package/lib/CredentialOfferClientV1_0_11.ts +112 -0
  70. package/lib/CredentialRequestClient.ts +11 -7
  71. package/lib/CredentialRequestClientBuilder.ts +9 -8
  72. package/lib/CredentialRequestClientBuilderV1_0_11.ts +156 -0
  73. package/lib/CredentialRequestClientV1_0_11.ts +190 -0
  74. package/lib/MetadataClient.ts +26 -48
  75. package/lib/MetadataClientV1_0_11.ts +186 -0
  76. package/lib/OpenID4VCIClient.ts +10 -92
  77. package/lib/OpenID4VCIClientV1_0_11.ts +644 -0
  78. package/lib/__tests__/AccessTokenClient.spec.ts +34 -6
  79. package/lib/__tests__/CredentialRequestClient.spec.ts +56 -39
  80. package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +4 -4
  81. package/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +316 -0
  82. package/lib/__tests__/EBSIE2E.spec.test.ts +2 -2
  83. package/lib/__tests__/IT.spec.ts +222 -11
  84. package/lib/__tests__/IssuanceInitiation.spec.ts +32 -51
  85. package/lib/__tests__/IssuanceInitiationV1_0_11.spec.ts +62 -0
  86. package/lib/__tests__/MattrE2E.spec.test.ts +2 -2
  87. package/lib/__tests__/MetadataClient.spec.ts +70 -6
  88. package/lib/__tests__/MetadataMocks.ts +41 -2
  89. package/lib/__tests__/OpenID4VCIClient.spec.ts +1 -1
  90. package/lib/__tests__/{OpenID4VCIClientPAR.spec.ts → OpenID4VCIClientPARV1_0_11.spec.ts} +5 -5
  91. package/lib/__tests__/OpenID4VCIClientV1_0_11.spec.ts +202 -0
  92. package/lib/__tests__/ProofOfPossessionBuilder.spec.ts +1 -1
  93. package/lib/__tests__/SdJwt.spec.ts +31 -21
  94. package/lib/__tests__/SphereonE2E.spec.test.ts +3 -3
  95. package/lib/__tests__/data/VciDataFixtures.ts +664 -27
  96. package/lib/functions/OpenIDUtils.ts +25 -0
  97. package/lib/index.ts +8 -1
  98. package/package.json +3 -3
@@ -1,17 +1,18 @@
1
1
  import {
2
2
  AuthorizationServerMetadata,
3
3
  AuthorizationServerType,
4
- CredentialIssuerMetadata,
5
- CredentialOfferPayload,
4
+ CredentialIssuerMetadataV1_0_13,
5
+ CredentialOfferPayloadV1_0_13,
6
6
  CredentialOfferRequestWithBaseUrl,
7
- EndpointMetadataResult,
7
+ EndpointMetadataResultV1_0_13,
8
8
  getIssuerFromCredentialOfferPayload,
9
+ IssuerMetadataV1_0_13,
9
10
  OpenIDResponse,
10
- WellKnownEndpoints,
11
- } from '@sphereon/oid4vci-common';
11
+ WellKnownEndpoints
12
+ } from '@sphereon/oid4vci-common'
12
13
  import Debug from 'debug';
13
14
 
14
- import { getJson } from './functions';
15
+ import { retrieveWellknown } from './functions/OpenIDUtils'
15
16
 
16
17
  const debug = Debug('sphereon:oid4vci:metadata');
17
18
 
@@ -21,15 +22,15 @@ export class MetadataClient {
21
22
  *
22
23
  * @param credentialOffer
23
24
  */
24
- public static async retrieveAllMetadataFromCredentialOffer(credentialOffer: CredentialOfferRequestWithBaseUrl): Promise<EndpointMetadataResult> {
25
- return MetadataClient.retrieveAllMetadataFromCredentialOfferRequest(credentialOffer.credential_offer);
25
+ public static async retrieveAllMetadataFromCredentialOffer(credentialOffer: CredentialOfferRequestWithBaseUrl): Promise<EndpointMetadataResultV1_0_13> {
26
+ return MetadataClient.retrieveAllMetadataFromCredentialOfferRequest(credentialOffer.credential_offer as CredentialOfferPayloadV1_0_13);
26
27
  }
27
28
 
28
29
  /**
29
30
  * Retrieve the metada using the initiation request obtained from a previous step
30
31
  * @param request
31
32
  */
32
- public static async retrieveAllMetadataFromCredentialOfferRequest(request: CredentialOfferPayload): Promise<EndpointMetadataResult> {
33
+ public static async retrieveAllMetadataFromCredentialOfferRequest(request: CredentialOfferPayloadV1_0_13): Promise<EndpointMetadataResultV1_0_13> {
33
34
  const issuer = getIssuerFromCredentialOfferPayload(request);
34
35
  if (issuer) {
35
36
  return MetadataClient.retrieveAllMetadata(issuer);
@@ -42,13 +43,13 @@ export class MetadataClient {
42
43
  * @param issuer The issuer URL
43
44
  * @param opts
44
45
  */
45
- public static async retrieveAllMetadata(issuer: string, opts?: { errorOnNotFound: boolean }): Promise<EndpointMetadataResult> {
46
+ public static async retrieveAllMetadata(issuer: string, opts?: { errorOnNotFound: boolean }): Promise<EndpointMetadataResultV1_0_13> {
46
47
  let token_endpoint: string | undefined;
47
48
  let credential_endpoint: string | undefined;
48
49
  let deferred_credential_endpoint: string | undefined;
49
50
  let authorization_endpoint: string | undefined;
50
51
  let authorizationServerType: AuthorizationServerType = 'OID4VCI';
51
- let authorization_server: string = issuer;
52
+ let authorization_servers: string[] = [issuer];
52
53
  const oid4vciResponse = await MetadataClient.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations
53
54
  let credentialIssuerMetadata = oid4vciResponse?.successBody;
54
55
  if (credentialIssuerMetadata) {
@@ -58,16 +59,14 @@ export class MetadataClient {
58
59
  if (credentialIssuerMetadata.token_endpoint) {
59
60
  token_endpoint = credentialIssuerMetadata.token_endpoint;
60
61
  }
61
- if (credentialIssuerMetadata.authorization_server) {
62
- authorization_server = credentialIssuerMetadata.authorization_server;
63
- }
64
- if (credentialIssuerMetadata.authorization_endpoint) {
65
- authorization_endpoint = credentialIssuerMetadata.authorization_endpoint;
62
+ if (credentialIssuerMetadata.authorization_servers) {
63
+ authorization_servers = credentialIssuerMetadata.authorization_servers;
66
64
  }
67
65
  }
68
66
  // No specific OID4VCI endpoint. Either can be an OAuth2 AS or an OIDC IDP. Let's start with OIDC first
69
- let response: OpenIDResponse<AuthorizationServerMetadata> = await MetadataClient.retrieveWellknown(
70
- authorization_server,
67
+ // TODO: for now we're taking just the first one
68
+ let response: OpenIDResponse<AuthorizationServerMetadata> = await retrieveWellknown(
69
+ authorization_servers[0],
71
70
  WellKnownEndpoints.OPENID_CONFIGURATION,
72
71
  {
73
72
  errorOnNotFound: false,
@@ -79,13 +78,14 @@ export class MetadataClient {
79
78
  authorizationServerType = 'OIDC';
80
79
  } else {
81
80
  // Now let's do OAuth2
82
- response = await MetadataClient.retrieveWellknown(authorization_server, WellKnownEndpoints.OAUTH_AS, { errorOnNotFound: false });
81
+ // TODO: for now we're taking just the first one
82
+ response = await retrieveWellknown(authorization_servers[0], WellKnownEndpoints.OAUTH_AS, { errorOnNotFound: false });
83
83
  authMetadata = response.successBody;
84
84
  }
85
85
  if (!authMetadata) {
86
86
  // We will always throw an error, no matter whether the user provided the option not to, because this is bad.
87
- if (issuer !== authorization_server) {
88
- throw Error(`Issuer ${issuer} provided a separate authorization server ${authorization_server}, but that server did not provide metadata`);
87
+ if (!authorization_servers.includes(issuer)) {
88
+ throw Error(`Issuer ${issuer} provided a separate authorization server ${authorization_servers}, but that server did not provide metadata`);
89
89
  }
90
90
  } else {
91
91
  if (!authorizationServerType) {
@@ -103,7 +103,7 @@ export class MetadataClient {
103
103
  }
104
104
  authorization_endpoint = authMetadata.authorization_endpoint;
105
105
  if (!authMetadata.token_endpoint) {
106
- throw Error(`Authorization Sever ${authorization_server} did not provide a token_endpoint`);
106
+ throw Error(`Authorization Sever ${authorization_servers} did not provide a token_endpoint`);
107
107
  } else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
108
108
  throw Error(
109
109
  `Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`,
@@ -152,7 +152,7 @@ export class MetadataClient {
152
152
 
153
153
  if (!credentialIssuerMetadata && authMetadata) {
154
154
  // Apparently everything worked out and the issuer is exposing everything in oAuth2/OIDC well-knowns. Spec is vague about this situation, but we can support it
155
- credentialIssuerMetadata = authMetadata as CredentialIssuerMetadata;
155
+ credentialIssuerMetadata = authMetadata as CredentialIssuerMetadataV1_0_13;
156
156
  }
157
157
  debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
158
158
  return {
@@ -160,7 +160,7 @@ export class MetadataClient {
160
160
  token_endpoint,
161
161
  credential_endpoint,
162
162
  deferred_credential_endpoint,
163
- authorization_server,
163
+ authorization_server: authorization_servers[0],
164
164
  authorization_endpoint,
165
165
  authorizationServerType,
166
166
  credentialIssuerMetadata: credentialIssuerMetadata,
@@ -178,31 +178,9 @@ export class MetadataClient {
178
178
  opts?: {
179
179
  errorOnNotFound?: boolean;
180
180
  },
181
- ): Promise<OpenIDResponse<CredentialIssuerMetadata> | undefined> {
182
- return MetadataClient.retrieveWellknown(issuerHost, WellKnownEndpoints.OPENID4VCI_ISSUER, {
181
+ ): Promise<OpenIDResponse<IssuerMetadataV1_0_13> | undefined> {
182
+ return retrieveWellknown(issuerHost, WellKnownEndpoints.OPENID4VCI_ISSUER, {
183
183
  errorOnNotFound: opts?.errorOnNotFound === undefined ? true : opts.errorOnNotFound,
184
184
  });
185
185
  }
186
-
187
- /**
188
- * Allows to retrieve information from a well-known location
189
- *
190
- * @param host The host
191
- * @param endpointType The endpoint type, currently supports OID4VCI, OIDC and OAuth2 endpoint types
192
- * @param opts Options, like for instance whether an error should be thrown in case the endpoint doesn't exist
193
- */
194
- public static async retrieveWellknown<T>(
195
- host: string,
196
- endpointType: WellKnownEndpoints,
197
- opts?: { errorOnNotFound?: boolean },
198
- ): Promise<OpenIDResponse<T>> {
199
- const result: OpenIDResponse<T> = await getJson(`${host.endsWith('/') ? host.slice(0, -1) : host}${endpointType}`, {
200
- exceptionOnHttpErrorStatus: opts?.errorOnNotFound,
201
- });
202
- if (result.origResponse.status >= 400) {
203
- // We only get here when error on not found is false
204
- debug(`host ${host} with endpoint type ${endpointType} status: ${result.origResponse.status}, ${result.origResponse.statusText}`);
205
- }
206
- return result;
207
- }
208
186
  }
@@ -0,0 +1,186 @@
1
+ import {
2
+ AuthorizationServerMetadata,
3
+ AuthorizationServerType,
4
+ CredentialIssuerMetadataV1_0_11,
5
+ CredentialOfferPayload,
6
+ CredentialOfferRequestWithBaseUrl,
7
+ EndpointMetadataResultV1_0_11,
8
+ getIssuerFromCredentialOfferPayload, IssuerMetadataV1_0_08,
9
+ OpenIDResponse,
10
+ WellKnownEndpoints
11
+ } from '@sphereon/oid4vci-common'
12
+ import Debug from 'debug';
13
+
14
+ import { retrieveWellknown } from './functions/OpenIDUtils'
15
+
16
+ const debug = Debug('sphereon:oid4vci:metadata');
17
+
18
+ export class MetadataClientV1_0_11 {
19
+ /**
20
+ * Retrieve metadata using the Initiation obtained from a previous step
21
+ *
22
+ * @param credentialOffer
23
+ */
24
+ public static async retrieveAllMetadataFromCredentialOffer(credentialOffer: CredentialOfferRequestWithBaseUrl): Promise<EndpointMetadataResultV1_0_11> {
25
+ return MetadataClientV1_0_11.retrieveAllMetadataFromCredentialOfferRequest(credentialOffer.credential_offer);
26
+ }
27
+
28
+ /**
29
+ * Retrieve the metada using the initiation request obtained from a previous step
30
+ * @param request
31
+ */
32
+ public static async retrieveAllMetadataFromCredentialOfferRequest(request: CredentialOfferPayload): Promise<EndpointMetadataResultV1_0_11> {
33
+ const issuer = getIssuerFromCredentialOfferPayload(request);
34
+ if (issuer) {
35
+ return MetadataClientV1_0_11.retrieveAllMetadata(issuer);
36
+ }
37
+ throw new Error("can't retrieve metadata from CredentialOfferRequest. No issuer field is present");
38
+ }
39
+
40
+ /**
41
+ * Retrieve all metadata from an issuer
42
+ * @param issuer The issuer URL
43
+ * @param opts
44
+ */
45
+ public static async retrieveAllMetadata(issuer: string, opts?: { errorOnNotFound: boolean }): Promise<EndpointMetadataResultV1_0_11> {
46
+ let token_endpoint: string | undefined;
47
+ let credential_endpoint: string | undefined;
48
+ let deferred_credential_endpoint: string | undefined;
49
+ let authorization_endpoint: string | undefined;
50
+ let authorizationServerType: AuthorizationServerType = 'OID4VCI';
51
+ let authorization_server: string = issuer;
52
+ const oid4vciResponse = await MetadataClientV1_0_11.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations
53
+ let credentialIssuerMetadata = oid4vciResponse?.successBody;
54
+ if (credentialIssuerMetadata) {
55
+ debug(`Issuer ${issuer} OID4VCI well-known server metadata\r\n${JSON.stringify(credentialIssuerMetadata)}`);
56
+ credential_endpoint = credentialIssuerMetadata.credential_endpoint;
57
+ deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint;
58
+ if (credentialIssuerMetadata.token_endpoint) {
59
+ token_endpoint = credentialIssuerMetadata.token_endpoint;
60
+ }
61
+ if (credentialIssuerMetadata.authorization_server) {
62
+ authorization_server = credentialIssuerMetadata.authorization_server;
63
+ }
64
+ if (credentialIssuerMetadata.authorization_endpoint) {
65
+ authorization_endpoint = credentialIssuerMetadata.authorization_endpoint;
66
+ }
67
+ }
68
+ // No specific OID4VCI endpoint. Either can be an OAuth2 AS or an OIDC IDP. Let's start with OIDC first
69
+ let response: OpenIDResponse<AuthorizationServerMetadata> = await retrieveWellknown(
70
+ authorization_server,
71
+ WellKnownEndpoints.OPENID_CONFIGURATION,
72
+ {
73
+ errorOnNotFound: false,
74
+ },
75
+ );
76
+ let authMetadata = response.successBody;
77
+ if (authMetadata) {
78
+ debug(`Issuer ${issuer} has OpenID Connect Server metadata in well-known location`);
79
+ authorizationServerType = 'OIDC';
80
+ } else {
81
+ // Now let's do OAuth2
82
+ response = await retrieveWellknown(authorization_server, WellKnownEndpoints.OAUTH_AS, { errorOnNotFound: false });
83
+ authMetadata = response.successBody;
84
+ }
85
+ if (!authMetadata) {
86
+ // We will always throw an error, no matter whether the user provided the option not to, because this is bad.
87
+ if (issuer !== authorization_server) {
88
+ throw Error(`Issuer ${issuer} provided a separate authorization server ${authorization_server}, but that server did not provide metadata`);
89
+ }
90
+ } else {
91
+ if (!authorizationServerType) {
92
+ authorizationServerType = 'OAuth 2.0';
93
+ }
94
+ debug(`Issuer ${issuer} has ${authorizationServerType} Server metadata in well-known location`);
95
+ if (!authMetadata.authorization_endpoint) {
96
+ console.warn(
97
+ `Issuer ${issuer} of type ${authorizationServerType} has no authorization_endpoint! Will use ${authorization_endpoint}. This only works for pre-authorized flows`,
98
+ );
99
+ } else if (authorization_endpoint && authMetadata.authorization_endpoint !== authorization_endpoint) {
100
+ throw Error(
101
+ `Credential issuer has a different authorization_endpoint (${authorization_endpoint}) from the Authorization Server (${authMetadata.authorization_endpoint})`,
102
+ );
103
+ }
104
+ authorization_endpoint = authMetadata.authorization_endpoint;
105
+ if (!authMetadata.token_endpoint) {
106
+ throw Error(`Authorization Sever ${authorization_server} did not provide a token_endpoint`);
107
+ } else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
108
+ throw Error(
109
+ `Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`,
110
+ );
111
+ }
112
+ token_endpoint = authMetadata.token_endpoint;
113
+ if (authMetadata.credential_endpoint) {
114
+ if (credential_endpoint && authMetadata.credential_endpoint !== credential_endpoint) {
115
+ debug(
116
+ `Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.credential_endpoint}). Will use the issuer value`,
117
+ );
118
+ } else {
119
+ credential_endpoint = authMetadata.credential_endpoint;
120
+ }
121
+ }
122
+ if (authMetadata.deferred_credential_endpoint) {
123
+ if (deferred_credential_endpoint && authMetadata.deferred_credential_endpoint !== deferred_credential_endpoint) {
124
+ debug(
125
+ `Credential issuer has a different deferred_credential_endpoint (${deferred_credential_endpoint}) from the Authorization Server (${authMetadata.deferred_credential_endpoint}). Will use the issuer value`,
126
+ );
127
+ } else {
128
+ deferred_credential_endpoint = authMetadata.deferred_credential_endpoint;
129
+ }
130
+ }
131
+ }
132
+
133
+ if (!authorization_endpoint) {
134
+ debug(`Issuer ${issuer} does not expose authorization_endpoint, so only pre-auth will be supported`);
135
+ }
136
+ if (!token_endpoint) {
137
+ debug(`Issuer ${issuer} does not have a token_endpoint listed in well-known locations!`);
138
+ if (opts?.errorOnNotFound) {
139
+ throw Error(`Could not deduce the token_endpoint for ${issuer}`);
140
+ } else {
141
+ token_endpoint = `${issuer}${issuer.endsWith('/') ? 'token' : '/token'}`;
142
+ }
143
+ }
144
+ if (!credential_endpoint) {
145
+ debug(`Issuer ${issuer} does not have a credential_endpoint listed in well-known locations!`);
146
+ if (opts?.errorOnNotFound) {
147
+ throw Error(`Could not deduce the credential endpoint for ${issuer}`);
148
+ } else {
149
+ credential_endpoint = `${issuer}${issuer.endsWith('/') ? 'credential' : '/credential'}`;
150
+ }
151
+ }
152
+
153
+ if (!credentialIssuerMetadata && authMetadata) {
154
+ // Apparently everything worked out and the issuer is exposing everything in oAuth2/OIDC well-knowns. Spec is vague about this situation, but we can support it
155
+ credentialIssuerMetadata = authMetadata as CredentialIssuerMetadataV1_0_11;
156
+ }
157
+ debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
158
+ return {
159
+ issuer,
160
+ token_endpoint,
161
+ credential_endpoint,
162
+ deferred_credential_endpoint,
163
+ authorization_server,
164
+ authorization_endpoint,
165
+ authorizationServerType,
166
+ credentialIssuerMetadata: credentialIssuerMetadata as unknown as (Partial<AuthorizationServerMetadata> & IssuerMetadataV1_0_08),
167
+ authorizationServerMetadata: authMetadata,
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Retrieve only the OID4VCI metadata for the issuer. So no OIDC/OAuth2 metadata
173
+ *
174
+ * @param issuerHost The issuer hostname
175
+ */
176
+ public static async retrieveOpenID4VCIServerMetadata(
177
+ issuerHost: string,
178
+ opts?: {
179
+ errorOnNotFound?: boolean;
180
+ },
181
+ ): Promise<OpenIDResponse<CredentialIssuerMetadataV1_0_11> | undefined> {
182
+ return retrieveWellknown(issuerHost, WellKnownEndpoints.OPENID4VCI_ISSUER, {
183
+ errorOnNotFound: opts?.errorOnNotFound === undefined ? true : opts.errorOnNotFound,
184
+ });
185
+ }
186
+ }
@@ -5,12 +5,11 @@ import {
5
5
  AuthorizationResponse,
6
6
  AuthzFlowType,
7
7
  CodeChallengeMethod,
8
- CredentialOfferPayloadV1_0_08,
9
8
  CredentialOfferRequestWithBaseUrl,
10
9
  CredentialResponse,
11
10
  CredentialSupported,
12
11
  DefaultURISchemes,
13
- EndpointMetadataResult,
12
+ EndpointMetadataResultV1_0_13,
14
13
  getClientIdFromCredentialOfferPayload,
15
14
  getIssuerFromCredentialOfferPayload,
16
15
  getSupportedCredentials,
@@ -20,9 +19,8 @@ import {
20
19
  OID4VCICredentialFormat,
21
20
  OpenId4VCIVersion,
22
21
  PKCEOpts,
23
- ProofOfPossessionCallbacks,
24
- toAuthorizationResponsePayload,
25
- } from '@sphereon/oid4vci-common';
22
+ ProofOfPossessionCallbacks, toAuthorizationResponsePayload
23
+ } from '@sphereon/oid4vci-common'
26
24
  import { CredentialFormat } from '@sphereon/ssi-types';
27
25
  import Debug from 'debug';
28
26
 
@@ -43,7 +41,7 @@ export interface OpenID4VCIClientState {
43
41
  kid?: string;
44
42
  jwk?: JWK;
45
43
  alg?: Alg | string;
46
- endpointMetadata?: EndpointMetadataResult;
44
+ endpointMetadata?: EndpointMetadataResultV1_0_13;
47
45
  accessTokenResponse?: AccessTokenResponse;
48
46
  authorizationRequestOpts?: AuthorizationRequestOpts;
49
47
  authorizationCodeResponse?: AuthorizationResponse;
@@ -77,7 +75,7 @@ export class OpenID4VCIClient {
77
75
  pkce?: PKCEOpts;
78
76
  authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl
79
77
  jwk?: JWK;
80
- endpointMetadata?: EndpointMetadataResult;
78
+ endpointMetadata?: EndpointMetadataResultV1_0_13;
81
79
  accessTokenResponse?: AccessTokenResponse;
82
80
  authorizationRequestOpts?: AuthorizationRequestOpts;
83
81
  authorizationCodeResponse?: AuthorizationResponse;
@@ -223,13 +221,13 @@ export class OpenID4VCIClient {
223
221
  endpointMetadata: this.endpointMetadata,
224
222
  authorizationRequest: this._state.authorizationRequestOpts,
225
223
  credentialOffer: this.credentialOffer,
226
- credentialsSupported: this.getCredentialsSupported(true),
224
+ credentialConfigurationSupported: this.getCredentialsSupported(),
227
225
  });
228
226
  }
229
227
  return this._state.authorizationURL;
230
228
  }
231
229
 
232
- public async retrieveServerMetadata(): Promise<EndpointMetadataResult> {
230
+ public async retrieveServerMetadata(): Promise<EndpointMetadataResultV1_0_13> {
233
231
  this.assertIssuerData();
234
232
  if (!this._state.endpointMetadata) {
235
233
  if (this.credentialOffer) {
@@ -284,7 +282,6 @@ export class OpenID4VCIClient {
284
282
  if (this._state.authorizationRequestOpts?.redirectUri && !redirectUri) {
285
283
  redirectUri = this._state.authorizationRequestOpts.redirectUri;
286
284
  }
287
-
288
285
  const response = await accessTokenClient.acquireAccessToken({
289
286
  credentialOffer: this.credentialOffer,
290
287
  metadata: this.endpointMetadata,
@@ -441,46 +438,17 @@ export class OpenID4VCIClient {
441
438
  return JSON.stringify(this._state);
442
439
  }
443
440
 
444
- // FIXME: We really should convert <v11 to v12 objects first. Right now the logic doesn't map nicely and is brittle.
445
- // We should resolve IDs to objects first in case of strings.
446
- // When < v11 convert into a v12 object. When v12 object retain it.
447
- // Then match the object array on server metadata
448
441
  getCredentialsSupported(
449
- restrictToInitiationTypes: boolean,
450
442
  format?: (OID4VCICredentialFormat | string) | (OID4VCICredentialFormat | string)[],
451
- ): CredentialSupported[] {
443
+ ): Record<string, CredentialSupported> {
452
444
  return getSupportedCredentials({
453
445
  issuerMetadata: this.endpointMetadata.credentialIssuerMetadata,
454
446
  version: this.version(),
455
447
  format: format,
456
- types: restrictToInitiationTypes ? this.getCredentialOfferTypes() : undefined,
448
+ types: undefined,
457
449
  });
458
450
  }
459
451
 
460
- getCredentialOfferTypes(): string[][] {
461
- if (!this.credentialOffer) {
462
- return [];
463
- } else if (this.credentialOffer.version < OpenId4VCIVersion.VER_1_0_11) {
464
- const orig = this.credentialOffer.original_credential_offer as CredentialOfferPayloadV1_0_08;
465
- const types: string[] = typeof orig.credential_type === 'string' ? [orig.credential_type] : orig.credential_type;
466
- const result: string[][] = [];
467
- result[0] = types;
468
- return result;
469
- } else {
470
- return this.credentialOffer.credential_offer.credentials.map((c) => {
471
- if (typeof c === 'string') {
472
- return [c];
473
- } else if ('types' in c) {
474
- return c.types;
475
- } else if ('vct' in c) {
476
- return [c.vct];
477
- } else {
478
- return c.credential_definition.types;
479
- }
480
- });
481
- }
482
- }
483
-
484
452
  issuerSupportedFlowTypes(): AuthzFlowType[] {
485
453
  return (
486
454
  this.credentialOffer?.supportedFlows ??
@@ -488,18 +456,6 @@ export class OpenID4VCIClient {
488
456
  );
489
457
  }
490
458
 
491
- isFlowTypeSupported(flowType: AuthzFlowType): boolean {
492
- return this.issuerSupportedFlowTypes().includes(flowType);
493
- }
494
-
495
- get authorizationURL(): string | undefined {
496
- return this._state.authorizationURL;
497
- }
498
-
499
- public hasAuthorizationURL(): boolean {
500
- return !!this.authorizationURL;
501
- }
502
-
503
459
  get credentialOffer(): CredentialOfferRequestWithBaseUrl | undefined {
504
460
  return this._state.credentialOffer;
505
461
  }
@@ -508,7 +464,7 @@ export class OpenID4VCIClient {
508
464
  return this.credentialOffer?.version ?? OpenId4VCIVersion.VER_1_0_11;
509
465
  }
510
466
 
511
- public get endpointMetadata(): EndpointMetadataResult {
467
+ public get endpointMetadata(): EndpointMetadataResultV1_0_13 {
512
468
  this.assertServerMetadata();
513
469
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
514
470
  return this._state.endpointMetadata!;
@@ -538,10 +494,6 @@ export class OpenID4VCIClient {
538
494
  return this._state.clientId;
539
495
  }
540
496
 
541
- public hasAccessTokenResponse(): boolean {
542
- return !!this._state.accessTokenResponse;
543
- }
544
-
545
497
  get accessTokenResponse(): AccessTokenResponse {
546
498
  this.assertAccessToken();
547
499
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -553,45 +505,11 @@ export class OpenID4VCIClient {
553
505
  return this._state.credentialIssuer;
554
506
  }
555
507
 
556
- public getAccessTokenEndpoint(): string {
557
- this.assertIssuerData();
558
- return this.endpointMetadata
559
- ? this.endpointMetadata.token_endpoint
560
- : AccessTokenClient.determineTokenURL({ issuerOpts: { issuer: this.getIssuer() } });
561
- }
562
-
563
- public getCredentialEndpoint(): string {
564
- this.assertIssuerData();
565
- return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential`;
566
- }
567
-
568
- public hasDeferredCredentialEndpoint(): boolean {
569
- return !!this.getAccessTokenEndpoint();
570
- }
571
-
572
508
  public getDeferredCredentialEndpoint(): string {
573
509
  this.assertIssuerData();
574
510
  return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential`;
575
511
  }
576
512
 
577
- /**
578
- * Too bad we need a method like this, but EBSI is not exposing metadata
579
- */
580
- public isEBSI() {
581
- if (
582
- this.credentialOffer?.credential_offer.credentials.find(
583
- (cred) =>
584
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
585
- // @ts-ignore
586
- typeof cred !== 'string' && 'trust_framework' in cred && 'name' in cred.trust_framework && cred.trust_framework.name.includes('ebsi'),
587
- )
588
- ) {
589
- return true;
590
- }
591
- this.assertIssuerData();
592
- return this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu');
593
- }
594
-
595
513
  private assertIssuerData(): void {
596
514
  if (!this._state.credentialIssuer) {
597
515
  throw Error(`No credential issuer value present`);