@sphereon/oid4vci-client 0.8.2-next.4 → 0.8.2-next.46

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 (45) hide show
  1. package/README.md +9 -8
  2. package/dist/AccessTokenClient.d.ts.map +1 -1
  3. package/dist/AccessTokenClient.js +9 -9
  4. package/dist/AccessTokenClient.js.map +1 -1
  5. package/dist/AuthorizationDetailsBuilder.d.ts.map +1 -1
  6. package/dist/AuthorizationDetailsBuilder.js.map +1 -1
  7. package/dist/CredentialOfferClient.js.map +1 -1
  8. package/dist/CredentialRequestClient.d.ts +13 -0
  9. package/dist/CredentialRequestClient.d.ts.map +1 -1
  10. package/dist/CredentialRequestClient.js +87 -41
  11. package/dist/CredentialRequestClient.js.map +1 -1
  12. package/dist/CredentialRequestClientBuilder.d.ts +19 -7
  13. package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
  14. package/dist/CredentialRequestClientBuilder.js +31 -1
  15. package/dist/CredentialRequestClientBuilder.js.map +1 -1
  16. package/dist/MetadataClient.d.ts.map +1 -1
  17. package/dist/MetadataClient.js +12 -1
  18. package/dist/MetadataClient.js.map +1 -1
  19. package/dist/OpenID4VCIClient.d.ts +19 -5
  20. package/dist/OpenID4VCIClient.d.ts.map +1 -1
  21. package/dist/OpenID4VCIClient.js +119 -41
  22. package/dist/OpenID4VCIClient.js.map +1 -1
  23. package/dist/ProofOfPossessionBuilder.d.ts +3 -1
  24. package/dist/ProofOfPossessionBuilder.d.ts.map +1 -1
  25. package/dist/ProofOfPossessionBuilder.js +5 -0
  26. package/dist/ProofOfPossessionBuilder.js.map +1 -1
  27. package/dist/functions/ProofUtil.d.ts +2 -1
  28. package/dist/functions/ProofUtil.d.ts.map +1 -1
  29. package/dist/functions/ProofUtil.js +6 -4
  30. package/dist/functions/ProofUtil.js.map +1 -1
  31. package/lib/AccessTokenClient.ts +11 -9
  32. package/lib/AuthorizationDetailsBuilder.ts +2 -2
  33. package/lib/CredentialRequestClient.ts +105 -43
  34. package/lib/CredentialRequestClientBuilder.ts +53 -8
  35. package/lib/MetadataClient.ts +13 -1
  36. package/lib/OpenID4VCIClient.ts +152 -42
  37. package/lib/ProofOfPossessionBuilder.ts +8 -0
  38. package/lib/__tests__/CredentialRequestClient.spec.ts +21 -9
  39. package/lib/__tests__/EBSIE2E.spec.test.ts +143 -0
  40. package/lib/__tests__/MetadataClient.spec.ts +4 -1
  41. package/lib/__tests__/OpenID4VCIClient.spec.ts +5 -0
  42. package/lib/__tests__/SdJwt.spec.ts +161 -0
  43. package/lib/__tests__/data/VciDataFixtures.ts +14 -13
  44. package/lib/functions/ProofUtil.ts +18 -4
  45. package/package.json +8 -6
