@sphereon/oid4vci-common 0.8.2-next.48 → 0.8.2-next.87

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 (72) hide show
  1. package/dist/functions/AuthorizationResponseUtil.d.ts +3 -0
  2. package/dist/functions/AuthorizationResponseUtil.d.ts.map +1 -0
  3. package/dist/functions/AuthorizationResponseUtil.js +21 -0
  4. package/dist/functions/AuthorizationResponseUtil.js.map +1 -0
  5. package/dist/functions/CredentialOfferUtil.d.ts +2 -0
  6. package/dist/functions/CredentialOfferUtil.d.ts.map +1 -1
  7. package/dist/functions/CredentialOfferUtil.js +64 -2
  8. package/dist/functions/CredentialOfferUtil.js.map +1 -1
  9. package/dist/functions/CredentialRequestUtil.d.ts +2 -2
  10. package/dist/functions/CredentialRequestUtil.d.ts.map +1 -1
  11. package/dist/functions/CredentialRequestUtil.js +16 -1
  12. package/dist/functions/CredentialRequestUtil.js.map +1 -1
  13. package/dist/functions/Encoding.js +1 -1
  14. package/dist/functions/Encoding.js.map +1 -1
  15. package/dist/functions/HttpUtils.js +1 -1
  16. package/dist/functions/HttpUtils.js.map +1 -1
  17. package/dist/functions/IssuerMetadataUtils.d.ts +5 -1
  18. package/dist/functions/IssuerMetadataUtils.d.ts.map +1 -1
  19. package/dist/functions/IssuerMetadataUtils.js +16 -1
  20. package/dist/functions/IssuerMetadataUtils.js.map +1 -1
  21. package/dist/functions/RandomUtils.d.ts +10 -0
  22. package/dist/functions/RandomUtils.d.ts.map +1 -0
  23. package/dist/functions/RandomUtils.js +73 -0
  24. package/dist/functions/RandomUtils.js.map +1 -0
  25. package/dist/functions/index.d.ts +5 -0
  26. package/dist/functions/index.d.ts.map +1 -1
  27. package/dist/functions/index.js +6 -0
  28. package/dist/functions/index.js.map +1 -1
  29. package/dist/functions/randomBytes.d.ts +7 -0
  30. package/dist/functions/randomBytes.d.ts.map +1 -0
  31. package/dist/functions/randomBytes.js +56 -0
  32. package/dist/functions/randomBytes.js.map +1 -0
  33. package/dist/types/Authorization.types.d.ts +48 -10
  34. package/dist/types/Authorization.types.d.ts.map +1 -1
  35. package/dist/types/Authorization.types.js +24 -3
  36. package/dist/types/Authorization.types.js.map +1 -1
  37. package/dist/types/CredentialIssuance.types.d.ts +4 -1
  38. package/dist/types/CredentialIssuance.types.d.ts.map +1 -1
  39. package/dist/types/CredentialIssuance.types.js.map +1 -1
  40. package/dist/types/Generic.types.d.ts +17 -0
  41. package/dist/types/Generic.types.d.ts.map +1 -1
  42. package/dist/types/Generic.types.js.map +1 -1
  43. package/dist/types/OpenID4VCIVersions.types.d.ts +1 -0
  44. package/dist/types/OpenID4VCIVersions.types.d.ts.map +1 -1
  45. package/dist/types/OpenID4VCIVersions.types.js +2 -1
  46. package/dist/types/OpenID4VCIVersions.types.js.map +1 -1
  47. package/dist/types/v1_0_11.types.d.ts +14 -2
  48. package/dist/types/v1_0_11.types.d.ts.map +1 -1
  49. package/dist/types/v1_0_11.types.js.map +1 -1
  50. package/dist/types/v1_0_12.types.d.ts +3 -0
  51. package/dist/types/v1_0_12.types.d.ts.map +1 -0
  52. package/dist/types/v1_0_12.types.js +3 -0
  53. package/dist/types/v1_0_12.types.js.map +1 -0
  54. package/lib/__tests__/CredentialOfferUtil.spec.ts +51 -2
  55. package/lib/__tests__/Encoding.spec.ts +15 -0
  56. package/lib/__tests__/randomBytes.spec.ts +15 -0
  57. package/lib/functions/AuthorizationResponseUtil.ts +18 -0
  58. package/lib/functions/CredentialOfferUtil.ts +62 -1
  59. package/lib/functions/CredentialRequestUtil.ts +18 -3
  60. package/lib/functions/Encoding.ts +1 -1
  61. package/lib/functions/HttpUtils.ts +1 -1
  62. package/lib/functions/IssuerMetadataUtils.ts +19 -0
  63. package/lib/functions/RandomUtils.ts +43 -0
  64. package/lib/functions/index.ts +5 -0
  65. package/lib/functions/randomBytes.js +61 -0
  66. package/lib/types/Authorization.types.ts +71 -6
  67. package/lib/types/CredentialIssuance.types.ts +7 -1
  68. package/lib/types/Generic.types.ts +26 -0
  69. package/lib/types/OpenID4VCIVersions.types.ts +2 -1
  70. package/lib/types/v1_0_11.types.ts +19 -2
  71. package/lib/types/v1_0_12.types.ts +4 -0
  72. package/package.json +14 -3
