Skip to content

Commit 609dccd

Browse files
committed
chore: v11 context fix
1 parent 6ddf9b0 commit 609dccd

8 files changed

Lines changed: 100 additions & 13 deletions

File tree

packages/client/lib/CredentialRequestClient.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ export class CredentialRequestClient {
7878
public async acquireCredentialsUsingProof<DIDDoc>(opts: {
7979
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
8080
credentialTypes?: string | string[];
81+
context?: string[];
8182
format?: CredentialFormat | OID4VCICredentialFormat;
8283
}): Promise<OpenIDResponse<CredentialResponse>> {
83-
const { credentialTypes, proofInput, format } = opts;
84+
const { credentialTypes, proofInput, format, context } = opts;
8485

85-
const request = await this.createCredentialRequest({ proofInput, credentialTypes, format, version: this.version() });
86+
const request = await this.createCredentialRequest({ proofInput, credentialTypes, context, format, version: this.version() });
8687
return await this.acquireCredentialsUsingRequest(request);
8788
}
8889

@@ -133,6 +134,7 @@ export class CredentialRequestClient {
133134
public async createCredentialRequest<DIDDoc>(opts: {
134135
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
135136
credentialTypes?: string | string[];
137+
context?: string[];
136138
format?: CredentialFormat | OID4VCICredentialFormat;
137139
version: OpenId4VCIVersion;
138140
}): Promise<UniformCredentialRequest> {
@@ -165,13 +167,20 @@ export class CredentialRequestClient {
165167
proof,
166168
};
167169
} else if (format === 'jwt_vc_json-ld' || format === 'ldp_vc') {
170+
if (this.version() >= OpenId4VCIVersion.VER_1_0_12 && !opts.context) {
171+
throw Error('No @context value present, but it is required');
172+
}
173+
168174
return {
169175
format,
170176
proof,
177+
178+
// Ignored because v11 does not have the context value, but it is required in v12
179+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
180+
// @ts-ignore
171181
credential_definition: {
172182
types,
173-
// FIXME: this was not included in the original code, but it is required
174-
'@context': [],
183+
...(opts.context && { '@context': opts.context }),
175184
},
176185
};
177186
} else if (format === 'vc+sd-jwt') {

packages/client/lib/OpenID4VCIClient.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ export class OpenID4VCIClient {
281281

282282
public async acquireCredentials({
283283
credentialTypes,
284+
context,
284285
proofCallbacks,
285286
format,
286287
kid,
@@ -291,6 +292,7 @@ export class OpenID4VCIClient {
291292
deferredCredentialIntervalInMS,
292293
}: {
293294
credentialTypes: string | string[];
295+
context?: string[];
294296
proofCallbacks: ProofOfPossessionCallbacks<any>;
295297
format?: CredentialFormat | OID4VCICredentialFormat;
296298
kid?: string;
@@ -375,7 +377,8 @@ export class OpenID4VCIClient {
375377
}
376378
const response = await credentialRequestClient.acquireCredentialsUsingProof({
377379
proofInput: proofBuilder,
378-
credentialTypes: credentialTypes,
380+
credentialTypes,
381+
context,
379382
format,
380383
});
381384
if (response.errorBody) {

packages/common/lib/functions/CredentialOfferUtil.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ export const getStateFromCredentialOfferPayload = (credentialOffer: CredentialOf
113113
};
114114

115115
export function determineSpecVersionFromOffer(offer: CredentialOfferPayload | CredentialOffer): OpenId4VCIVersion {
116-
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)) {
117119
return OpenId4VCIVersion.VER_1_0_11;
118120
} else if (isCredentialOfferV1_0_09(offer)) {
119121
return OpenId4VCIVersion.VER_1_0_09;
@@ -183,6 +185,21 @@ function isCredentialOfferV1_0_11(offer: CredentialOfferPayload | CredentialOffe
183185
return 'credential_offer_uri' in offer;
184186
}
185187

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+
186203
export async function toUniformCredentialOfferRequest(
187204
offer: CredentialOffer,
188205
opts?: {

packages/common/lib/functions/CredentialRequestUtil.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { CredentialRequestV1_0_08, OpenId4VCIVersion, UniformCredentialRequest } from '../types';
1+
import {
2+
CredentialRequestV1_0_08,
3+
CredentialRequestV1_0_11,
4+
OpenId4VCIVersion,
5+
UniformCredentialRequest,
6+
} from '../types';
27

38
import { getFormatForVersion } from './FormatUtils';
49

@@ -7,7 +12,9 @@ export function getTypesFromRequest(credentialRequest: UniformCredentialRequest,
712
if (credentialRequest.format === 'jwt_vc_json' || credentialRequest.format === 'jwt_vc') {
813
types = credentialRequest.types;
914
} else if (credentialRequest.format === 'jwt_vc_json-ld' || credentialRequest.format === 'ldp_vc') {
10-
types = credentialRequest.credential_definition.types;
15+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
16+
// @ts-ignore
17+
types = 'credential_definition' in credentialRequest && credentialRequest.credential_definition ? credentialRequest.credential_definition.types : credentialRequest.types;
1118
} else if (credentialRequest.format === 'vc+sd-jwt') {
1219
types = [credentialRequest.vct];
1320
}
@@ -24,7 +31,7 @@ export function getTypesFromRequest(credentialRequest: UniformCredentialRequest,
2431
export function getCredentialRequestForVersion(
2532
credentialRequest: UniformCredentialRequest,
2633
version: OpenId4VCIVersion,
27-
): UniformCredentialRequest | CredentialRequestV1_0_08 {
34+
): UniformCredentialRequest | CredentialRequestV1_0_08 | CredentialRequestV1_0_11 {
2835
if (version === OpenId4VCIVersion.VER_1_0_08) {
2936
const draft8Format = getFormatForVersion(credentialRequest.format, version);
3037
const types = getTypesFromRequest(credentialRequest, { filterVerifiableCredential: true });
@@ -34,6 +41,14 @@ export function getCredentialRequestForVersion(
3441
proof: credentialRequest.proof,
3542
type: types[0],
3643
} 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;*/
3752
}
3853

3954
return credentialRequest;

packages/common/lib/types/Generic.types.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ICredentialContextType, IVerifiableCredential, W3CVerifiableCredential
33
import { ProofOfPossession } from './CredentialIssuance.types';
44
import { AuthorizationServerMetadata } from './ServerMetadata';
55
import { CredentialOfferSession } from './StateManager.types';
6-
import { CredentialRequestV1_0_11 } from './v1_0_11.types';
6+
import { CredentialRequestV1_0_11 } from './v1_0_11.types'
77

88
/**
99
* Important Note: please be aware that these Common interfaces are based on versions v1_0.11 and v1_0.09
@@ -51,16 +51,24 @@ export interface CredentialIssuerMetadataOpts {
5151
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.
5252
credential_issuer: string; // REQUIRED. The Credential Issuer's identifier.
5353
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].
5455
token_endpoint?: string;
5556
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:
5657
credential_supplier_config?: CredentialSupplierConfig;
5758
}
5859

5960
// 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
6061
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].
6163
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.
6268
}
6369

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+
6472
export interface CredentialSupportedBrief {
6573
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
6674
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 {
229237
* Authorization Request with the Credential Issuer to a context set up during previous steps.
230238
*/
231239
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;
232246
}
233247

234248
export interface GrantUrnIetf {
@@ -241,6 +255,18 @@ export interface GrantUrnIetf {
241255
* in a Pre-Authorized Code Flow. Default is false.
242256
*/
243257
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;
244270
}
245271

246272
export const PRE_AUTH_CODE_LITERAL = 'pre-authorized_code';

packages/common/lib/types/OpenID4VCIVersions.types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ export enum OpenId4VCIVersion {
22
VER_1_0_08 = 1008,
33
VER_1_0_09 = 1009,
44
VER_1_0_11 = 1011,
5-
VER_UNKNOWN = Number.MIN_VALUE,
5+
VER_1_0_12 = 1012,
6+
VER_UNKNOWN = Number.MAX_VALUE,
67
}
78

89
export enum DefaultURISchemes {

packages/common/lib/types/v1_0_11.types.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { AuthorizationDetailsJwtVcJson, CommonAuthorizationRequest } from './Aut
22
import {
33
CommonCredentialRequest,
44
CredentialDataSupplierInput,
5+
CredentialIssuerMetadataOpts,
56
CredentialOfferFormat,
67
CredentialRequestJwtVcJson,
7-
CredentialRequestJwtVcJsonLdAndLdpVc,
88
CredentialRequestSdJwtVc,
99
Grant,
10+
JsonLdIssuerCredentialDefinition,
1011
} from './Generic.types';
1112
import { QRCodeOpts } from './QRCode.types';
13+
import { AuthorizationServerMetadata } from './ServerMetadata';
1214

1315
export interface CredentialOfferV1_0_11 {
1416
credential_offer?: CredentialOfferPayloadV1_0_11;
@@ -56,7 +58,17 @@ export interface CredentialOfferPayloadV1_0_11 {
5658
}
5759

5860
export type CredentialRequestV1_0_11 = CommonCredentialRequest &
59-
(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+
}
6072

6173
export interface AuthorizationRequestV1_0_11 extends AuthorizationDetailsJwtVcJson, AuthorizationDetailsJwtVcJson {
6274
issuer_state?: string;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

0 commit comments

Comments
 (0)