@@ -1,4 +1,4 @@
1
- import { Jwt, ProofOfPossession, ProofOfPossessionCallbacks, Typ } from '@sphereon/oid4vci-common';
1
+ import { JWK, Jwt, ProofOfPossession, ProofOfPossessionCallbacks, Typ } from '@sphereon/oid4vci-common';
2
2
  /**
3
3
  *
4
4
  * - proofOfPossessionCallback: JWTSignerCallback
@@ -20,6 +20,7 @@ export declare const createProofOfPossession: <DIDDoc>(callbacks: ProofOfPossess
20
20
  export interface JwtProps {
21
21
  typ?: Typ;
22
22
  kid?: string;
23
+ jwk?: JWK;
23
24
  issuer?: string;
24
25
  clientId?: string;
25
26
  alg?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ProofUtil.d.ts","sourceRoot":"","sources":["../../lib/functions/ProofUtil.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,GAAG,EAAyB,iBAAiB,EAAE,0BAA0B,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAKrJ;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,qEAEvB,QAAQ,gBACL,GAAG,KAChB,QAAQ,iBAAiB,CA0B3B,CAAC;AAQF,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"ProofUtil.d.ts","sourceRoot":"","sources":["../../lib/functions/ProofUtil.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,GAAG,EAEH,GAAG,EAGH,iBAAiB,EACjB,0BAA0B,EAC1B,GAAG,EACJ,MAAM,0BAA0B,CAAC;AAKlC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,qEAEvB,QAAQ,gBACL,GAAG,KAChB,QAAQ,iBAAiB,CA0B3B,CAAC;AAQF,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -66,7 +66,7 @@ const partiallyValidateJWS = (jws) => {
66
66
  }
67
67
  };
68
68
  const createJWT = (jwtProps, existingJwt) => {
69
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
69
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
70
70
  const aud = getJwtProperty('aud', true, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.issuer, (_a = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.payload) === null || _a === void 0 ? void 0 : _a.aud);
71
71
  const iss = getJwtProperty('iss', false, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.clientId, (_b = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.payload) === null || _b === void 0 ? void 0 : _b.iss);
72
72
  const jti = getJwtProperty('jti', false, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.jti, (_c = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.payload) === null || _c === void 0 ? void 0 : _c.jti);
@@ -74,14 +74,16 @@ const createJWT = (jwtProps, existingJwt) => {
74
74
  const nonce = getJwtProperty('nonce', false, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.nonce, (_e = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.payload) === null || _e === void 0 ? void 0 : _e.nonce); // Officially this is required, but some implementations don't have it
75
75
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
76
76
  const alg = getJwtProperty('alg', false, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.alg, (_f = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.header) === null || _f === void 0 ? void 0 : _f.alg, 'ES256');
77
- const kid = getJwtProperty('kid', true, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.kid, (_g = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.header) === null || _g === void 0 ? void 0 : _g.kid);
77
+ const kid = getJwtProperty('kid', false, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.kid, (_g = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.header) === null || _g === void 0 ? void 0 : _g.kid);
78
+ const jwk = getJwtProperty('jwk', false, jwtProps === null || jwtProps === void 0 ? void 0 : jwtProps.jwk, (_h = existingJwt === null || existingJwt === void 0 ? void 0 : existingJwt.header) === null || _h === void 0 ? void 0 : _h.jwk);
78
79
  const jwt = existingJwt ? existingJwt : {};
79
80
  const now = +new Date();
80
- const jwtPayload = Object.assign(Object.assign({ aud, iat: ((_h = jwt.payload) === null || _h === void 0 ? void 0 : _h.iat) ? jwt.payload.iat : now / 1000 - 60, exp: ((_j = jwt.payload) === null || _j === void 0 ? void 0 : _j.exp) ? jwt.payload.exp : now / 1000 + 10 * 60, nonce }, (iss ? { iss } : {})), (jti ? { jti } : {}));
81
+ const jwtPayload = Object.assign(Object.assign({ aud, iat: ((_j = jwt.payload) === null || _j === void 0 ? void 0 : _j.iat) ? jwt.payload.iat : now / 1000 - 60, exp: ((_k = jwt.payload) === null || _k === void 0 ? void 0 : _k.exp) ? jwt.payload.exp : now / 1000 + 10 * 60, nonce }, (iss ? { iss } : {})), (jti ? { jti } : {}));
81
82
  const jwtHeader = {
82
83
  typ,
83
84
  alg,
84
85
  kid,
86
+ jwk,
85
87
  };
86
88
  return {
87
89
  payload: Object.assign(Object.assign({}, jwt.payload), jwtPayload),
@@ -89,7 +91,7 @@ const createJWT = (jwtProps, existingJwt) => {
89
91
  };
90
92
  };
91
93
  const getJwtProperty = (propertyName, required, option, jwtProperty, defaultValue) => {
92
- if (option && jwtProperty && option !== jwtProperty) {
94
+ if (typeof option === 'string' && option && jwtProperty && option !== jwtProperty) {
93
95
  throw Error(`Cannot have a property '${propertyName}' with value '${option}' and different JWT value '${jwtProperty}' at the same time`);
94
96
  }
95
97
  let result = (jwtProperty ? jwtProperty : option);
@@ -1 +1 @@
1
- {"version":3,"file":"ProofUtil.js","sourceRoot":"","sources":["../../lib/functions/ProofUtil.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProofUtil.js","sourceRoot":"","sources":["../../lib/functions/ProofUtil.ts"],"names":[],"mappings":"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"}
@@ -27,9 +27,11 @@ export class AccessTokenClient {
27
27
  public async acquireAccessToken(opts: AccessTokenRequestOpts): Promise<OpenIDResponse<AccessTokenResponse>> {
28
28
  const { asOpts, pin, codeVerifier, code, redirectUri, metadata } = opts;
29
29
 
30
- const credentialOffer = await assertedUniformCredentialOffer(opts.credentialOffer);
31
- const isPinRequired = this.isPinRequiredValue(credentialOffer.credential_offer);
32
- const issuer = getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) ?? (metadata?.issuer as string);
30
+ const credentialOffer = opts.credentialOffer ? await assertedUniformCredentialOffer(opts.credentialOffer) : undefined;
31
+ const isPinRequired = credentialOffer && this.isPinRequiredValue(credentialOffer.credential_offer);
32
+ const issuer =
33
+ opts.credentialIssuer ??
34
+ (credentialOffer ? getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) : (metadata?.issuer as string));
33
35
  if (!issuer) {
34
36
  throw Error('Issuer required at this point');
35
37
  }
@@ -83,14 +85,14 @@ export class AccessTokenClient {
83
85
 
84
86
  public async createAccessTokenRequest(opts: AccessTokenRequestOpts): Promise<AccessTokenRequest> {
85
87
  const { asOpts, pin, codeVerifier, code, redirectUri } = opts;
86
- const credentialOfferRequest = await toUniformCredentialOfferRequest(opts.credentialOffer);
88
+ const credentialOfferRequest = opts.credentialOffer ? await toUniformCredentialOfferRequest(opts.credentialOffer) : undefined;
87
89
  const request: Partial<AccessTokenRequest> = {};
88
90
 
89
91
  if (asOpts?.clientId) {
90
92
  request.client_id = asOpts.clientId;
91
93
  }
92
94
 
93
- if (credentialOfferRequest.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) {
95
+ if (credentialOfferRequest?.supportedFlows.includes(AuthzFlowType.PRE_AUTHORIZED_CODE_FLOW)) {
94
96
  this.assertNumericPin(this.isPinRequiredValue(credentialOfferRequest.credential_offer), pin);
95
97
  request.user_pin = pin;
96
98
 
@@ -102,7 +104,7 @@ export class AccessTokenClient {
102
104
  return request as AccessTokenRequest;
103
105
  }
104
106
 
105
- if (credentialOfferRequest.supportedFlows.includes(AuthzFlowType.AUTHORIZATION_CODE_FLOW)) {
107
+ if (!credentialOfferRequest || credentialOfferRequest.supportedFlows.includes(AuthzFlowType.AUTHORIZATION_CODE_FLOW)) {
106
108
  request.grant_type = GrantTypes.AUTHORIZATION_CODE;
107
109
  request.code = code;
108
110
  request.redirect_uri = redirectUri;
@@ -193,7 +195,7 @@ export class AccessTokenClient {
193
195
  this.assertNonEmptyCode(accessTokenRequest);
194
196
  this.assertNonEmptyRedirectUri(accessTokenRequest);
195
197
  } else {
196
- this.throwNotSupportedFlow;
198
+ this.throwNotSupportedFlow();
197
199
  }
198
200
  }
199
201
 
@@ -243,7 +245,7 @@ export class AccessTokenClient {
243
245
  }
244
246
 
245
247
  private throwNotSupportedFlow(): void {
246
- debug(`Only pre-authorized flow supported.`);
247
- throw new Error('Only pre-authorized-code flow is supported');
248
+ debug(`Only pre-authorized or authorization code flows supported.`);
249
+ throw new Error('Only pre-authorized-code or authorization code flows are supported');
248
250
  }
249
251
  }
@@ -1,8 +1,8 @@
1
- import { AuthorizationDetailsJwtVcJson, OID4VCICredentialFormat } from '@sphereon/oid4vci-common';
1
+ import { AuthorizationDetails, AuthorizationDetailsJwtVcJson, OID4VCICredentialFormat } from '@sphereon/oid4vci-common';
2
2
 
3
3
  //todo: refactor this builder to be able to create ldp details as well
4
4
  export class AuthorizationDetailsBuilder {
5
- private readonly authorizationDetails: Partial<AuthorizationDetailsJwtVcJson>;
5
+ private readonly authorizationDetails: Partial<Exclude<AuthorizationDetails, string>>;
6
6
 
7
7
  constructor() {
8
8
  this.authorizationDetails = {};
@@ -1,6 +1,9 @@
1
1
  import {
2
- CredentialRequestV1_0_08,
2
+ acquireDeferredCredential,
3
3
  CredentialResponse,
4
+ getCredentialRequestForVersion,
5
+ getUniformFormat,
6
+ isDeferredCredentialResponse,
4
7
  OID4VCICredentialFormat,
5
8
  OpenId4VCIVersion,
6
9
  OpenIDResponse,
@@ -18,7 +21,10 @@ import { isValidURL, post } from './functions';
18
21
  const debug = Debug('sphereon:oid4vci:credential');
19
22
 
20
23
  export interface CredentialRequestOpts {
24
+ deferredCredentialAwait?: boolean;
25
+ deferredCredentialIntervalInMS?: number;
21
26
  credentialEndpoint: string;
27
+ deferredCredentialEndpoint?: string;
22
28
  credentialTypes: string[];
23
29
  format?: CredentialFormat | OID4VCICredentialFormat;
24
30
  proof: ProofOfPossession;
@@ -26,17 +32,45 @@ export interface CredentialRequestOpts {
26
32
  version: OpenId4VCIVersion;
27
33
  }
28
34
 
35
+ export async function buildProof<DIDDoc>(
36
+ proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession,
37
+ opts: {
38
+ version: OpenId4VCIVersion;
39
+ cNonce?: string;
40
+ },
41
+ ) {
42
+ if ('proof_type' in proofInput) {
43
+ if (opts.cNonce) {
44
+ throw Error(`Cnonce param is only supported when using a Proof of Posession builder`);
45
+ }
46
+ return await ProofOfPossessionBuilder.fromProof(proofInput as ProofOfPossession, opts.version).build();
47
+ }
48
+ if (opts.cNonce) {
49
+ proofInput.withAccessTokenNonce(opts.cNonce);
50
+ }
51
+ return await proofInput.build();
52
+ }
53
+
29
54
  export class CredentialRequestClient {
30
55
  private readonly _credentialRequestOpts: Partial<CredentialRequestOpts>;
56
+ private _isDeferred = false;
31
57
 
32
58
  get credentialRequestOpts(): CredentialRequestOpts {
33
59
  return this._credentialRequestOpts as CredentialRequestOpts;
34
60
  }
35
61
 
62
+ public isDeferred(): boolean {
63
+ return this._isDeferred;
64
+ }
65
+
36
66
  public getCredentialEndpoint(): string {
37
67
  return this.credentialRequestOpts.credentialEndpoint;
38
68
  }
39
69
 
70
+ public getDeferredCredentialEndpoint(): string | undefined {
71
+ return this.credentialRequestOpts.deferredCredentialEndpoint;
72
+ }
73
+
40
74
  public constructor(builder: CredentialRequestClientBuilder) {
41
75
  this._credentialRequestOpts = { ...builder };
42
76
  }
@@ -53,36 +87,49 @@ export class CredentialRequestClient {
53
87
  }
54
88
 
55
89
  public async acquireCredentialsUsingRequest(uniformRequest: UniformCredentialRequest): Promise<OpenIDResponse<CredentialResponse>> {
56
- let request: CredentialRequestV1_0_08 | UniformCredentialRequest = uniformRequest;
57
- if (!this.isV11OrHigher()) {
58
- let format: string = uniformRequest.format;
59
- if (format === 'jwt_vc_json') {
60
- format = 'jwt_vc';
61
- } else if (format === 'jwt_vc_json-ld') {
62
- format = 'ldp_vc';
63
- }
64
-
65
- request = {
66
- format,
67
- proof: uniformRequest.proof,
68
- type:
69
- 'types' in uniformRequest
70
- ? uniformRequest.types.filter((t) => t !== 'VerifiableCredential')[0]
71
- : uniformRequest.credential_definition.types[0],
72
- } as CredentialRequestV1_0_08;
73
- }
90
+ const request = getCredentialRequestForVersion(uniformRequest, this.version());
74
91
  const credentialEndpoint: string = this.credentialRequestOpts.credentialEndpoint;
75
92
  if (!isValidURL(credentialEndpoint)) {
76
93
  debug(`Invalid credential endpoint: ${credentialEndpoint}`);
77
94
  throw new Error(URL_NOT_VALID);
78
95
  }
79
96
  debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
97
+ debug(`request\n: ${JSON.stringify(request, null, 2)}`);
80
98
  const requestToken: string = this.credentialRequestOpts.token;
81
- const response: OpenIDResponse<CredentialResponse> = await post(credentialEndpoint, JSON.stringify(request), { bearerToken: requestToken });
82
- debug(`Credential endpoint ${credentialEndpoint} response:\r\n${response}`);
99
+ let response: OpenIDResponse<CredentialResponse> = await post(credentialEndpoint, JSON.stringify(request), { bearerToken: requestToken });
100
+ this._isDeferred = isDeferredCredentialResponse(response);
101
+ if (this.isDeferred() && this.credentialRequestOpts.deferredCredentialAwait && response.successBody) {
102
+ response = await this.acquireDeferredCredential(response.successBody, { bearerToken: this.credentialRequestOpts.token });
103
+ }
104
+
105
+ debug(`Credential endpoint ${credentialEndpoint} response:\r\n${JSON.stringify(response, null, 2)}`);
83
106
  return response;
84
107
  }
85
108
 
109
+ public async acquireDeferredCredential(
110
+ response: Pick<CredentialResponse, 'transaction_id' | 'acceptance_token' | 'c_nonce'>,
111
+ opts?: {
112
+ bearerToken?: string;
113
+ },
114
+ ): Promise<OpenIDResponse<CredentialResponse>> {
115
+ const transactionId = response.transaction_id;
116
+ const bearerToken = response.acceptance_token ?? opts?.bearerToken;
117
+ const deferredCredentialEndpoint = this.getDeferredCredentialEndpoint();
118
+ if (!deferredCredentialEndpoint) {
119
+ throw Error(`No deferred credential endpoint supplied.`);
120
+ } else if (!bearerToken) {
121
+ throw Error(`No bearer token present and refresh for defered endpoint not supported yet`);
122
+ // todo updated bearer token with new c_nonce
123
+ }
124
+ return await acquireDeferredCredential({
125
+ bearerToken,
126
+ transactionId,
127
+ deferredCredentialEndpoint,
128
+ deferredCredentialAwait: this.credentialRequestOpts.deferredCredentialAwait,
129
+ deferredCredentialIntervalInMS: this.credentialRequestOpts.deferredCredentialIntervalInMS,
130
+ });
131
+ }
132
+
86
133
  public async createCredentialRequest<DIDDoc>(opts: {
87
134
  proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
88
135
  credentialTypes?: string | string[];
@@ -92,20 +139,10 @@ export class CredentialRequestClient {
92
139
  const { proofInput } = opts;
93
140
  const formatSelection = opts.format ?? this.credentialRequestOpts.format;
94
141
 
95
- let format: OID4VCICredentialFormat = formatSelection as OID4VCICredentialFormat;
96
- if (opts.version < OpenId4VCIVersion.VER_1_0_11) {
97
- if (formatSelection === 'jwt_vc' || formatSelection === 'jwt') {
98
- format = 'jwt_vc_json';
99
- } else if (formatSelection === 'ldp_vc' || formatSelection === 'ldp') {
100
- format = 'jwt_vc_json-ld';
101
- }
102
- }
103
-
104
- if (!format) {
142
+ if (!formatSelection) {
105
143
  throw Error(`Format of credential to be issued is missing`);
106
- } else if (format !== 'jwt_vc_json-ld' && format !== 'jwt_vc_json' && format !== 'ldp_vc') {
107
- throw Error(`Invalid format of credential to be issued: ${format}`);
108
144
  }
145
+ const format = getUniformFormat(formatSelection);
109
146
  const typesSelection =
110
147
  opts?.credentialTypes && (typeof opts.credentialTypes === 'string' || opts.credentialTypes.length > 0)
111
148
  ? opts.credentialTypes
@@ -113,24 +150,49 @@ export class CredentialRequestClient {
113
150
  const types = Array.isArray(typesSelection) ? typesSelection : [typesSelection];
114
151
  if (types.length === 0) {
115
152
  throw Error(`Credential type(s) need to be provided`);
116
- } else if (!this.isV11OrHigher() && types.length !== 1) {
153
+ }
154
+ // FIXME: this is mixing up the type (as id) from v8/v9 and the types (from the vc.type) from v11
155
+ else if (!this.isV11OrHigher() && types.length !== 1) {
117
156
  throw Error('Only a single credential type is supported for V8/V9');
118
157
  }
158
+ const proof = await buildProof(proofInput, opts);
119
159
 
120
- const proof =
121
- 'proof_type' in proofInput
122
- ? await ProofOfPossessionBuilder.fromProof(proofInput as ProofOfPossession, opts.version).build()
123
- : await proofInput.build();
124
- return {
125
- types,
126
- format,
127
- proof,
128
- } as UniformCredentialRequest;
160
+ // TODO: we should move format specific logic
161
+ if (format === 'jwt_vc_json' || format === 'jwt_vc') {
162
+ return {
163
+ types,
164
+ format,
165
+ proof,
166
+ };
167
+ } else if (format === 'jwt_vc_json-ld' || format === 'ldp_vc') {
168
+ return {
169
+ format,
170
+ proof,
171
+ credential_definition: {
172
+ types,
173
+ // FIXME: this was not included in the original code, but it is required
174
+ '@context': [],
175
+ },
176
+ };
177
+ } else if (format === 'vc+sd-jwt') {
178
+ if (types.length > 1) {
179
+ throw Error(`Only a single credential type is supported for ${format}`);
180
+ }
181
+
182
+ return {
183
+ format,
184
+ proof,
185
+ vct: types[0],
186
+ };
187
+ }
188
+
189
+ throw new Error(`Unsupported format: ${format}`);
129
190
  }
130
191
 
131
192
  private version(): OpenId4VCIVersion {
132
193
  return this.credentialRequestOpts?.version ?? OpenId4VCIVersion.VER_1_0_11;
133
194
  }
195
+
134
196
  private isV11OrHigher(): boolean {
135
197
  return this.version() >= OpenId4VCIVersion.VER_1_0_11;
136
198
  }
@@ -6,6 +6,7 @@ import {
6
6
  determineSpecVersionFromOffer,
7
7
  EndpointMetadata,
8
8
  getIssuerFromCredentialOfferPayload,
9
+ getTypesFromOffer,
9
10
  OID4VCICredentialFormat,
10
11
  OpenId4VCIVersion,
11
12
  UniformCredentialOfferRequest,
@@ -17,11 +18,36 @@ import { CredentialRequestClient } from './CredentialRequestClient';
17
18
 
18
19
  export class CredentialRequestClientBuilder {
19
20
  credentialEndpoint?: string;
21
+ deferredCredentialEndpoint?: string;
22
+ deferredCredentialAwait = false;
23
+ deferredCredentialIntervalInMS = 5000;
20
24
  credentialTypes: string[] = [];
21
25
  format?: CredentialFormat | OID4VCICredentialFormat;
22
26
  token?: string;
23
27
  version?: OpenId4VCIVersion;
24
28
 
29
+ public static fromCredentialIssuer({
30
+ credentialIssuer,
31
+ metadata,
32
+ version,
33
+ credentialTypes,
34
+ }: {
35
+ credentialIssuer: string;
36
+ metadata?: EndpointMetadata;
37
+ version?: OpenId4VCIVersion;
38
+ credentialTypes: string | string[];
39
+ }): CredentialRequestClientBuilder {
40
+ const issuer = credentialIssuer;
41
+ const builder = new CredentialRequestClientBuilder();
42
+ builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_11);
43
+ builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
44
+ if (metadata?.deferred_credential_endpoint) {
45
+ builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
46
+ }
47
+ builder.withCredentialType(credentialTypes);
48
+ return builder;
49
+ }
50
+
25
51
  public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilder> {
26
52
  const offer = await CredentialOfferClient.fromURI(uri);
27
53
  return CredentialRequestClientBuilder.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
@@ -40,13 +66,16 @@ export class CredentialRequestClientBuilder {
40
66
  const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
41
67
  builder.withVersion(version);
42
68
  builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
69
+ if (metadata?.deferred_credential_endpoint) {
70
+ builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
71
+ }
43
72
 
44
73
  if (version <= OpenId4VCIVersion.VER_1_0_08) {
45
74
  //todo: This basically sets all types available during initiation. Probably the user only wants a subset. So do we want to do this?
46
75
  builder.withCredentialType((request.original_credential_offer as CredentialOfferPayloadV1_0_08).credential_type);
47
76
  } else {
48
77
  // todo: look whether this is correct
49
- builder.withCredentialType(request.credential_offer.credentials.flatMap((c) => (typeof c === 'string' ? c : c.types)));
78
+ builder.withCredentialType(getTypesFromOffer(request.credential_offer));
50
79
  }
51
80
 
52
81
  return builder;
@@ -66,37 +95,53 @@ export class CredentialRequestClientBuilder {
66
95
  });
67
96
  }
68
97
 
69
- public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): CredentialRequestClientBuilder {
98
+ public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
70
99
  this.credentialEndpoint = metadata.credential_endpoint;
71
100
  return this;
72
101
  }
73
102
 
74
- public withCredentialEndpoint(credentialEndpoint: string): CredentialRequestClientBuilder {
103
+ public withCredentialEndpoint(credentialEndpoint: string): this {
75
104
  this.credentialEndpoint = credentialEndpoint;
76
105
  return this;
77
106
  }
78
107
 
79
- public withCredentialType(credentialTypes: string | string[]): CredentialRequestClientBuilder {
108
+ public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
109
+ this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
110
+ return this;
111
+ }
112
+
113
+ public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
114
+ this.deferredCredentialEndpoint = deferredCredentialEndpoint;
115
+ return this;
116
+ }
117
+
118
+ public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
119
+ this.deferredCredentialAwait = deferredCredentialAwait;
120
+ this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
121
+ return this;
122
+ }
123
+
124
+ public withCredentialType(credentialTypes: string | string[]): this {
80
125
  this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
81
126
  return this;
82
127
  }
83
128
 
84
- public withFormat(format: CredentialFormat | OID4VCICredentialFormat): CredentialRequestClientBuilder {
129
+ public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
85
130
  this.format = format;
86
131
  return this;
87
132
  }
88
133
 
89
- public withToken(accessToken: string): CredentialRequestClientBuilder {
134
+ public withToken(accessToken: string): this {
90
135
  this.token = accessToken;
91
136
  return this;
92
137
  }
93
138
 
94
- public withTokenFromResponse(response: AccessTokenResponse): CredentialRequestClientBuilder {
139
+ public withTokenFromResponse(response: AccessTokenResponse): this {
95
140
  this.token = response.access_token;
96
141
  return this;
97
142
  }
98
143
 
99
- public withVersion(version: OpenId4VCIVersion): CredentialRequestClientBuilder {
144
+ public withVersion(version: OpenId4VCIVersion): this {
100
145
  this.version = version;
101
146
  return this;
102
147
  }
@@ -45,6 +45,7 @@ export class MetadataClient {
45
45
  public static async retrieveAllMetadata(issuer: string, opts?: { errorOnNotFound: boolean }): Promise<EndpointMetadataResult> {
46
46
  let token_endpoint: string | undefined;
47
47
  let credential_endpoint: string | undefined;
48
+ let deferred_credential_endpoint: string | undefined;
48
49
  let authorization_endpoint: string | undefined;
49
50
  let authorizationServerType: AuthorizationServerType = 'OID4VCI';
50
51
  let authorization_server: string = issuer;
@@ -53,6 +54,7 @@ export class MetadataClient {
53
54
  if (credentialIssuerMetadata) {
54
55
  debug(`Issuer ${issuer} OID4VCI well-known server metadata\r\n${JSON.stringify(credentialIssuerMetadata)}`);
55
56
  credential_endpoint = credentialIssuerMetadata.credential_endpoint;
57
+ deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint;
56
58
  if (credentialIssuerMetadata.token_endpoint) {
57
59
  token_endpoint = credentialIssuerMetadata.token_endpoint;
58
60
  }
@@ -111,12 +113,21 @@ export class MetadataClient {
111
113
  if (authMetadata.credential_endpoint) {
112
114
  if (credential_endpoint && authMetadata.credential_endpoint !== credential_endpoint) {
113
115
  debug(
114
- `Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.token_endpoint}). Will use the issuer value`,
116
+ `Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.credential_endpoint}). Will use the issuer value`,
115
117
  );
116
118
  } else {
117
119
  credential_endpoint = authMetadata.credential_endpoint;
118
120
  }
119
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
+ }
120
131
  }
121
132
 
122
133
  if (!authorization_endpoint) {
@@ -148,6 +159,7 @@ export class MetadataClient {
148
159
  issuer,
149
160
  token_endpoint,
150
161
  credential_endpoint,
162
+ deferred_credential_endpoint,
151
163
  authorization_server,
152
164
  authorization_endpoint,
153
165
  authorizationServerType,