@@ -1,4 +1,5 @@
1
1
  import Debug from 'debug';
2
+ import jwtDecode, { JwtPayload } from 'jwt-decode';
2
3
 
3
4
  import {
4
5
  AssertedUniformCredentialOffer,
@@ -68,8 +69,53 @@ export function getIssuerFromCredentialOfferPayload(request: CredentialOfferPayl
68
69
  return 'issuer' in request ? request.issuer : request['credential_issuer'];
69
70
  }
70
71
 
72
+ export const getClientIdFromCredentialOfferPayload = (credentialOffer?: CredentialOfferPayload): string | undefined => {
73
+ if (!credentialOffer) {
74
+ return;
75
+ }
76
+ if ('client_id' in credentialOffer) {
77
+ return credentialOffer.client_id;
78
+ }
79
+
80
+ const state: string | undefined = getStateFromCredentialOfferPayload(credentialOffer);
81
+ if (state && isJWT(state)) {
82
+ const decoded = jwtDecode<JwtPayload>(state, { header: false });
83
+ if ('client_id' in decoded && typeof decoded.client_id === 'string') {
84
+ return decoded.client_id;
85
+ }
86
+ }
87
+ return;
88
+ };
89
+
90
+ const isJWT = (input?: string) => {
91
+ if (!input) {
92
+ return false;
93
+ }
94
+ const noParts = input?.split('.').length;
95
+ return input?.startsWith('ey') && noParts === 3;
96
+ };
97
+ export const getStateFromCredentialOfferPayload = (credentialOffer: CredentialOfferPayload): string | undefined => {
98
+ if ('grants' in credentialOffer) {
99
+ if (credentialOffer.grants?.authorization_code) {
100
+ return credentialOffer.grants.authorization_code.issuer_state;
101
+ } else if (credentialOffer.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']) {
102
+ return credentialOffer.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.['pre-authorized_code'];
103
+ }
104
+ }
105
+ if ('op_state' in credentialOffer) {
106
+ // older spec versions
107
+ return credentialOffer.op_state;
108
+ } else if ('pre-authorized_code' in credentialOffer) {
109
+ return credentialOffer['pre-authorized_code'];
110
+ }
111
+
112
+ return;
113
+ };
114
+
71
115
  export function determineSpecVersionFromOffer(offer: CredentialOfferPayload | CredentialOffer): OpenId4VCIVersion {
72
- if (isCredentialOfferV1_0_11(offer)) {
116
+ if (isCredentialOfferV1_0_12(offer)) {
117
+ return OpenId4VCIVersion.VER_1_0_12;
118
+ } else if (isCredentialOfferV1_0_11(offer)) {
73
119
  return OpenId4VCIVersion.VER_1_0_11;
74
120
  } else if (isCredentialOfferV1_0_09(offer)) {
75
121
  return OpenId4VCIVersion.VER_1_0_09;
@@ -139,6 +185,21 @@ function isCredentialOfferV1_0_11(offer: CredentialOfferPayload | CredentialOffe
139
185
  return 'credential_offer_uri' in offer;
140
186
  }
141
187
 
188
+ function isCredentialOfferV1_0_12(offer: CredentialOfferPayload | CredentialOffer): boolean {
189
+ if (!offer) {
190
+ return false;
191
+ }
192
+ if ('credential_issuer' in offer && 'credentials' in offer) {
193
+ // payload
194
+ return true;
195
+ }
196
+ if ('credential_offer' in offer && offer['credential_offer']) {
197
+ // offer, so check payload
198
+ return isCredentialOfferV1_0_12(offer['credential_offer']);
199
+ }
200
+ return 'credential_offer_uri' in offer;
201
+ }
202
+
142
203
  export async function toUniformCredentialOfferRequest(
143
204
  offer: CredentialOffer,
144
205
  opts?: {
@@ -1,4 +1,4 @@
1
- import { CredentialRequestV1_0_08, OpenId4VCIVersion, UniformCredentialRequest } from '../types';
1
+ import { CredentialRequestV1_0_08, CredentialRequestV1_0_11, OpenId4VCIVersion, UniformCredentialRequest } from '../types';
2
2
 
3
3
  import { getFormatForVersion } from './FormatUtils';
4
4
 
@@ -7,7 +7,14 @@ export function getTypesFromRequest(credentialRequest: UniformCredentialRequest,
7
7
  if (credentialRequest.format === 'jwt_vc_json' || credentialRequest.format === 'jwt_vc') {
8
8
  types = credentialRequest.types;
9
9
  } else if (credentialRequest.format === 'jwt_vc_json-ld' || credentialRequest.format === 'ldp_vc') {
10
- types = credentialRequest.credential_definition.types;
10
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
11
+ // @ts-ignore
12
+ types =
13
+ 'credential_definition' in credentialRequest && credentialRequest.credential_definition
14
+ ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
15
+ // @ts-ignore
16
+ credentialRequest.credential_definition.types
17
+ : credentialRequest.types;
11
18
  } else if (credentialRequest.format === 'vc+sd-jwt') {
12
19
  types = [credentialRequest.vct];
13
20
  }
@@ -24,7 +31,7 @@ export function getTypesFromRequest(credentialRequest: UniformCredentialRequest,
24
31
  export function getCredentialRequestForVersion(
25
32
  credentialRequest: UniformCredentialRequest,
26
33
  version: OpenId4VCIVersion,
27
- ): UniformCredentialRequest | CredentialRequestV1_0_08 {
34
+ ): UniformCredentialRequest | CredentialRequestV1_0_08 | CredentialRequestV1_0_11 {
28
35
  if (version === OpenId4VCIVersion.VER_1_0_08) {
29
36
  const draft8Format = getFormatForVersion(credentialRequest.format, version);
30
37
  const types = getTypesFromRequest(credentialRequest, { filterVerifiableCredential: true });
@@ -34,6 +41,14 @@ export function getCredentialRequestForVersion(
34
41
  proof: credentialRequest.proof,
35
42
  type: types[0],
36
43
  } satisfies CredentialRequestV1_0_08;
44
+ /* } else if (version === OpenId4VCIVersion.VER_1_0_11) {
45
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
46
+ // @ts-ignore
47
+ const { credential_definition = undefined, ...requestv11 } = credentialRequest;
48
+ return {
49
+ ...requestv11,
50
+ ...credential_definition,
51
+ } as CredentialRequestV1_0_11;*/
37
52
  }
38
53
 
39
54
  return credentialRequest;
@@ -88,7 +88,7 @@ export function convertJsonToURI(
88
88
  * - arrayTypeProperties: properties that can show up more that once
89
89
  */
90
90
  export function convertURIToJsonObject(uri: string, opts?: DecodeURIAsJsonOpts): unknown {
91
- if (!uri || !opts?.requiredProperties?.every((p) => uri.includes(p))) {
91
+ if (!uri || (opts?.requiredProperties && !opts.requiredProperties?.every((p) => uri.includes(p)))) {
92
92
  throw new Error(BAD_PARAMS);
93
93
  }
94
94
  const uriComponents = getURIComponentsAsArray(uri, opts?.arrayTypeProperties);
@@ -87,7 +87,7 @@ const openIdFetch = async <T>(
87
87
 
88
88
  debug(`START fetching url: ${url}`);
89
89
  if (body) {
90
- debug(`Body:\r\n${JSON.stringify(body)}`);
90
+ debug(`Body:\r\n${typeof body == 'string' ? body : JSON.stringify(body)}`);
91
91
  }
92
92
  debug(`Headers:\r\n${JSON.stringify(payload.headers)}`);
93
93
  const origResponse = await fetch(url, payload);
@@ -1,4 +1,5 @@
1
1
  import {
2
+ AuthorizationServerMetadata,
2
3
  CredentialIssuerMetadata,
3
4
  CredentialOfferFormat,
4
5
  CredentialSupported,
@@ -165,3 +166,21 @@ export function getIssuerDisplays(metadata: CredentialIssuerMetadata | IssuerMet
165
166
  ) ?? [];
166
167
  return matchedDisplays.sort((item) => (item.locale ? opts?.prefLocales.indexOf(item.locale) ?? 1 : Number.MAX_VALUE));
167
168
  }
169
+
170
+ /**
171
+ * TODO check again when WAL-617 is done to replace how we get the issuer name.
172
+ */
173
+ export function getIssuerName(
174
+ url: string,
175
+ credentialIssuerMetadata?: Partial<AuthorizationServerMetadata> & (CredentialIssuerMetadata | IssuerMetadataV1_0_08),
176
+ ): string {
177
+ if (credentialIssuerMetadata) {
178
+ const displays: Array<MetadataDisplay> = credentialIssuerMetadata ? getIssuerDisplays(credentialIssuerMetadata) : [];
179
+ for (const display of displays) {
180
+ if (display.name) {
181
+ return display.name;
182
+ }
183
+ }
184
+ }
185
+ return url;
186
+ }
@@ -0,0 +1,43 @@
1
+ import SHA from 'sha.js';
2
+ import * as u8a from 'uint8arrays';
3
+ import { SupportedEncodings } from 'uint8arrays/to-string';
4
+
5
+ import { CodeChallengeMethod } from '../types';
6
+
7
+ import { randomBytes } from './randomBytes';
8
+
9
+ export const CODE_VERIFIER_DEFAULT_LENGTH = 128;
10
+ export const NONCE_LENGTH = 32;
11
+
12
+ export const generateRandomString = (length: number, encoding?: SupportedEncodings): string => {
13
+ return u8a.toString(randomBytes(length), encoding).slice(0, length);
14
+ };
15
+
16
+ export const generateNonce = (length?: number): string => {
17
+ return generateRandomString(length ?? NONCE_LENGTH);
18
+ };
19
+ export const generateCodeVerifier = (length?: number): string => {
20
+ const codeVerifier = generateRandomString(length ?? CODE_VERIFIER_DEFAULT_LENGTH, 'base64url');
21
+ assertValidCodeVerifier(codeVerifier);
22
+ return codeVerifier;
23
+ };
24
+
25
+ export const createCodeChallenge = (codeVerifier: string, codeChallengeMethod?: CodeChallengeMethod): string => {
26
+ if (codeChallengeMethod === CodeChallengeMethod.plain) {
27
+ return codeVerifier;
28
+ } else if (!codeChallengeMethod || codeChallengeMethod === CodeChallengeMethod.S256) {
29
+ return u8a.toString(SHA('sha256').update(codeVerifier).digest(), 'base64url');
30
+ } else {
31
+ // Just a precaution if a new method would be introduced
32
+ throw Error(`code challenge method ${codeChallengeMethod} not implemented`);
33
+ }
34
+ };
35
+
36
+ export const assertValidCodeVerifier = (codeVerifier: string) => {
37
+ const length = codeVerifier.length;
38
+ if (length < 43) {
39
+ throw Error(`code_verifier should have a minimum length of 43; see rfc7636`);
40
+ } else if (length > 128) {
41
+ throw Error(`code_verifier should have a maximum length of 128; see rfc7636`);
42
+ }
43
+ };
@@ -1,3 +1,4 @@
1
+ import { randomBytes } from './randomBytes.js';
1
2
  export * from './CredentialRequestUtil';
2
3
  export * from './CredentialResponseUtil';
3
4
  export * from './CredentialOfferUtil';
@@ -5,3 +6,7 @@ export * from './Encoding';
5
6
  export * from './TypeConversionUtils';
6
7
  export * from './IssuerMetadataUtils';
7
8
  export * from './FormatUtils';
9
+ export * from './HttpUtils';
10
+ export * from './AuthorizationResponseUtil';
11
+ export { randomBytes };
12
+ export * from './RandomUtils';
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ // limit of Crypto.getRandomValues()
4
+ // https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
5
+ const MAX_BYTES = 65536;
6
+
7
+ // Node supports requesting up to this number of bytes
8
+ // https://github.com/nodejs/node/blob/master/lib/internal/crypto/random.js#L48
9
+ const MAX_UINT32 = 4294967295;
10
+
11
+ function oldBrowser() {
12
+ throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11');
13
+ }
14
+
15
+ // eslint-disable-next-line no-undef
16
+ const _global = typeof globalThis !== 'undefined' ? globalThis : global;
17
+
18
+ let crypto = _global.crypto || _global.msCrypto;
19
+ if (!crypto) {
20
+ try {
21
+ // eslint-disable-next-line no-undef
22
+ crypto = require('crypto');
23
+ } catch (err) {
24
+ throw Error('crypto module is not available');
25
+ }
26
+ }
27
+
28
+ if (crypto && crypto.getRandomValues) {
29
+ // eslint-disable-next-line no-undef
30
+ module.exports = randomBytes;
31
+ } else {
32
+ // eslint-disable-next-line no-undef
33
+ module.exports = oldBrowser;
34
+ }
35
+
36
+ function randomBytes(size) {
37
+ // phantomjs needs to throw
38
+ if (size > MAX_UINT32) throw new Error('requested too many random bytes');
39
+
40
+ // eslint-disable-next-line no-undef
41
+ const bytes = Buffer.allocUnsafe(size);
42
+
43
+ if (size > 0) {
44
+ // getRandomValues fails on IE if size == 0
45
+ if (size > MAX_BYTES) {
46
+ // this is the max bytes crypto.getRandomValues
47
+ // can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
48
+ for (let generated = 0; generated < size; generated += MAX_BYTES) {
49
+ // buffer.slice automatically checks if the end is past the end of
50
+ // the buffer so we don't have to here
51
+ crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES));
52
+ }
53
+ } else {
54
+ crypto.getRandomValues(bytes);
55
+ }
56
+ }
57
+ return Uint8Array.from(bytes);
58
+ }
59
+
60
+ // eslint-disable-next-line no-undef
61
+ module.exports = { randomBytes };
@@ -70,7 +70,9 @@ export interface CommonAuthorizationRequest {
70
70
  /**
71
71
  * string type added for conformity with our previous code in the client
72
72
  */
73
- export type AuthorizationDetails = AuthorizationDetailsJwtVcJson | AuthorizationDetailsJwtVcJsonLdAndLdpVc | AuthorizationDetailsSdJwtVc | string;
73
+ export type AuthorizationDetails =
74
+ | (CommonAuthorizationDetails & (AuthorizationDetailsJwtVcJson | AuthorizationDetailsJwtVcJsonLdAndLdpVc | AuthorizationDetailsSdJwtVc))
75
+ | string;
74
76
 
75
77
  export type AuthorizationRequest = AuthorizationRequestJwtVcJson | AuthorizationRequestJwtVcJsonLdAndLdpVc | AuthorizationRequestSdJwtVc;
76
78
 
@@ -86,6 +88,16 @@ export interface AuthorizationRequestSdJwtVc extends CommonAuthorizationRequest
86
88
  authorization_details?: AuthorizationDetailsSdJwtVc[];
87
89
  }
88
90
 
91
+ /*
92
+ export interface AuthDetails {
93
+ type: 'openid_credential' | string;
94
+ locations?: string | string[];
95
+ format: CredentialFormat | CredentialFormat[];
96
+
97
+ [s: string]: unknown;
98
+ }
99
+ */
100
+
89
101
  export interface CommonAuthorizationDetails {
90
102
  /**
91
103
  * REQUIRED. JSON string that determines the authorization details type.
@@ -159,8 +171,8 @@ export enum ResponseType {
159
171
  }
160
172
 
161
173
  export enum CodeChallengeMethod {
162
- TEXT = 'text',
163
- SHA256 = 'S256',
174
+ plain = 'plain',
175
+ S256 = 'S256',
164
176
  }
165
177
 
166
178
  export interface AuthorizationServerOpts {
@@ -176,6 +188,9 @@ export interface IssuerOpts {
176
188
  fetchMetadata?: boolean;
177
189
  }
178
190
 
191
+ export interface AccessTokenFromAuthorizationResponseOpts extends AccessTokenRequestOpts {
192
+ authorizationResponse: AuthorizationResponse;
193
+ }
179
194
  export interface AccessTokenRequestOpts {
180
195
  credentialOffer?: UniformCredentialOffer;
181
196
  credentialIssuer?: string;
@@ -187,22 +202,72 @@ export interface AccessTokenRequestOpts {
187
202
  pin?: string; // Pin-number. Only used when required
188
203
  }
189
204
 
190
- export interface AuthorizationRequestOpts {
205
+ /*export interface AuthorizationRequestOpts {
191
206
  clientId: string;
192
207
  codeChallenge: string;
193
208
  codeChallengeMethod: CodeChallengeMethod;
194
209
  authorizationDetails?: AuthorizationDetails[];
195
210
  redirectUri: string;
196
211
  scope?: string;
212
+ }*/
213
+
214
+ /**
215
+ * Determinse whether PAR should be used when supported
216
+ *
217
+ * REQUIRE: Require PAR, if AS does not support it throw an error
218
+ * AUTO: Use PAR is the AS supports it, otherwise construct a reqular URI,
219
+ * NEVER: Do not use PAR even if the AS supports it (not recommended)
220
+ */
221
+ export enum PARMode {
222
+ REQUIRE,
223
+ AUTO,
224
+ NEVER,
197
225
  }
198
226
 
199
- export interface AuthorizationGrantResponse {
200
- grant_type: string;
227
+ /**
228
+ * Optional options to provide PKCE params like code verifier and challenge yourself, or to disable PKCE altogether. If not provide PKCE will still be used! If individual params are not provide, they will be generated/calculated
229
+ */
230
+ export interface PKCEOpts {
231
+ /**
232
+ * PKCE is enabled by default even if you do not provide these options. Set this to true to disable PKCE
233
+ */
234
+ disabled?: boolean;
235
+
236
+ /**
237
+ * Provide a code_challenge, otherwise it will be calculated using the code_verifier and method
238
+ */
239
+ codeChallenge?: string;
240
+
241
+ /**
242
+ * The code_challenge_method, should always by S256
243
+ */
244
+ codeChallengeMethod?: CodeChallengeMethod;
245
+
246
+ /**
247
+ * Provide a code_verifier, otherwise it will be generated
248
+ */
249
+ codeVerifier?: string;
250
+ }
251
+
252
+ export interface AuthorizationRequestOpts {
253
+ clientId?: string;
254
+ pkce?: PKCEOpts;
255
+ parMode?: PARMode;
256
+ authorizationDetails?: AuthorizationDetails | AuthorizationDetails[];
257
+ redirectUri?: string;
258
+ scope?: string;
259
+ }
260
+
261
+ export interface AuthorizationResponse {
201
262
  code: string;
202
263
  scope?: string;
203
264
  state?: string;
204
265
  }
205
266
 
267
+ export interface AuthorizationGrantResponse extends AuthorizationResponse {
268
+ grant_type: string;
269
+ }
270
+
206
271
  export interface AccessTokenRequest {
207
272
  client_id?: string;
208
273
  code?: string;
@@ -18,6 +18,7 @@ export interface CredentialResponse {
18
18
 
19
19
  export interface CredentialOfferRequestWithBaseUrl extends UniformCredentialOfferRequest {
20
20
  scheme: string;
21
+ clientId?: string;
21
22
  baseUrl: string;
22
23
  userPinRequired: boolean;
23
24
  issuerState?: string;
@@ -26,7 +27,9 @@ export interface CredentialOfferRequestWithBaseUrl extends UniformCredentialOffe
26
27
 
27
28
  export type CredentialOffer = CredentialOfferV1_0_09 | CredentialOfferV1_0_11;
28
29
 
29
- export type CredentialOfferPayload = CredentialOfferPayloadV1_0_08 | CredentialOfferPayloadV1_0_09 | CredentialOfferPayloadV1_0_11;
30
+ export type CredentialOfferPayload = (CredentialOfferPayloadV1_0_08 | CredentialOfferPayloadV1_0_09 | CredentialOfferPayloadV1_0_11) & {
31
+ [x: string]: any;
32
+ };
30
33
 
31
34
  export interface AssertedUniformCredentialOffer extends UniformCredentialOffer {
32
35
  credential_offer: UniformCredentialOfferPayload;
@@ -107,6 +110,7 @@ export interface JWK extends BaseJWK {
107
110
  x5t?: string;
108
111
  'x5t#S256'?: string;
109
112
  x5u?: string;
113
+
110
114
  [propName: string]: unknown;
111
115
  }
112
116
 
@@ -147,6 +151,7 @@ export interface JWSHeaderParameters extends JoseHeaderParameters {
147
151
  alg?: Alg | string; // REQUIRED by the JWT signer
148
152
  b64?: boolean;
149
153
  crit?: string[];
154
+
150
155
  [propName: string]: unknown;
151
156
  }
152
157
 
@@ -172,6 +177,7 @@ export interface JWTPayload {
172
177
 
173
178
  export type JWTSignerCallback = (jwt: Jwt, kid?: string) => Promise<string>;
174
179
  export type JWTVerifyCallback<DIDDoc> = (args: { jwt: string; kid?: string }) => Promise<JwtVerifyResult<DIDDoc>>;
180
+
175
181
  export interface JwtVerifyResult<DIDDoc> {
176
182
  jwt: Jwt;
177
183
  kid?: string;
@@ -51,6 +51,7 @@ export interface CredentialIssuerMetadataOpts {
51
51
  credentials_supported: CredentialSupported[]; // REQUIRED. A JSON array containing a list of JSON objects, each of them representing metadata about a separate credential type that the Credential Issuer can issue. The JSON objects in the array MUST conform to the structure of the Section 10.2.3.1.
52
52
  credential_issuer: string; // REQUIRED. The Credential Issuer's identifier.
53
53
  authorization_server?: string; // OPTIONAL. Identifier of the OAuth 2.0 Authorization Server (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
54
+ // authorization_servers?: string[]; // OPTIONAL. Array of strings that identify the OAuth 2.0 Authorization Servers (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
54
55
  token_endpoint?: string;
55
56
  display?: MetadataDisplay[]; // An array of objects, where each object contains display properties of a Credential Issuer for a certain language. Below is a non-exhaustive list of valid parameters that MAY be included:
56
57
  credential_supplier_config?: CredentialSupplierConfig;
@@ -58,9 +59,16 @@ export interface CredentialIssuerMetadataOpts {
58
59
 
59
60
  // For now we extend the opts above. Only difference is that the credential endpoint is optional in the Opts, as it can come from other sources. The value is however required in the eventual Issuer Metadata
60
61
  export interface CredentialIssuerMetadata extends CredentialIssuerMetadataOpts, Partial<AuthorizationServerMetadata> {
62
+ authorization_servers?: string[]; // OPTIONAL. Array of strings that identify the OAuth 2.0 Authorization Servers (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
61
63
  credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components.
64
+ credential_response_encryption_alg_values_supported?: string; // OPTIONAL. Array containing a list of the JWE [RFC7516] encryption algorithms (alg values) [RFC7518] supported by the Credential and/or Batch Credential Endpoint to encode the Credential or Batch Credential Response in a JWT [RFC7519].
65
+ credential_response_encryption_enc_values_supported?: string; //OPTIONAL. Array containing a list of the JWE [RFC7516] encryption algorithms (enc values) [RFC7518] supported by the Credential and/or Batch Credential Endpoint to encode the Credential or Batch Credential Response in a JWT [RFC7519].
66
+ require_credential_response_encryption?: boolean; //OPTIONAL. Boolean value specifying whether the Credential Issuer requires additional encryption on top of TLS for the Credential Response and expects encryption parameters to be present in the Credential Request and/or Batch Credential Request, with true indicating support. When the value is true, credential_response_encryption_alg_values_supported parameter MUST also be provided. If omitted, the default value is false.
67
+ credential_identifiers_supported?: boolean; // OPTIONAL. Boolean value specifying whether the Credential Issuer supports returning credential_identifiers parameter in the authorization_details Token Response parameter, with true indicating support. If omitted, the default value is false.
62
68
  }
63
69
 
70
+ // For now we extend the opts above. Only difference is that the credential endpoint is optional in the Opts, as it can come from other sources. The value is however required in the eventual Issuer Metadata
71
+
64
72
  export interface CredentialSupportedBrief {
65
73
  cryptographic_binding_methods_supported?: string[]; // OPTIONAL. Array of case sensitive strings that identify how the Credential is bound to the identifier of the End-User who possesses the Credential
66
74
  cryptographic_suites_supported?: string[]; // OPTIONAL. Array of case sensitive strings that identify the cryptographic suites that are supported for the cryptographic_binding_methods_supported
@@ -229,6 +237,12 @@ export interface GrantAuthorizationCode {
229
237
  * Authorization Request with the Credential Issuer to a context set up during previous steps.
230
238
  */
231
239
  issuer_state?: string;
240
+
241
+ // v12 feature
242
+ /**
243
+ * OPTIONAL string that the Wallet can use to identify the Authorization Server to use with this grant type when authorization_servers parameter in the Credential Issuer metadata has multiple entries. MUST NOT be used otherwise. The value of this parameter MUST match with one of the values in the authorization_servers array obtained from the Credential Issuer metadata
244
+ */
245
+ authorization_server?: string;
232
246
  }
233
247
 
234
248
  export interface GrantUrnIetf {
@@ -241,6 +255,18 @@ export interface GrantUrnIetf {
241
255
  * in a Pre-Authorized Code Flow. Default is false.
242
256
  */
243
257
  user_pin_required: boolean;
258
+
259
+ //v12
260
+ /**
261
+ * OPTIONAL. The minimum amount of time in seconds that the Wallet SHOULD wait between polling requests to the token endpoint (in case the Authorization Server responds with error code authorization_pending - see Section 6.3). If no value is provided, Wallets MUST use 5 as the default.
262
+ */
263
+ interval?: number;
264
+
265
+ // v12 feature
266
+ /**
267
+ * OPTIONAL string that the Wallet can use to identify the Authorization Server to use with this grant type when authorization_servers parameter in the Credential Issuer metadata has multiple entries. MUST NOT be used otherwise. The value of this parameter MUST match with one of the values in the authorization_servers array obtained from the Credential Issuer metadata
268
+ */
269
+ authorization_server?: string;
244
270
  }
245
271
 
246
272
  export const PRE_AUTH_CODE_LITERAL = 'pre-authorized_code';
@@ -2,7 +2,8 @@ export enum OpenId4VCIVersion {
2
2
  VER_1_0_08 = 1008,
3
3
  VER_1_0_09 = 1009,
4
4
  VER_1_0_11 = 1011,
5
- VER_UNKNOWN = Number.MIN_VALUE,
5
+ VER_1_0_12 = 1012,
6
+ VER_UNKNOWN = Number.MAX_VALUE,
6
7
  }
7
8
 
8
9
  export enum DefaultURISchemes {
@@ -2,13 +2,15 @@ import { AuthorizationDetailsJwtVcJson, CommonAuthorizationRequest } from './Aut
2
2
  import {
3
3
  CommonCredentialRequest,
4
4
  CredentialDataSupplierInput,
5
+ CredentialIssuerMetadataOpts,
5
6
  CredentialOfferFormat,
6
7
  CredentialRequestJwtVcJson,
7
- CredentialRequestJwtVcJsonLdAndLdpVc,
8
8
  CredentialRequestSdJwtVc,
9
9
  Grant,
10
+ JsonLdIssuerCredentialDefinition,
10
11
  } from './Generic.types';
11
12
  import { QRCodeOpts } from './QRCode.types';
13
+ import { AuthorizationServerMetadata } from './ServerMetadata';
12
14
 
13
15
  export interface CredentialOfferV1_0_11 {
14
16
  credential_offer?: CredentialOfferPayloadV1_0_11;
@@ -48,10 +50,25 @@ export interface CredentialOfferPayloadV1_0_11 {
48
50
  * using the respective metadata. When multiple grants are present, it's at the Wallet's discretion which one to use.
49
51
  */
50
52
  grants?: Grant;
53
+
54
+ /**
55
+ * Some implementations might include a client_id in the offer. For instance EBSI in a same-device flow. (Cross-device tucks it in the state JWT)
56
+ */
57
+ client_id?: string;
51
58
  }
52
59
 
53
60
  export type CredentialRequestV1_0_11 = CommonCredentialRequest &
54
- (CredentialRequestJwtVcJson | CredentialRequestJwtVcJsonLdAndLdpVc | CredentialRequestSdJwtVc);
61
+ (CredentialRequestJwtVcJson | CredentialRequestJwtVcJsonLdAndLdpVcV1_0_11 | CredentialRequestSdJwtVc);
62
+
63
+ export interface CredentialRequestJwtVcJsonLdAndLdpVcV1_0_11
64
+ extends CommonCredentialRequest,
65
+ Pick<JsonLdIssuerCredentialDefinition, 'credentialSubject' | 'types'> {
66
+ format: 'ldp_vc' | 'jwt_vc_json-ld';
67
+ }
68
+ export interface CredentialIssuerMetadataV1_0_11 extends CredentialIssuerMetadataOpts, Partial<AuthorizationServerMetadata> {
69
+ credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components.
70
+ authorization_server?: string;
71
+ }
55
72
 
56
73
  export interface AuthorizationRequestV1_0_11 extends AuthorizationDetailsJwtVcJson, AuthorizationDetailsJwtVcJson {
57
74
  issuer_state?: string;
@@ -0,0 +1,4 @@
1
+ import { CommonCredentialRequest, CredentialRequestJwtVcJson, CredentialRequestJwtVcJsonLdAndLdpVc, CredentialRequestSdJwtVc } from './Generic.types';
2
+
3
+ export type CredentialRequestV1_0_12 = CommonCredentialRequest &
4
+ (CredentialRequestJwtVcJson | CredentialRequestJwtVcJsonLdAndLdpVc | CredentialRequestSdJwtVc);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/oid4vci-common",
3
- "version": "0.8.2-next.48+81adb47",
3
+ "version": "0.8.2-next.87+9f0679e",
4
4
  "description": "OpenID 4 Verifiable Credential Issuance Common Types",
5
5
  "source": "lib/index.ts",
6
6
  "main": "dist/index.js",
@@ -12,12 +12,23 @@
12
12
  "dependencies": {
13
13
  "@sphereon/ssi-types": "^0.18.1",
14
14
  "cross-fetch": "^3.1.8",
15
- "jwt-decode": "^3.1.2"
15
+ "jwt-decode": "^3.1.2",
16
+ "sha.js": "^2.4.11",
17
+ "uint8arrays": "3.1.1"
16
18
  },
17
19
  "devDependencies": {
18
20
  "@types/jest": "^29.5.3",
21
+ "@types/sha.js": "^2.4.4",
19
22
  "typescript": "5.3.3"
20
23
  },
24
+ "peerDependencies": {
25
+ "msrcrypto": "^1.5.8"
26
+ },
27
+ "peerDependenciesMeta": {
28
+ "msrcrypto": {
29
+ "optional": true
30
+ }
31
+ },
21
32
  "engines": {
22
33
  "node": ">=18"
23
34
  },
@@ -46,5 +57,5 @@
46
57
  "publishConfig": {
47
58
  "access": "public"
48
59
  },
49
- "gitHead": "81adb47112f687715737f17c5e8518739b8a6a58"
60
+ "gitHead": "9f0679e6cbf0b0ba7f7d4f8ecc2263981d4ef80e"
50
61
  }