@sphereon/oid4vci-client 0.12.1-next.2 → 0.12.1-next.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.
- package/dist/AccessTokenClient.d.ts.map +1 -1
- package/dist/AccessTokenClient.js +7 -5
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -1
- package/dist/AccessTokenClientV1_0_11.js +7 -5
- package/dist/AccessTokenClientV1_0_11.js.map +1 -1
- package/dist/CredentialRequestClient.d.ts +3 -2
- package/dist/CredentialRequestClient.d.ts.map +1 -1
- package/dist/CredentialRequestClient.js.map +1 -1
- package/dist/CredentialRequestClientBuilder.d.ts +7 -15
- package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
- package/dist/CredentialRequestClientBuilder.js +79 -55
- package/dist/CredentialRequestClientBuilder.js.map +1 -1
- package/dist/CredentialRequestClientBuilderV1_0_13.d.ts +51 -0
- package/dist/CredentialRequestClientBuilderV1_0_13.d.ts.map +1 -0
- package/dist/CredentialRequestClientBuilderV1_0_13.js +130 -0
- package/dist/CredentialRequestClientBuilderV1_0_13.js.map +1 -0
- package/dist/OpenID4VCIClient.d.ts +3 -1
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +22 -13
- package/dist/OpenID4VCIClient.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts +2 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.js +13 -4
- package/dist/OpenID4VCIClientV1_0_11.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_13.d.ts +2 -1
- package/dist/OpenID4VCIClientV1_0_13.d.ts.map +1 -1
- package/dist/OpenID4VCIClientV1_0_13.js +16 -7
- package/dist/OpenID4VCIClientV1_0_13.js.map +1 -1
- package/dist/functions/AccessTokenUtil.d.ts +5 -0
- package/dist/functions/AccessTokenUtil.d.ts.map +1 -0
- package/dist/functions/AccessTokenUtil.js +55 -0
- package/dist/functions/AccessTokenUtil.js.map +1 -0
- package/dist/functions/index.d.ts +2 -0
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +2 -0
- package/dist/functions/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/lib/AccessTokenClient.ts +5 -4
- package/lib/AccessTokenClientV1_0_11.ts +6 -3
- package/lib/CredentialRequestClient.ts +3 -2
- package/lib/CredentialRequestClientBuilder.ts +98 -67
- package/lib/CredentialRequestClientBuilderV1_0_13.ts +173 -0
- package/lib/OpenID4VCIClient.ts +27 -6
- package/lib/OpenID4VCIClientV1_0_11.ts +19 -1
- package/lib/OpenID4VCIClientV1_0_13.ts +19 -1
- package/lib/__tests__/CredentialRequestClient.spec.ts +8 -13
- package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +40 -2
- package/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +96 -0
- package/lib/__tests__/IT.spec.ts +148 -111
- package/lib/__tests__/MetadataMocks.ts +35 -0
- package/lib/__tests__/ProofOfPossessionBuilder.spec.ts +85 -0
- package/lib/__tests__/SdJwt.spec.ts +103 -0
- package/lib/functions/AccessTokenUtil.ts +45 -0
- package/lib/functions/index.ts +2 -0
- package/lib/index.ts +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AccessTokenResponse,
|
|
3
|
+
CredentialIssuerMetadataV1_0_13,
|
|
4
|
+
CredentialOfferPayloadV1_0_13,
|
|
5
|
+
CredentialOfferRequestWithBaseUrl,
|
|
6
|
+
determineSpecVersionFromOffer,
|
|
7
|
+
EndpointMetadata,
|
|
8
|
+
ExperimentalSubjectIssuance,
|
|
9
|
+
getIssuerFromCredentialOfferPayload,
|
|
10
|
+
OID4VCICredentialFormat,
|
|
11
|
+
OpenId4VCIVersion,
|
|
12
|
+
UniformCredentialOfferRequest,
|
|
13
|
+
} from '@sphereon/oid4vci-common';
|
|
14
|
+
import { CredentialFormat } from '@sphereon/ssi-types';
|
|
15
|
+
|
|
16
|
+
import { CredentialOfferClient } from './CredentialOfferClient';
|
|
17
|
+
import { CredentialRequestClient } from './CredentialRequestClient';
|
|
18
|
+
|
|
19
|
+
export class CredentialRequestClientBuilderV1_0_13 {
|
|
20
|
+
credentialEndpoint?: string;
|
|
21
|
+
deferredCredentialEndpoint?: string;
|
|
22
|
+
deferredCredentialAwait = false;
|
|
23
|
+
deferredCredentialIntervalInMS = 5000;
|
|
24
|
+
credentialIdentifier?: string;
|
|
25
|
+
credentialTypes?: string[] = [];
|
|
26
|
+
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
27
|
+
token?: string;
|
|
28
|
+
version?: OpenId4VCIVersion;
|
|
29
|
+
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
30
|
+
|
|
31
|
+
public static fromCredentialIssuer({
|
|
32
|
+
credentialIssuer,
|
|
33
|
+
metadata,
|
|
34
|
+
version,
|
|
35
|
+
credentialIdentifier,
|
|
36
|
+
credentialTypes,
|
|
37
|
+
}: {
|
|
38
|
+
credentialIssuer: string;
|
|
39
|
+
metadata?: EndpointMetadata;
|
|
40
|
+
version?: OpenId4VCIVersion;
|
|
41
|
+
credentialIdentifier?: string;
|
|
42
|
+
credentialTypes?: string | string[];
|
|
43
|
+
}): CredentialRequestClientBuilderV1_0_13 {
|
|
44
|
+
const issuer = credentialIssuer;
|
|
45
|
+
const builder = new CredentialRequestClientBuilderV1_0_13();
|
|
46
|
+
builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_13);
|
|
47
|
+
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
48
|
+
if (metadata?.deferred_credential_endpoint) {
|
|
49
|
+
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
50
|
+
}
|
|
51
|
+
if (credentialIdentifier) {
|
|
52
|
+
builder.withCredentialIdentifier(credentialIdentifier);
|
|
53
|
+
}
|
|
54
|
+
if (credentialTypes) {
|
|
55
|
+
builder.withCredentialType(credentialTypes);
|
|
56
|
+
}
|
|
57
|
+
return builder;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilderV1_0_13> {
|
|
61
|
+
const offer = await CredentialOfferClient.fromURI(uri);
|
|
62
|
+
return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public static fromCredentialOfferRequest(opts: {
|
|
66
|
+
request: UniformCredentialOfferRequest;
|
|
67
|
+
scheme?: string;
|
|
68
|
+
baseUrl?: string;
|
|
69
|
+
version?: OpenId4VCIVersion;
|
|
70
|
+
metadata?: EndpointMetadata;
|
|
71
|
+
}): CredentialRequestClientBuilderV1_0_13 {
|
|
72
|
+
const { request, metadata } = opts;
|
|
73
|
+
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
|
|
74
|
+
if (version < OpenId4VCIVersion.VER_1_0_13) {
|
|
75
|
+
throw new Error('Versions below v1.0.13 (draft 13) are not supported.');
|
|
76
|
+
}
|
|
77
|
+
const builder = new CredentialRequestClientBuilderV1_0_13();
|
|
78
|
+
const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
|
|
79
|
+
builder.withVersion(version);
|
|
80
|
+
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
81
|
+
if (metadata?.deferred_credential_endpoint) {
|
|
82
|
+
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
83
|
+
}
|
|
84
|
+
const ids: string[] = (request.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids;
|
|
85
|
+
// if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
|
|
86
|
+
if (ids.length && ids.length === 1) {
|
|
87
|
+
builder.withCredentialIdentifier(ids[0]);
|
|
88
|
+
}
|
|
89
|
+
return builder;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public static fromCredentialOffer({
|
|
93
|
+
credentialOffer,
|
|
94
|
+
metadata,
|
|
95
|
+
}: {
|
|
96
|
+
credentialOffer: CredentialOfferRequestWithBaseUrl;
|
|
97
|
+
metadata?: EndpointMetadata;
|
|
98
|
+
}): CredentialRequestClientBuilderV1_0_13 {
|
|
99
|
+
return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
|
|
100
|
+
request: credentialOffer,
|
|
101
|
+
metadata,
|
|
102
|
+
version: credentialOffer.version,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
107
|
+
this.credentialEndpoint = metadata.credential_endpoint;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public withCredentialEndpoint(credentialEndpoint: string): this {
|
|
112
|
+
this.credentialEndpoint = credentialEndpoint;
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
117
|
+
this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
|
|
122
|
+
this.deferredCredentialEndpoint = deferredCredentialEndpoint;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
|
|
127
|
+
this.deferredCredentialAwait = deferredCredentialAwait;
|
|
128
|
+
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public withCredentialIdentifier(credentialIdentifier: string): this {
|
|
133
|
+
this.credentialIdentifier = credentialIdentifier;
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public withCredentialType(credentialTypes: string | string[]): this {
|
|
138
|
+
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
|
|
143
|
+
this.format = format;
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
|
|
148
|
+
this.subjectIssuance = subjectIssuance;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public withToken(accessToken: string): this {
|
|
153
|
+
this.token = accessToken;
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public withTokenFromResponse(response: AccessTokenResponse): this {
|
|
158
|
+
this.token = response.access_token;
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public withVersion(version: OpenId4VCIVersion): this {
|
|
163
|
+
this.version = version;
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public build(): CredentialRequestClient {
|
|
168
|
+
if (!this.version) {
|
|
169
|
+
this.withVersion(OpenId4VCIVersion.VER_1_0_11);
|
|
170
|
+
}
|
|
171
|
+
return new CredentialRequestClient(this);
|
|
172
|
+
}
|
|
173
|
+
}
|
package/lib/OpenID4VCIClient.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Alg,
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationResponse,
|
|
6
|
+
AuthorizationServerOpts,
|
|
6
7
|
AuthzFlowType,
|
|
7
8
|
CodeChallengeMethod,
|
|
8
9
|
CredentialConfigurationSupported,
|
|
@@ -41,7 +42,7 @@ import { createAuthorizationRequestUrl } from './AuthorizationCodeClient';
|
|
|
41
42
|
import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
|
|
42
43
|
import { CredentialOfferClient } from './CredentialOfferClient';
|
|
43
44
|
import { CredentialRequestOpts } from './CredentialRequestClient';
|
|
44
|
-
import {
|
|
45
|
+
import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
|
|
45
46
|
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
|
|
46
47
|
import { MetadataClient } from './MetadataClient';
|
|
47
48
|
import { OpenID4VCIClientStateV1_0_11 } from './OpenID4VCIClientV1_0_11';
|
|
@@ -273,8 +274,10 @@ export class OpenID4VCIClient {
|
|
|
273
274
|
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
274
275
|
code?: string; // Directly pass in a code from an auth response
|
|
275
276
|
redirectUri?: string;
|
|
277
|
+
additionalRequestParams?: Record<string, any>;
|
|
278
|
+
asOpts?: AuthorizationServerOpts;
|
|
276
279
|
}): Promise<AccessTokenResponse> {
|
|
277
|
-
const { pin, clientId } = opts ?? {};
|
|
280
|
+
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
|
|
278
281
|
let { redirectUri } = opts ?? {};
|
|
279
282
|
if (opts?.authorizationResponse) {
|
|
280
283
|
this._state.authorizationCodeResponse = { ...toAuthorizationResponsePayload(opts.authorizationResponse) };
|
|
@@ -288,6 +291,23 @@ export class OpenID4VCIClient {
|
|
|
288
291
|
}
|
|
289
292
|
this.assertIssuerData();
|
|
290
293
|
|
|
294
|
+
const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
|
|
295
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
296
|
+
const clientAssertionType =
|
|
297
|
+
asOpts.clientOpts?.clientAssertionType ??
|
|
298
|
+
(kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
|
|
299
|
+
? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
300
|
+
: undefined);
|
|
301
|
+
if (clientId) {
|
|
302
|
+
asOpts.clientOpts = {
|
|
303
|
+
...asOpts.clientOpts,
|
|
304
|
+
clientId,
|
|
305
|
+
...(kid && { kid }),
|
|
306
|
+
...(clientAssertionType && { clientAssertionType }),
|
|
307
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
291
311
|
if (clientId) {
|
|
292
312
|
this._state.clientId = clientId;
|
|
293
313
|
}
|
|
@@ -311,7 +331,8 @@ export class OpenID4VCIClient {
|
|
|
311
331
|
...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
|
|
312
332
|
code,
|
|
313
333
|
redirectUri,
|
|
314
|
-
asOpts
|
|
334
|
+
asOpts,
|
|
335
|
+
...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
|
|
315
336
|
});
|
|
316
337
|
|
|
317
338
|
if (response.errorBody) {
|
|
@@ -368,7 +389,7 @@ export class OpenID4VCIClient {
|
|
|
368
389
|
if (jwk) this._state.jwk = jwk;
|
|
369
390
|
if (kid) this._state.kid = kid;
|
|
370
391
|
|
|
371
|
-
let requestBuilder:
|
|
392
|
+
let requestBuilder: CredentialRequestClientBuilderV1_0_13 | CredentialRequestClientBuilderV1_0_11;
|
|
372
393
|
if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
|
|
373
394
|
requestBuilder = this.credentialOffer
|
|
374
395
|
? CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
|
|
@@ -383,11 +404,11 @@ export class OpenID4VCIClient {
|
|
|
383
404
|
});
|
|
384
405
|
} else {
|
|
385
406
|
requestBuilder = this.credentialOffer
|
|
386
|
-
?
|
|
407
|
+
? CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
|
|
387
408
|
credentialOffer: this.credentialOffer,
|
|
388
409
|
metadata: this.endpointMetadata,
|
|
389
410
|
})
|
|
390
|
-
:
|
|
411
|
+
: CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
|
|
391
412
|
credentialIssuer: this.getIssuer(),
|
|
392
413
|
credentialTypes,
|
|
393
414
|
metadata: this.endpointMetadata,
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Alg,
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationResponse,
|
|
6
|
+
AuthorizationServerOpts,
|
|
6
7
|
AuthzFlowType,
|
|
7
8
|
CodeChallengeMethod,
|
|
8
9
|
CredentialConfigurationSupported,
|
|
@@ -259,6 +260,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
259
260
|
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
260
261
|
code?: string; // Directly pass in a code from an auth response
|
|
261
262
|
redirectUri?: string;
|
|
263
|
+
asOpts?: AuthorizationServerOpts;
|
|
262
264
|
}): Promise<AccessTokenResponse> {
|
|
263
265
|
const { pin, clientId } = opts ?? {};
|
|
264
266
|
let { redirectUri } = opts ?? {};
|
|
@@ -288,6 +290,22 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
288
290
|
if (this._state.authorizationRequestOpts?.redirectUri && !redirectUri) {
|
|
289
291
|
redirectUri = this._state.authorizationRequestOpts.redirectUri;
|
|
290
292
|
}
|
|
293
|
+
const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
|
|
294
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
295
|
+
const clientAssertionType =
|
|
296
|
+
asOpts.clientOpts?.clientAssertionType ??
|
|
297
|
+
(kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
|
|
298
|
+
? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
299
|
+
: undefined);
|
|
300
|
+
if (clientId) {
|
|
301
|
+
asOpts.clientOpts = {
|
|
302
|
+
...asOpts.clientOpts,
|
|
303
|
+
clientId,
|
|
304
|
+
...(kid && { kid }),
|
|
305
|
+
...(clientAssertionType && { clientAssertionType }),
|
|
306
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
291
309
|
|
|
292
310
|
const response = await accessTokenClient.acquireAccessToken({
|
|
293
311
|
credentialOffer: this.credentialOffer,
|
|
@@ -297,7 +315,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
297
315
|
...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
|
|
298
316
|
code,
|
|
299
317
|
redirectUri,
|
|
300
|
-
asOpts
|
|
318
|
+
asOpts,
|
|
301
319
|
});
|
|
302
320
|
|
|
303
321
|
if (response.errorBody) {
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Alg,
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationResponse,
|
|
6
|
+
AuthorizationServerOpts,
|
|
6
7
|
AuthzFlowType,
|
|
7
8
|
CodeChallengeMethod,
|
|
8
9
|
CredentialConfigurationSupportedV1_0_13,
|
|
@@ -265,6 +266,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
265
266
|
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
266
267
|
code?: string; // Directly pass in a code from an auth response
|
|
267
268
|
redirectUri?: string;
|
|
269
|
+
asOpts?: AuthorizationServerOpts;
|
|
268
270
|
}): Promise<AccessTokenResponse> {
|
|
269
271
|
const { pin, clientId } = opts ?? {};
|
|
270
272
|
let { redirectUri } = opts ?? {};
|
|
@@ -279,6 +281,22 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
279
281
|
this._state.pkce.codeVerifier = opts.codeVerifier;
|
|
280
282
|
}
|
|
281
283
|
this.assertIssuerData();
|
|
284
|
+
const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
|
|
285
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
286
|
+
const clientAssertionType =
|
|
287
|
+
asOpts.clientOpts?.clientAssertionType ??
|
|
288
|
+
(kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
|
|
289
|
+
? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
290
|
+
: undefined);
|
|
291
|
+
if (clientId) {
|
|
292
|
+
asOpts.clientOpts = {
|
|
293
|
+
...asOpts.clientOpts,
|
|
294
|
+
clientId,
|
|
295
|
+
...(kid && { kid }),
|
|
296
|
+
...(clientAssertionType && { clientAssertionType }),
|
|
297
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
282
300
|
|
|
283
301
|
if (clientId) {
|
|
284
302
|
this._state.clientId = clientId;
|
|
@@ -302,7 +320,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
302
320
|
...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
|
|
303
321
|
code,
|
|
304
322
|
redirectUri,
|
|
305
|
-
asOpts
|
|
323
|
+
asOpts,
|
|
306
324
|
});
|
|
307
325
|
|
|
308
326
|
if (response.errorBody) {
|
|
@@ -20,13 +20,8 @@ import * as jose from 'jose';
|
|
|
20
20
|
// @ts-ignore
|
|
21
21
|
import nock from 'nock';
|
|
22
22
|
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
CredentialRequestClientBuilder,
|
|
26
|
-
CredentialRequestClientBuilderV1_0_11,
|
|
27
|
-
MetadataClientV1_0_11,
|
|
28
|
-
ProofOfPossessionBuilder,
|
|
29
|
-
} from '..';
|
|
23
|
+
import { CredentialOfferClient, MetadataClient, ProofOfPossessionBuilder } from '..';
|
|
24
|
+
import { CredentialRequestClientBuilder } from '../CredentialRequestClientBuilder';
|
|
30
25
|
|
|
31
26
|
import { IDENTIPROOF_ISSUER_URL, IDENTIPROOF_OID4VCI_METADATA, INITIATION_TEST, WALT_OID4VCI_METADATA } from './MetadataMocks';
|
|
32
27
|
import { getMockData } from './data/VciDataFixtures';
|
|
@@ -154,14 +149,14 @@ describe('Credential Request Client with Walt.id ', () => {
|
|
|
154
149
|
nock.cleanAll();
|
|
155
150
|
const WALT_IRR_URI =
|
|
156
151
|
'openid-initiate-issuance://?issuer=https%3A%2F%2Fjff.walt.id%2Fissuer-api%2Foidc%2F&credential_type=OpenBadgeCredential&pre-authorized_code=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhOTUyZjUxNi1jYWVmLTQ4YjMtODIxYy00OTRkYzgyNjljZjAiLCJwcmUtYXV0aG9yaXplZCI6dHJ1ZX0.YE5DlalcLC2ChGEg47CQDaN1gTxbaQqSclIVqsSAUHE&user_pin_required=false';
|
|
157
|
-
const credentialOffer = await
|
|
152
|
+
const credentialOffer = await CredentialOfferClient.fromURI(WALT_IRR_URI);
|
|
158
153
|
|
|
159
154
|
const request = credentialOffer.credential_offer;
|
|
160
|
-
const metadata = await
|
|
155
|
+
const metadata = await MetadataClient.retrieveAllMetadata(getIssuerFromCredentialOfferPayload(request) as string);
|
|
161
156
|
expect(metadata.credential_endpoint).toEqual(WALT_OID4VCI_METADATA.credential_endpoint);
|
|
162
157
|
expect(metadata.token_endpoint).toEqual(WALT_OID4VCI_METADATA.token_endpoint);
|
|
163
158
|
|
|
164
|
-
const credReqClient =
|
|
159
|
+
const credReqClient = CredentialRequestClientBuilder.fromCredentialOffer({
|
|
165
160
|
credentialOffer,
|
|
166
161
|
metadata,
|
|
167
162
|
}).build();
|
|
@@ -205,7 +200,7 @@ describe('Credential Request Client with different issuers ', () => {
|
|
|
205
200
|
const IRR_URI =
|
|
206
201
|
'openid-initiate-issuance://?issuer=https%3A%2F%2Fjff.walt.id%2Fissuer-api%2Fdefault%2Foidc%2F&credential_type=OpenBadgeCredential&pre-authorized_code=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwMTc4OTNjYy04ZTY3LTQxNzItYWZlOS1lODcyYmYxNDBlNWMiLCJwcmUtYXV0aG9yaXplZCI6dHJ1ZX0.ODfq2AIhOcB61dAb3zMrXBJjPJaf53zkeHh_AssYyYA&user_pin_required=false';
|
|
207
202
|
const credentialOffer = await (
|
|
208
|
-
await
|
|
203
|
+
await CredentialRequestClientBuilder.fromURI({
|
|
209
204
|
uri: IRR_URI,
|
|
210
205
|
metadata: getMockData('walt')?.metadata as unknown as EndpointMetadata,
|
|
211
206
|
})
|
|
@@ -250,7 +245,7 @@ describe('Credential Request Client with different issuers ', () => {
|
|
|
250
245
|
const IRR_URI =
|
|
251
246
|
'openid-initiate-issuance://?issuer=https://launchpad.mattrlabs.com&credential_type=OpenBadgeCredential&pre-authorized_code=g0UCOj6RAN5AwHU6gczm_GzB4_lH6GW39Z0Dl2DOOiO';
|
|
252
247
|
const credentialOffer = await (
|
|
253
|
-
await
|
|
248
|
+
await CredentialRequestClientBuilder.fromURI({
|
|
254
249
|
uri: IRR_URI,
|
|
255
250
|
metadata: getMockData('mattr')?.metadata as unknown as EndpointMetadata,
|
|
256
251
|
})
|
|
@@ -273,7 +268,7 @@ describe('Credential Request Client with different issuers ', () => {
|
|
|
273
268
|
const IRR_URI =
|
|
274
269
|
'openid-initiate-issuance://?issuer=https://oidc4vc.diwala.io&credential_type=OpenBadgeCredential&pre-authorized_code=eyJhbGciOiJIUzI1NiJ9.eyJjcmVkZW50aWFsX3R5cGUiOiJPcGVuQmFkZ2VDcmVkZW50aWFsIiwiZXhwIjoxNjgxOTg0NDY3fQ.fEAHKz2nuWfiYHw406iNxr-81pWkNkbi31bWsYSf6Ng';
|
|
275
270
|
const credentialOffer = await (
|
|
276
|
-
await
|
|
271
|
+
await CredentialRequestClientBuilder.fromURI({
|
|
277
272
|
uri: IRR_URI,
|
|
278
273
|
metadata: getMockData('diwala')?.metadata as unknown as EndpointMetadata,
|
|
279
274
|
})
|
|
@@ -11,11 +11,13 @@ import {
|
|
|
11
11
|
} from '@sphereon/oid4vci-common';
|
|
12
12
|
import * as jose from 'jose';
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { CredentialRequestOpts, ProofOfPossessionBuilder } from '..';
|
|
15
|
+
import { CredentialRequestClientBuilder } from '../CredentialRequestClientBuilder';
|
|
15
16
|
|
|
16
17
|
import { IDENTIPROOF_ISSUER_URL, IDENTIPROOF_OID4VCI_METADATA, INITIATION_TEST_URI, WALT_ISSUER_URL, WALT_OID4VCI_METADATA } from './MetadataMocks';
|
|
17
18
|
|
|
18
19
|
const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN';
|
|
20
|
+
const partialJWT_withoutDid = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJlYmZlYjFmNzEyZWJjNmYxYzI3N';
|
|
19
21
|
|
|
20
22
|
/*const jwtv1_0_08: Jwt = {
|
|
21
23
|
header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
|
|
@@ -27,8 +29,15 @@ const jwtv1_0_11: Jwt = {
|
|
|
27
29
|
payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
|
|
28
30
|
};
|
|
29
31
|
|
|
32
|
+
const jwtv1_0_13_withoutDid: Jwt = {
|
|
33
|
+
header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'openid4vci-proof+jwt' },
|
|
34
|
+
payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
|
|
35
|
+
};
|
|
36
|
+
|
|
30
37
|
const kid = 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1';
|
|
31
38
|
|
|
39
|
+
const kid_withoutDid = 'ebfeb1f712ebc6f1c276e12ec21/keys/1';
|
|
40
|
+
|
|
32
41
|
let keypair: KeyPair;
|
|
33
42
|
|
|
34
43
|
beforeAll(async () => {
|
|
@@ -81,7 +90,7 @@ describe('Credential Request Client Builder', () => {
|
|
|
81
90
|
.build();
|
|
82
91
|
expect(credReqClient.credentialRequestOpts.credentialEndpoint).toBe('https://oidc4vci.demo.spruceid.com/credential');
|
|
83
92
|
expect(credReqClient.credentialRequestOpts.format).toBe('jwt_vc');
|
|
84
|
-
expect(credReqClient.credentialRequestOpts.credentialIdentifier).toStrictEqual('credentialType');
|
|
93
|
+
expect((credReqClient.credentialRequestOpts as CredentialRequestOpts).credentialIdentifier).toStrictEqual('credentialType');
|
|
85
94
|
expect(credReqClient.credentialRequestOpts.token).toBe('token');
|
|
86
95
|
});
|
|
87
96
|
|
|
@@ -115,6 +124,35 @@ describe('Credential Request Client Builder', () => {
|
|
|
115
124
|
}
|
|
116
125
|
});
|
|
117
126
|
|
|
127
|
+
it('should build credential request correctly without did', async () => {
|
|
128
|
+
const credReqClient = (await CredentialRequestClientBuilder.fromURI({ uri: INITIATION_TEST_URI }))
|
|
129
|
+
.withCredentialEndpoint('https://oidc4vci.demo.spruceid.com/credential')
|
|
130
|
+
.withFormat('jwt_vc')
|
|
131
|
+
.withCredentialType('OpenBadgeCredential')
|
|
132
|
+
.build();
|
|
133
|
+
const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
|
|
134
|
+
jwt: jwtv1_0_13_withoutDid,
|
|
135
|
+
callbacks: {
|
|
136
|
+
signCallback: proofOfPossessionCallbackFunction,
|
|
137
|
+
verifyCallback: proofOfPossessionVerifierCallbackFunction,
|
|
138
|
+
},
|
|
139
|
+
version: OpenId4VCIVersion.VER_1_0_13,
|
|
140
|
+
})
|
|
141
|
+
.withClientId('sphereon:wallet')
|
|
142
|
+
.withKid(kid_withoutDid)
|
|
143
|
+
.build();
|
|
144
|
+
await proofOfPossessionVerifierCallbackFunction({ ...proof, kid: kid_withoutDid });
|
|
145
|
+
const credentialRequest: CredentialRequestV1_0_13 = await credReqClient.createCredentialRequest({
|
|
146
|
+
proofInput: proof,
|
|
147
|
+
credentialTypes: 'OpenBadgeCredential',
|
|
148
|
+
version: OpenId4VCIVersion.VER_1_0_13,
|
|
149
|
+
});
|
|
150
|
+
expect(credentialRequest.proof?.jwt).toContain(partialJWT_withoutDid);
|
|
151
|
+
if ('types' in credentialRequest) {
|
|
152
|
+
expect(credentialRequest.types).toStrictEqual(['OpenBadgeCredential']);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
118
156
|
it('should build correctly from metadata', async () => {
|
|
119
157
|
const credReqClient = (
|
|
120
158
|
await CredentialRequestClientBuilder.fromURI({
|
|
@@ -28,14 +28,22 @@ import {
|
|
|
28
28
|
import { getMockData } from './data/VciDataFixtures';
|
|
29
29
|
|
|
30
30
|
const partialJWT = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmN';
|
|
31
|
+
const partialJWT_withoutDid = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJlYmZlYjFmNzEyZWJjNmYxYzI3N';
|
|
31
32
|
|
|
32
33
|
const jwt: Jwt = {
|
|
33
34
|
header: { alg: Alg.ES256, kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
|
|
34
35
|
payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
|
|
35
36
|
};
|
|
36
37
|
|
|
38
|
+
const jwt_withoutDid: Jwt = {
|
|
39
|
+
header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
|
|
40
|
+
payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL },
|
|
41
|
+
};
|
|
42
|
+
|
|
37
43
|
const kid = 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1';
|
|
38
44
|
|
|
45
|
+
const kid_withoutDid = 'ebfeb1f712ebc6f1c276e12ec21/keys/1';
|
|
46
|
+
|
|
39
47
|
let keypair: KeyPair;
|
|
40
48
|
|
|
41
49
|
async function proofOfPossessionCallbackFunction(args: Jwt, kid?: string): Promise<string> {
|
|
@@ -102,6 +110,36 @@ describe('Credential Request Client ', () => {
|
|
|
102
110
|
expect(result?.errorBody?.error).toBe('unsupported_format');
|
|
103
111
|
});
|
|
104
112
|
|
|
113
|
+
it('should get a failed credential response with an unsupported format and without did', async function () {
|
|
114
|
+
const basePath = 'https://sphereonjunit2022101301.com/';
|
|
115
|
+
nock(basePath).post(/.*/).reply(500, {
|
|
116
|
+
error: 'unsupported_format',
|
|
117
|
+
error_description: 'This is a mock error message',
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({ credentialOffer: INITIATION_TEST_V1_0_08 })
|
|
121
|
+
.withCredentialEndpoint(basePath + '/credential')
|
|
122
|
+
.withFormat('ldp_vc')
|
|
123
|
+
.withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential')
|
|
124
|
+
.build();
|
|
125
|
+
const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
|
|
126
|
+
jwt: jwt_withoutDid,
|
|
127
|
+
callbacks: {
|
|
128
|
+
signCallback: proofOfPossessionCallbackFunction,
|
|
129
|
+
},
|
|
130
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
131
|
+
})
|
|
132
|
+
// .withEndpointMetadata(metadata)
|
|
133
|
+
.withClientId('sphereon:wallet')
|
|
134
|
+
.withKid(kid_withoutDid)
|
|
135
|
+
.build();
|
|
136
|
+
expect(credReqClient.getCredentialEndpoint()).toEqual(basePath + '/credential');
|
|
137
|
+
const credentialRequest = await credReqClient.createCredentialRequest({ proofInput: proof, version: OpenId4VCIVersion.VER_1_0_08 });
|
|
138
|
+
expect(credentialRequest.proof?.jwt?.includes(partialJWT_withoutDid)).toBeTruthy();
|
|
139
|
+
const result = await credReqClient.acquireCredentialsUsingRequest(credentialRequest);
|
|
140
|
+
expect(result?.errorBody?.error).toBe('unsupported_format');
|
|
141
|
+
});
|
|
142
|
+
|
|
105
143
|
it('should get success credential response', async function () {
|
|
106
144
|
const mockedVC =
|
|
107
145
|
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImlkIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXSwiaXNzdWVyIjoiaHR0cHM6Ly9leGFtcGxlLmVkdS9pc3N1ZXJzLzU2NTA0OSIsImlzc3VhbmNlRGF0ZSI6IjIwMTAtMDEtMDFUMDA6MDA6MDBaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJkZWdyZWUiOnsidHlwZSI6IkJhY2hlbG9yRGVncmVlIiwibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMifX19LCJpc3MiOiJodHRwczovL2V4YW1wbGUuZWR1L2lzc3VlcnMvNTY1MDQ5IiwibmJmIjoxMjYyMzA0MDAwLCJqdGkiOiJodHRwOi8vZXhhbXBsZS5lZHUvY3JlZGVudGlhbHMvMzczMiIsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSJ9.z5vgMTK1nfizNCg5N-niCOL3WUIAL7nXy-nGhDZYO_-PNGeE-0djCpWAMH8fD8eWSID5PfkPBYkx_dfLJnQ7NA';
|
|
@@ -138,6 +176,42 @@ describe('Credential Request Client ', () => {
|
|
|
138
176
|
expect(result?.successBody?.credential).toEqual(mockedVC);
|
|
139
177
|
});
|
|
140
178
|
|
|
179
|
+
it('should get success credential response without did', async function () {
|
|
180
|
+
const mockedVC =
|
|
181
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIl0sImlkIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXSwiaXNzdWVyIjoiaHR0cHM6Ly9leGFtcGxlLmVkdS9pc3N1ZXJzLzU2NTA0OSIsImlzc3VhbmNlRGF0ZSI6IjIwMTAtMDEtMDFUMDA6MDA6MDBaIiwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJlYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJkZWdyZWUiOnsidHlwZSI6IkJhY2hlbG9yRGVncmVlIiwibmFtZSI6IkJhY2hlbG9yIG9mIFNjaWVuY2UgYW5kIEFydHMifX19LCJpc3MiOiJodHRwczovL2V4YW1wbGUuZWR1L2lzc3VlcnMvNTY1MDQ5IiwibmJmIjoxMjYyMzA0MDAwLCJqdGkiOiJodHRwOi8vZXhhbXBsZS5lZHUvY3JlZGVudGlhbHMvMzczMiIsInN1YiI6ImViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsImlhdCI6MTcxODM1NzcxOH0.7iiOTuIjQRyrIincYyDW6m0nBYmDoYfXcTYFrywsKEY';
|
|
182
|
+
nock('https://oidc4vci.demo.spruceid.com')
|
|
183
|
+
.post(/credential/)
|
|
184
|
+
.reply(200, {
|
|
185
|
+
format: 'jwt-vc',
|
|
186
|
+
credential: mockedVC,
|
|
187
|
+
});
|
|
188
|
+
const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest({ request: INITIATION_TEST })
|
|
189
|
+
.withCredentialEndpoint('https://oidc4vci.demo.spruceid.com/credential')
|
|
190
|
+
.withFormat('jwt_vc')
|
|
191
|
+
.withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential')
|
|
192
|
+
.build();
|
|
193
|
+
const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
|
|
194
|
+
jwt: jwt_withoutDid,
|
|
195
|
+
callbacks: {
|
|
196
|
+
signCallback: proofOfPossessionCallbackFunction,
|
|
197
|
+
},
|
|
198
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
199
|
+
})
|
|
200
|
+
// .withEndpointMetadata(metadata)
|
|
201
|
+
.withKid(kid_withoutDid)
|
|
202
|
+
.withClientId('sphereon:wallet')
|
|
203
|
+
.build();
|
|
204
|
+
const credentialRequest = await credReqClient.createCredentialRequest({
|
|
205
|
+
proofInput: proof,
|
|
206
|
+
format: 'jwt',
|
|
207
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
208
|
+
});
|
|
209
|
+
expect(credentialRequest.proof?.jwt?.includes(partialJWT_withoutDid)).toBeTruthy();
|
|
210
|
+
expect(credentialRequest.format).toEqual('jwt_vc');
|
|
211
|
+
const result = await credReqClient.acquireCredentialsUsingRequest(credentialRequest);
|
|
212
|
+
expect(result?.successBody?.credential).toEqual(mockedVC);
|
|
213
|
+
});
|
|
214
|
+
|
|
141
215
|
it('should fail with invalid url', async () => {
|
|
142
216
|
const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest({ request: INITIATION_TEST })
|
|
143
217
|
.withCredentialEndpoint('httpsf://oidc4vci.demo.spruceid.com/credential')
|
|
@@ -159,6 +233,28 @@ describe('Credential Request Client ', () => {
|
|
|
159
233
|
Error(URL_NOT_VALID),
|
|
160
234
|
);
|
|
161
235
|
});
|
|
236
|
+
|
|
237
|
+
it('should fail with invalid url without did', async () => {
|
|
238
|
+
const credReqClient = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest({ request: INITIATION_TEST })
|
|
239
|
+
.withCredentialEndpoint('httpsf://oidc4vci.demo.spruceid.com/credential')
|
|
240
|
+
.withFormat('jwt_vc')
|
|
241
|
+
.withCredentialType('https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#OpenBadgeCredential')
|
|
242
|
+
.build();
|
|
243
|
+
const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
|
|
244
|
+
jwt: jwt_withoutDid,
|
|
245
|
+
callbacks: {
|
|
246
|
+
signCallback: proofOfPossessionCallbackFunction,
|
|
247
|
+
},
|
|
248
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
249
|
+
})
|
|
250
|
+
// .withEndpointMetadata(metadata)
|
|
251
|
+
.withKid(kid_withoutDid)
|
|
252
|
+
.withClientId('sphereon:wallet')
|
|
253
|
+
.build();
|
|
254
|
+
await expect(credReqClient.acquireCredentialsUsingRequest({ format: 'jwt_vc_json', types: ['random'], proof })).rejects.toThrow(
|
|
255
|
+
Error(URL_NOT_VALID),
|
|
256
|
+
);
|
|
257
|
+
});
|
|
162
258
|
});
|
|
163
259
|
|
|
164
260
|
describe('Credential Request Client with Walt.id ', () => {
|