@sphereon/oid4vci-client 0.19.1-next.2 → 0.19.1-next.220
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/index.cjs +961 -2390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -417
- package/dist/index.d.ts +128 -417
- package/dist/index.js +940 -2379
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -9,10 +9,6 @@ import { createDPoP, getCreateDPoPOptions } from "@sphereon/oid4vc-common";
|
|
|
9
9
|
import { assertedUniformCredentialOffer, AuthzFlowType, convertJsonToURI, formPost, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload2, GrantTypes, JsonURIMode, PRE_AUTH_CODE_LITERAL as PRE_AUTH_CODE_LITERAL2, PRE_AUTH_GRANT_LITERAL as PRE_AUTH_GRANT_LITERAL2, TokenErrorResponse, toUniformCredentialOfferRequest } from "@sphereon/oid4vci-common";
|
|
10
10
|
import { ObjectUtils } from "@sphereon/ssi-types";
|
|
11
11
|
|
|
12
|
-
// lib/MetadataClientV1_0_13.ts
|
|
13
|
-
import { getIssuerFromCredentialOfferPayload, WellKnownEndpoints } from "@sphereon/oid4vci-common";
|
|
14
|
-
import { Loggers as Loggers2 } from "@sphereon/ssi-types";
|
|
15
|
-
|
|
16
12
|
// lib/functions/AuthorizationUtil.ts
|
|
17
13
|
import { assertValidCodeVerifier, CodeChallengeMethod, createCodeChallenge, generateCodeVerifier } from "@sphereon/oid4vci-common";
|
|
18
14
|
var generateMissingPKCEOpts = /* @__PURE__ */ __name((pkce) => {
|
|
@@ -87,17 +83,17 @@ var retrieveWellknown = /* @__PURE__ */ __name(async (host, endpointType, opts)
|
|
|
87
83
|
|
|
88
84
|
// lib/functions/AccessTokenUtil.ts
|
|
89
85
|
import { uuidv4 } from "@sphereon/oid4vc-common";
|
|
90
|
-
import { OpenId4VCIVersion
|
|
86
|
+
import { OpenId4VCIVersion } from "@sphereon/oid4vci-common";
|
|
91
87
|
|
|
92
88
|
// lib/ProofOfPossessionBuilder.ts
|
|
93
|
-
import { createProofOfPossession, NO_JWT_PROVIDED,
|
|
89
|
+
import { createProofOfPossession, NO_JWT_PROVIDED, PROOF_CANT_BE_CONSTRUCTED } from "@sphereon/oid4vci-common";
|
|
94
90
|
var ProofOfPossessionBuilder = class _ProofOfPossessionBuilder {
|
|
95
91
|
static {
|
|
96
92
|
__name(this, "ProofOfPossessionBuilder");
|
|
97
93
|
}
|
|
98
94
|
proof;
|
|
99
95
|
callbacks;
|
|
100
|
-
version
|
|
96
|
+
// private readonly version: OpenId4VCIVersion
|
|
101
97
|
mode = "pop";
|
|
102
98
|
kid;
|
|
103
99
|
jwk;
|
|
@@ -113,11 +109,10 @@ var ProofOfPossessionBuilder = class _ProofOfPossessionBuilder {
|
|
|
113
109
|
this.mode = mode;
|
|
114
110
|
this.proof = proof;
|
|
115
111
|
this.callbacks = callbacks;
|
|
116
|
-
this.version = version;
|
|
117
112
|
if (jwt) {
|
|
118
113
|
this.withJwt(jwt);
|
|
119
114
|
} else {
|
|
120
|
-
this.withTyp(
|
|
115
|
+
this.withTyp(mode === "JWT" ? "JWT" : "openid4vci-proof+jwt");
|
|
121
116
|
}
|
|
122
117
|
if (accessTokenResponse) {
|
|
123
118
|
this.withAccessTokenResponse(accessTokenResponse);
|
|
@@ -182,7 +177,7 @@ var ProofOfPossessionBuilder = class _ProofOfPossessionBuilder {
|
|
|
182
177
|
return this;
|
|
183
178
|
}
|
|
184
179
|
withTyp(typ) {
|
|
185
|
-
if (this.mode === "pop"
|
|
180
|
+
if (this.mode === "pop") {
|
|
186
181
|
if (!!typ && typ !== "openid4vci-proof+jwt") {
|
|
187
182
|
throw Error(`typ must be openid4vci-proof+jwt for version 1.0.11 and up. Provided: ${typ}`);
|
|
188
183
|
}
|
|
@@ -224,7 +219,7 @@ var ProofOfPossessionBuilder = class _ProofOfPossessionBuilder {
|
|
|
224
219
|
if (jwt.header.typ) {
|
|
225
220
|
this.withTyp(jwt.header.typ);
|
|
226
221
|
}
|
|
227
|
-
if (!this.typ
|
|
222
|
+
if (!this.typ) {
|
|
228
223
|
this.withTyp("openid4vci-proof+jwt");
|
|
229
224
|
}
|
|
230
225
|
this.withAlg(jwt.header.alg);
|
|
@@ -244,7 +239,7 @@ var ProofOfPossessionBuilder = class _ProofOfPossessionBuilder {
|
|
|
244
239
|
return Promise.resolve(this.proof);
|
|
245
240
|
} else if (this.callbacks) {
|
|
246
241
|
return await createProofOfPossession(this.mode, this.callbacks, {
|
|
247
|
-
typ: this.typ ?? (this.
|
|
242
|
+
typ: this.typ ?? (this.mode === "JWT" ? "JWT" : "openid4vci-proof+jwt"),
|
|
248
243
|
kid: this.kid,
|
|
249
244
|
jwk: this.jwk,
|
|
250
245
|
jti: this.jti,
|
|
@@ -297,7 +292,7 @@ var createJwtBearerClientAssertion = /* @__PURE__ */ __name(async (request, opts
|
|
|
297
292
|
const pop = await ProofOfPossessionBuilder.fromJwt({
|
|
298
293
|
jwt,
|
|
299
294
|
callbacks: signCallbacks,
|
|
300
|
-
version: opts.version ??
|
|
295
|
+
version: opts.version ?? OpenId4VCIVersion.VER_1_0_15,
|
|
301
296
|
mode: "JWT"
|
|
302
297
|
}).build();
|
|
303
298
|
request.client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
@@ -307,7 +302,7 @@ var createJwtBearerClientAssertion = /* @__PURE__ */ __name(async (request, opts
|
|
|
307
302
|
|
|
308
303
|
// lib/functions/CredentialOfferCommons.ts
|
|
309
304
|
import { decodeJsonProperties, getClientIdFromCredentialOfferPayload, getURIComponentsAsArray, PRE_AUTH_CODE_LITERAL, PRE_AUTH_GRANT_LITERAL } from "@sphereon/oid4vci-common";
|
|
310
|
-
import
|
|
305
|
+
import fetch from "cross-fetch";
|
|
311
306
|
function isUriEncoded(str) {
|
|
312
307
|
const pattern = /%[0-9A-F]{2}/i;
|
|
313
308
|
return pattern.test(str);
|
|
@@ -352,11 +347,54 @@ function constructBaseResponse(request, scheme, baseUrl) {
|
|
|
352
347
|
}
|
|
353
348
|
__name(constructBaseResponse, "constructBaseResponse");
|
|
354
349
|
|
|
355
|
-
// lib/
|
|
350
|
+
// lib/functions/dpopUtil.ts
|
|
351
|
+
import { dpopTokenRequestNonceError } from "@sphereon/oid4vc-common";
|
|
352
|
+
function shouldRetryTokenRequestWithDPoPNonce(response) {
|
|
353
|
+
if (!response.errorBody || response.errorBody.error !== dpopTokenRequestNonceError) {
|
|
354
|
+
return {
|
|
355
|
+
ok: false
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
const dPoPNonce = response.origResponse.headers.get("DPoP-Nonce");
|
|
359
|
+
if (!dPoPNonce) {
|
|
360
|
+
throw new Error("Missing required DPoP-Nonce header.");
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
ok: true,
|
|
364
|
+
dpopNonce: dPoPNonce
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
__name(shouldRetryTokenRequestWithDPoPNonce, "shouldRetryTokenRequestWithDPoPNonce");
|
|
368
|
+
function shouldRetryResourceRequestWithDPoPNonce(response) {
|
|
369
|
+
if (!response.errorBody || response.origResponse.status !== 401) {
|
|
370
|
+
return {
|
|
371
|
+
ok: false
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
const wwwAuthenticateHeader = response.origResponse.headers.get("WWW-Authenticate");
|
|
375
|
+
if (!wwwAuthenticateHeader?.includes(dpopTokenRequestNonceError)) {
|
|
376
|
+
return {
|
|
377
|
+
ok: false
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
const dPoPNonce = response.origResponse.headers.get("DPoP-Nonce");
|
|
381
|
+
if (!dPoPNonce) {
|
|
382
|
+
throw new Error("Missing required DPoP-Nonce header.");
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
ok: true,
|
|
386
|
+
dpopNonce: dPoPNonce
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
__name(shouldRetryResourceRequestWithDPoPNonce, "shouldRetryResourceRequestWithDPoPNonce");
|
|
390
|
+
|
|
391
|
+
// lib/MetadataClientV1_0_15.ts
|
|
392
|
+
import { getIssuerFromCredentialOfferPayload, WellKnownEndpoints } from "@sphereon/oid4vci-common";
|
|
393
|
+
import { Loggers as Loggers2 } from "@sphereon/ssi-types";
|
|
356
394
|
var logger2 = Loggers2.DEFAULT.get("sphereon:oid4vci:metadata");
|
|
357
|
-
var
|
|
395
|
+
var MetadataClientV1_0_15 = class _MetadataClientV1_0_15 {
|
|
358
396
|
static {
|
|
359
|
-
__name(this, "
|
|
397
|
+
__name(this, "MetadataClientV1_0_15");
|
|
360
398
|
}
|
|
361
399
|
/**
|
|
362
400
|
* Retrieve metadata using the Initiation obtained from a previous step
|
|
@@ -364,7 +402,7 @@ var MetadataClientV1_0_13 = class _MetadataClientV1_0_13 {
|
|
|
364
402
|
* @param credentialOffer
|
|
365
403
|
*/
|
|
366
404
|
static async retrieveAllMetadataFromCredentialOffer(credentialOffer) {
|
|
367
|
-
return
|
|
405
|
+
return _MetadataClientV1_0_15.retrieveAllMetadataFromCredentialOfferRequest(credentialOffer.credential_offer);
|
|
368
406
|
}
|
|
369
407
|
/**
|
|
370
408
|
* Retrieve the metada using the initiation request obtained from a previous step
|
|
@@ -373,7 +411,7 @@ var MetadataClientV1_0_13 = class _MetadataClientV1_0_13 {
|
|
|
373
411
|
static async retrieveAllMetadataFromCredentialOfferRequest(request) {
|
|
374
412
|
const issuer = getIssuerFromCredentialOfferPayload(request);
|
|
375
413
|
if (issuer) {
|
|
376
|
-
return
|
|
414
|
+
return _MetadataClientV1_0_15.retrieveAllMetadata(issuer);
|
|
377
415
|
}
|
|
378
416
|
throw new Error("can't retrieve metadata from CredentialOfferRequest. No issuer field is present");
|
|
379
417
|
}
|
|
@@ -385,6 +423,7 @@ var MetadataClientV1_0_13 = class _MetadataClientV1_0_13 {
|
|
|
385
423
|
static async retrieveAllMetadata(issuer, opts) {
|
|
386
424
|
let token_endpoint;
|
|
387
425
|
let credential_endpoint;
|
|
426
|
+
let nonce_endpoint;
|
|
388
427
|
let deferred_credential_endpoint;
|
|
389
428
|
let authorization_endpoint;
|
|
390
429
|
let authorization_challenge_endpoint;
|
|
@@ -392,7 +431,7 @@ var MetadataClientV1_0_13 = class _MetadataClientV1_0_13 {
|
|
|
392
431
|
let authorization_servers = [
|
|
393
432
|
issuer
|
|
394
433
|
];
|
|
395
|
-
const oid4vciResponse = await
|
|
434
|
+
const oid4vciResponse = await _MetadataClientV1_0_15.retrieveOpenID4VCIServerMetadata(issuer, {
|
|
396
435
|
errorOnNotFound: false
|
|
397
436
|
});
|
|
398
437
|
let credentialIssuerMetadata = oid4vciResponse?.successBody;
|
|
@@ -400,6 +439,7 @@ var MetadataClientV1_0_13 = class _MetadataClientV1_0_13 {
|
|
|
400
439
|
logger2.debug(`Issuer ${issuer} OID4VCI well-known server metadata\r
|
|
401
440
|
${JSON.stringify(credentialIssuerMetadata)}`);
|
|
402
441
|
credential_endpoint = credentialIssuerMetadata.credential_endpoint;
|
|
442
|
+
nonce_endpoint = credentialIssuerMetadata.nonce_endpoint;
|
|
403
443
|
deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint;
|
|
404
444
|
if (credentialIssuerMetadata.token_endpoint) {
|
|
405
445
|
token_endpoint = credentialIssuerMetadata.token_endpoint;
|
|
@@ -427,9 +467,6 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
427
467
|
throw Error(`Issuer ${issuer} provided a separate authorization server ${authorization_servers}, but that server did not provide metadata`);
|
|
428
468
|
}
|
|
429
469
|
} else {
|
|
430
|
-
if (!authorizationServerType) {
|
|
431
|
-
authorizationServerType = "OAuth 2.0";
|
|
432
|
-
}
|
|
433
470
|
logger2.debug(`Issuer ${issuer} has ${authorizationServerType} Server metadata in well-known location`);
|
|
434
471
|
if (!authMetadata.authorization_endpoint) {
|
|
435
472
|
console.warn(`Issuer ${issuer} of type ${authorizationServerType} has no authorization_endpoint! Will use ${authorization_endpoint}. This only works for pre-authorized flows`);
|
|
@@ -484,17 +521,29 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
484
521
|
if (!credentialIssuerMetadata && authMetadata) {
|
|
485
522
|
credentialIssuerMetadata = authMetadata;
|
|
486
523
|
}
|
|
524
|
+
const ci = credentialIssuerMetadata ?? {};
|
|
525
|
+
const ciAuthorizationServers = Array.isArray(ci.authorization_servers) && ci.authorization_servers.length > 0 ? ci.authorization_servers : authorization_servers;
|
|
526
|
+
const v15CredentialIssuerMetadata = {
|
|
527
|
+
credential_issuer: ci.credential_issuer ?? issuer,
|
|
528
|
+
credential_endpoint,
|
|
529
|
+
authorization_servers: ciAuthorizationServers,
|
|
530
|
+
credential_configurations_supported: ci.credential_configurations_supported ?? {},
|
|
531
|
+
display: ci.display ?? [],
|
|
532
|
+
...nonce_endpoint && {
|
|
533
|
+
nonce_endpoint
|
|
534
|
+
},
|
|
535
|
+
...deferred_credential_endpoint && {
|
|
536
|
+
deferred_credential_endpoint
|
|
537
|
+
}
|
|
538
|
+
};
|
|
487
539
|
logger2.debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
|
|
488
540
|
return {
|
|
489
541
|
issuer,
|
|
490
542
|
token_endpoint,
|
|
491
543
|
credential_endpoint,
|
|
492
|
-
deferred_credential_endpoint,
|
|
493
|
-
authorization_server: authorization_servers[0],
|
|
494
|
-
authorization_endpoint,
|
|
495
544
|
authorization_challenge_endpoint,
|
|
496
545
|
authorizationServerType,
|
|
497
|
-
credentialIssuerMetadata,
|
|
546
|
+
credentialIssuerMetadata: v15CredentialIssuerMetadata,
|
|
498
547
|
authorizationServerMetadata: authMetadata
|
|
499
548
|
};
|
|
500
549
|
}
|
|
@@ -511,47 +560,6 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
511
560
|
}
|
|
512
561
|
};
|
|
513
562
|
|
|
514
|
-
// lib/functions/dpopUtil.ts
|
|
515
|
-
import { dpopTokenRequestNonceError } from "@sphereon/oid4vc-common";
|
|
516
|
-
function shouldRetryTokenRequestWithDPoPNonce(response) {
|
|
517
|
-
if (!response.errorBody || response.errorBody.error !== dpopTokenRequestNonceError) {
|
|
518
|
-
return {
|
|
519
|
-
ok: false
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
const dPoPNonce = response.origResponse.headers.get("DPoP-Nonce");
|
|
523
|
-
if (!dPoPNonce) {
|
|
524
|
-
throw new Error("Missing required DPoP-Nonce header.");
|
|
525
|
-
}
|
|
526
|
-
return {
|
|
527
|
-
ok: true,
|
|
528
|
-
dpopNonce: dPoPNonce
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
__name(shouldRetryTokenRequestWithDPoPNonce, "shouldRetryTokenRequestWithDPoPNonce");
|
|
532
|
-
function shouldRetryResourceRequestWithDPoPNonce(response) {
|
|
533
|
-
if (!response.errorBody || response.origResponse.status !== 401) {
|
|
534
|
-
return {
|
|
535
|
-
ok: false
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
const wwwAuthenticateHeader = response.origResponse.headers.get("WWW-Authenticate");
|
|
539
|
-
if (!wwwAuthenticateHeader?.includes(dpopTokenRequestNonceError)) {
|
|
540
|
-
return {
|
|
541
|
-
ok: false
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
const dPoPNonce = response.origResponse.headers.get("DPoP-Nonce");
|
|
545
|
-
if (!dPoPNonce) {
|
|
546
|
-
throw new Error("Missing required DPoP-Nonce header.");
|
|
547
|
-
}
|
|
548
|
-
return {
|
|
549
|
-
ok: true,
|
|
550
|
-
dpopNonce: dPoPNonce
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
__name(shouldRetryResourceRequestWithDPoPNonce, "shouldRetryResourceRequestWithDPoPNonce");
|
|
554
|
-
|
|
555
563
|
// lib/AccessTokenClient.ts
|
|
556
564
|
var AccessTokenClient = class _AccessTokenClient {
|
|
557
565
|
static {
|
|
@@ -593,7 +601,7 @@ var AccessTokenClient = class _AccessTokenClient {
|
|
|
593
601
|
const requestTokenURL = _AccessTokenClient.determineTokenURL({
|
|
594
602
|
asOpts,
|
|
595
603
|
issuerOpts,
|
|
596
|
-
metadata: metadata ? metadata : issuerOpts?.fetchMetadata ? await
|
|
604
|
+
metadata: metadata ? metadata : issuerOpts?.fetchMetadata ? await MetadataClientV1_0_15.retrieveAllMetadata(issuerOpts.issuer, {
|
|
597
605
|
errorOnNotFound: false
|
|
598
606
|
}) : void 0
|
|
599
607
|
});
|
|
@@ -782,319 +790,108 @@ var AccessTokenClient = class _AccessTokenClient {
|
|
|
782
790
|
}
|
|
783
791
|
};
|
|
784
792
|
|
|
785
|
-
// lib/
|
|
786
|
-
import {
|
|
787
|
-
import {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
793
|
+
// lib/AuthorizationCodeClient.ts
|
|
794
|
+
import { CodeChallengeMethod as CodeChallengeMethod2, convertJsonToURI as convertJsonToURI2, CreateRequestObjectMode, determineSpecVersionFromOffer as determineSpecVersionFromOffer2, formPost as formPost2, isW3cCredentialSupported, JsonURIMode as JsonURIMode2, OpenId4VCIVersion as OpenId4VCIVersion3, PARMode, ResponseType } from "@sphereon/oid4vci-common";
|
|
795
|
+
import { Loggers as Loggers4 } from "@sphereon/ssi-types";
|
|
796
|
+
|
|
797
|
+
// lib/MetadataClient.ts
|
|
798
|
+
import { determineSpecVersionFromOffer, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload3, OpenId4VCIVersion as OpenId4VCIVersion2, WellKnownEndpoints as WellKnownEndpoints2 } from "@sphereon/oid4vci-common";
|
|
799
|
+
import { Loggers as Loggers3 } from "@sphereon/ssi-types";
|
|
800
|
+
var logger3 = Loggers3.DEFAULT.get("sphereon:oid4vci:metadata");
|
|
801
|
+
var MetadataClient = class _MetadataClient {
|
|
791
802
|
static {
|
|
792
|
-
__name(this, "
|
|
803
|
+
__name(this, "MetadataClient");
|
|
793
804
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
805
|
+
/**
|
|
806
|
+
* Retrieve metadata using the Initiation obtained from a previous step
|
|
807
|
+
*
|
|
808
|
+
* @param credentialOffer
|
|
809
|
+
*/
|
|
810
|
+
static async retrieveAllMetadataFromCredentialOffer(credentialOffer) {
|
|
811
|
+
const openId4VCIVersion = determineSpecVersionFromOffer(credentialOffer.credential_offer);
|
|
812
|
+
if (openId4VCIVersion >= OpenId4VCIVersion2.VER_1_0_15) {
|
|
813
|
+
return await MetadataClientV1_0_15.retrieveAllMetadataFromCredentialOffer(credentialOffer);
|
|
801
814
|
}
|
|
802
|
-
|
|
803
|
-
issuer
|
|
804
|
-
};
|
|
805
|
-
return await this.acquireAccessTokenUsingRequest({
|
|
806
|
-
accessTokenRequest: await this.createAccessTokenRequest({
|
|
807
|
-
credentialOffer,
|
|
808
|
-
asOpts,
|
|
809
|
-
codeVerifier,
|
|
810
|
-
code,
|
|
811
|
-
redirectUri,
|
|
812
|
-
pin,
|
|
813
|
-
credentialIssuer: issuer,
|
|
814
|
-
metadata,
|
|
815
|
-
additionalParams: opts.additionalParams,
|
|
816
|
-
pinMetadata: opts.pinMetadata
|
|
817
|
-
}),
|
|
818
|
-
isPinRequired,
|
|
819
|
-
metadata,
|
|
820
|
-
asOpts,
|
|
821
|
-
issuerOpts,
|
|
822
|
-
createDPoPOpts
|
|
823
|
-
});
|
|
815
|
+
return Promise.reject(Error(`OpenId4VCIVersion ${openId4VCIVersion} is not supported in retrieveAllMetadataFromCredentialOffer`));
|
|
824
816
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
headers: {
|
|
838
|
-
dpop: dPoP
|
|
817
|
+
/**
|
|
818
|
+
* Retrieve the metada using the initiation request obtained from a previous step
|
|
819
|
+
* @param request
|
|
820
|
+
*/
|
|
821
|
+
static async retrieveAllMetadataFromCredentialOfferRequest(request) {
|
|
822
|
+
const issuer = getIssuerFromCredentialOfferPayload3(request);
|
|
823
|
+
if (issuer) {
|
|
824
|
+
const openId4VCIVersion = determineSpecVersionFromOffer(request);
|
|
825
|
+
if (openId4VCIVersion >= OpenId4VCIVersion2.VER_1_0_15) {
|
|
826
|
+
return MetadataClientV1_0_15.retrieveAllMetadataFromCredentialOfferRequest(request);
|
|
827
|
+
} else {
|
|
828
|
+
return Promise.reject(Error(`OpenId4VCIVersion ${openId4VCIVersion} is not supported in retrieveAllMetadataFromCredentialOfferRequest`));
|
|
839
829
|
}
|
|
840
|
-
} : void 0);
|
|
841
|
-
let nextDPoPNonce = createDPoPOpts?.jwtPayloadProps.nonce;
|
|
842
|
-
const retryWithNonce = shouldRetryTokenRequestWithDPoPNonce(response);
|
|
843
|
-
if (retryWithNonce.ok && createDPoPOpts) {
|
|
844
|
-
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
845
|
-
dPoP = await createDPoP2(getCreateDPoPOptions2(createDPoPOpts, requestTokenURL));
|
|
846
|
-
response = await this.sendAuthCode(requestTokenURL, accessTokenRequest, dPoP ? {
|
|
847
|
-
headers: {
|
|
848
|
-
dpop: dPoP
|
|
849
|
-
}
|
|
850
|
-
} : void 0);
|
|
851
|
-
const successDPoPNonce = response.origResponse.headers.get("DPoP-Nonce");
|
|
852
|
-
nextDPoPNonce = successDPoPNonce ?? retryWithNonce.dpopNonce;
|
|
853
830
|
}
|
|
854
|
-
|
|
855
|
-
throw new Error("Invalid token type returned. Expected DPoP. Received: " + response.successBody.token_type);
|
|
856
|
-
}
|
|
857
|
-
return {
|
|
858
|
-
...response,
|
|
859
|
-
...nextDPoPNonce && {
|
|
860
|
-
params: {
|
|
861
|
-
dpop: {
|
|
862
|
-
dpopNonce: nextDPoPNonce
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
};
|
|
831
|
+
throw new Error("can't retrieve metadata from CredentialOfferRequest. No issuer field is present");
|
|
867
832
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
833
|
+
/**
|
|
834
|
+
* Retrieve all metadata from an issuer
|
|
835
|
+
* @param issuer The issuer URL
|
|
836
|
+
* @param opts
|
|
837
|
+
*/
|
|
838
|
+
static async retrieveAllMetadata(issuer, opts) {
|
|
839
|
+
let token_endpoint;
|
|
840
|
+
let credential_endpoint;
|
|
841
|
+
let deferred_credential_endpoint;
|
|
842
|
+
let authorization_endpoint;
|
|
843
|
+
let authorization_challenge_endpoint;
|
|
844
|
+
let authorizationServerType = "OID4VCI";
|
|
845
|
+
let authorization_servers = [
|
|
846
|
+
issuer
|
|
847
|
+
];
|
|
848
|
+
let authorization_server = void 0;
|
|
849
|
+
const oid4vciResponse = await _MetadataClient.retrieveOpenID4VCIServerMetadata(issuer, {
|
|
850
|
+
errorOnNotFound: false
|
|
882
851
|
});
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
852
|
+
let credentialIssuerMetadata = oid4vciResponse?.successBody;
|
|
853
|
+
if (credentialIssuerMetadata) {
|
|
854
|
+
logger3.debug(`Issuer ${issuer} OID4VCI well-known server metadata\r
|
|
855
|
+
${JSON.stringify(credentialIssuerMetadata)}`);
|
|
856
|
+
credential_endpoint = credentialIssuerMetadata.credential_endpoint;
|
|
857
|
+
deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint ? credentialIssuerMetadata.deferred_credential_endpoint : void 0;
|
|
858
|
+
if (credentialIssuerMetadata.token_endpoint) {
|
|
859
|
+
token_endpoint = credentialIssuerMetadata.token_endpoint;
|
|
889
860
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
assertPreAuthorizedGrantType(grantType) {
|
|
902
|
-
if (GrantTypes2.PRE_AUTHORIZED_CODE !== grantType) {
|
|
903
|
-
throw new Error("grant type must be PRE_AUTH_GRANT_LITERAL");
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
assertAuthorizationGrantType(grantType) {
|
|
907
|
-
if (GrantTypes2.AUTHORIZATION_CODE !== grantType) {
|
|
908
|
-
throw new Error("grant type must be 'authorization_code'");
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
isPinRequiredValue(requestPayload) {
|
|
912
|
-
let isPinRequired = false;
|
|
913
|
-
if (!requestPayload) {
|
|
914
|
-
throw new Error(TokenErrorResponse2.invalid_request);
|
|
861
|
+
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
|
|
862
|
+
if (credentialIssuerMetadata.authorization_servers) {
|
|
863
|
+
authorization_servers = credentialIssuerMetadata.authorization_servers;
|
|
864
|
+
} else if (credentialIssuerMetadata.authorization_server) {
|
|
865
|
+
authorization_server = credentialIssuerMetadata.authorization_server;
|
|
866
|
+
authorization_servers = [
|
|
867
|
+
authorization_server
|
|
868
|
+
];
|
|
869
|
+
}
|
|
870
|
+
} else {
|
|
871
|
+
throw new Error(`Issuer ${issuer} does not expose /.well-known/openid-credential-issuer`);
|
|
915
872
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
873
|
+
let response = await retrieveWellknown(authorization_servers[0], WellKnownEndpoints2.OPENID_CONFIGURATION, {
|
|
874
|
+
errorOnNotFound: false
|
|
875
|
+
});
|
|
876
|
+
let authMetadata = response.successBody;
|
|
877
|
+
if (authMetadata) {
|
|
878
|
+
logger3.debug(`Issuer ${issuer} has OpenID Connect Server metadata in well-known location`);
|
|
879
|
+
authorizationServerType = "OIDC";
|
|
880
|
+
} else {
|
|
881
|
+
response = await retrieveWellknown(authorization_servers[0], WellKnownEndpoints2.OAUTH_AS, {
|
|
882
|
+
errorOnNotFound: false
|
|
883
|
+
});
|
|
884
|
+
authMetadata = response.successBody;
|
|
919
885
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
assertNumericPin(isPinRequired, pin) {
|
|
924
|
-
if (isPinRequired) {
|
|
925
|
-
if (!pin || !/^\d{1,8}$/.test(pin)) {
|
|
926
|
-
logger3.debug(`Pin is not 1 to 8 digits long`);
|
|
927
|
-
throw new Error("A valid pin consisting of maximal 8 numeric characters must be present.");
|
|
928
|
-
}
|
|
929
|
-
} else if (pin) {
|
|
930
|
-
logger3.debug(`Pin set, whilst not required`);
|
|
931
|
-
throw new Error("Cannot set a pin, when the pin is not required.");
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
assertNonEmptyPreAuthorizedCode(accessTokenRequest) {
|
|
935
|
-
if (!accessTokenRequest[PRE_AUTH_CODE_LITERAL3]) {
|
|
936
|
-
logger3.debug(`No pre-authorized code present, whilst it is required`);
|
|
937
|
-
throw new Error("Pre-authorization must be proven by presenting the pre-authorized code. Code must be present.");
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
assertNonEmptyCodeVerifier(accessTokenRequest) {
|
|
941
|
-
if (!accessTokenRequest.code_verifier) {
|
|
942
|
-
logger3.debug("No code_verifier present, whilst it is required");
|
|
943
|
-
throw new Error("Authorization flow requires the code_verifier to be present");
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
assertNonEmptyCode(accessTokenRequest) {
|
|
947
|
-
if (!accessTokenRequest.code) {
|
|
948
|
-
logger3.debug("No code present, whilst it is required");
|
|
949
|
-
throw new Error("Authorization flow requires the code to be present");
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
validate(accessTokenRequest, isPinRequired) {
|
|
953
|
-
if (accessTokenRequest.grant_type === GrantTypes2.PRE_AUTHORIZED_CODE) {
|
|
954
|
-
this.assertPreAuthorizedGrantType(accessTokenRequest.grant_type);
|
|
955
|
-
this.assertNonEmptyPreAuthorizedCode(accessTokenRequest);
|
|
956
|
-
this.assertNumericPin(isPinRequired, accessTokenRequest.user_pin);
|
|
957
|
-
} else if (accessTokenRequest.grant_type === GrantTypes2.AUTHORIZATION_CODE) {
|
|
958
|
-
this.assertAuthorizationGrantType(accessTokenRequest.grant_type);
|
|
959
|
-
this.assertNonEmptyCodeVerifier(accessTokenRequest);
|
|
960
|
-
this.assertNonEmptyCode(accessTokenRequest);
|
|
961
|
-
} else {
|
|
962
|
-
this.throwNotSupportedFlow();
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
async sendAuthCode(requestTokenURL, accessTokenRequest, opts) {
|
|
966
|
-
return await formPost2(requestTokenURL, convertJsonToURI2(accessTokenRequest, {
|
|
967
|
-
mode: JsonURIMode2.X_FORM_WWW_URLENCODED
|
|
968
|
-
}), {
|
|
969
|
-
customHeaders: opts?.headers ? opts.headers : void 0
|
|
970
|
-
});
|
|
971
|
-
}
|
|
972
|
-
static determineTokenURL({ asOpts, issuerOpts, metadata }) {
|
|
973
|
-
if (!asOpts && !metadata?.token_endpoint && !issuerOpts) {
|
|
974
|
-
throw new Error("Cannot determine token URL if no issuer, metadata and no Authorization Server values are present");
|
|
975
|
-
}
|
|
976
|
-
let url;
|
|
977
|
-
if (asOpts && asOpts.as) {
|
|
978
|
-
url = this.creatTokenURLFromURL(asOpts.as, asOpts?.allowInsecureEndpoints, asOpts.tokenEndpoint);
|
|
979
|
-
} else if (metadata?.token_endpoint) {
|
|
980
|
-
url = metadata.token_endpoint;
|
|
981
|
-
} else {
|
|
982
|
-
if (!issuerOpts?.issuer) {
|
|
983
|
-
throw Error("Either authorization server options, a token endpoint or issuer options are required at this point");
|
|
984
|
-
}
|
|
985
|
-
url = this.creatTokenURLFromURL(issuerOpts.issuer, asOpts?.allowInsecureEndpoints, issuerOpts.tokenEndpoint);
|
|
986
|
-
}
|
|
987
|
-
if (!url || !ObjectUtils2.isString(url)) {
|
|
988
|
-
throw new Error("No authorization server token URL present. Cannot acquire access token");
|
|
989
|
-
}
|
|
990
|
-
logger3.debug(`Token endpoint determined to be ${url}`);
|
|
991
|
-
return url;
|
|
992
|
-
}
|
|
993
|
-
static creatTokenURLFromURL(url, allowInsecureEndpoints, tokenEndpoint) {
|
|
994
|
-
if (allowInsecureEndpoints !== true && url.startsWith("http:")) {
|
|
995
|
-
throw Error(`Unprotected token endpoints are not allowed ${url}. Use the 'allowInsecureEndpoints' param if you really need this for dev/testing!`);
|
|
996
|
-
}
|
|
997
|
-
const hostname = url.replace(/https?:\/\//, "").replace(/\/$/, "");
|
|
998
|
-
const endpoint = tokenEndpoint ? tokenEndpoint.startsWith("/") ? tokenEndpoint : tokenEndpoint.substring(1) : "/token";
|
|
999
|
-
const scheme = url.split("://")[0];
|
|
1000
|
-
return `${scheme ? scheme + "://" : "https://"}${hostname}${endpoint}`;
|
|
1001
|
-
}
|
|
1002
|
-
throwNotSupportedFlow() {
|
|
1003
|
-
logger3.debug(`Only pre-authorized or authorization code flows supported.`);
|
|
1004
|
-
throw new Error("Only pre-authorized-code or authorization code flows are supported");
|
|
1005
|
-
}
|
|
1006
|
-
};
|
|
1007
|
-
|
|
1008
|
-
// lib/AuthorizationCodeClient.ts
|
|
1009
|
-
import { CodeChallengeMethod as CodeChallengeMethod2, convertJsonToURI as convertJsonToURI3, CreateRequestObjectMode, determineSpecVersionFromOffer as determineSpecVersionFromOffer2, formPost as formPost3, isW3cCredentialSupported, JsonURIMode as JsonURIMode3, OpenId4VCIVersion as OpenId4VCIVersion5, PARMode, ResponseType } from "@sphereon/oid4vci-common";
|
|
1010
|
-
import { Loggers as Loggers6 } from "@sphereon/ssi-types";
|
|
1011
|
-
|
|
1012
|
-
// lib/MetadataClient.ts
|
|
1013
|
-
import { determineSpecVersionFromOffer, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload5, OpenId4VCIVersion as OpenId4VCIVersion4, WellKnownEndpoints as WellKnownEndpoints3 } from "@sphereon/oid4vci-common";
|
|
1014
|
-
import { Loggers as Loggers5 } from "@sphereon/ssi-types";
|
|
1015
|
-
|
|
1016
|
-
// lib/MetadataClientV1_0_11.ts
|
|
1017
|
-
import { getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload4, WellKnownEndpoints as WellKnownEndpoints2 } from "@sphereon/oid4vci-common";
|
|
1018
|
-
import { Loggers as Loggers4 } from "@sphereon/ssi-types";
|
|
1019
|
-
var logger4 = Loggers4.DEFAULT.get("sphereon:oid4vci:metadata");
|
|
1020
|
-
var MetadataClientV1_0_11 = class _MetadataClientV1_0_11 {
|
|
1021
|
-
static {
|
|
1022
|
-
__name(this, "MetadataClientV1_0_11");
|
|
1023
|
-
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Retrieve metadata using the Initiation obtained from a previous step
|
|
1026
|
-
*
|
|
1027
|
-
* @param credentialOffer
|
|
1028
|
-
*/
|
|
1029
|
-
static async retrieveAllMetadataFromCredentialOffer(credentialOffer) {
|
|
1030
|
-
return _MetadataClientV1_0_11.retrieveAllMetadataFromCredentialOfferRequest(credentialOffer.credential_offer);
|
|
1031
|
-
}
|
|
1032
|
-
/**
|
|
1033
|
-
* Retrieve the metada using the initiation request obtained from a previous step
|
|
1034
|
-
* @param request
|
|
1035
|
-
*/
|
|
1036
|
-
static async retrieveAllMetadataFromCredentialOfferRequest(request) {
|
|
1037
|
-
const issuer = getIssuerFromCredentialOfferPayload4(request);
|
|
1038
|
-
if (issuer) {
|
|
1039
|
-
return _MetadataClientV1_0_11.retrieveAllMetadata(issuer);
|
|
1040
|
-
}
|
|
1041
|
-
throw new Error("can't retrieve metadata from CredentialOfferRequest. No issuer field is present");
|
|
1042
|
-
}
|
|
1043
|
-
/**
|
|
1044
|
-
* Retrieve all metadata from an issuer
|
|
1045
|
-
* @param issuer The issuer URL
|
|
1046
|
-
* @param opts
|
|
1047
|
-
*/
|
|
1048
|
-
static async retrieveAllMetadata(issuer, opts) {
|
|
1049
|
-
let token_endpoint;
|
|
1050
|
-
let credential_endpoint;
|
|
1051
|
-
let deferred_credential_endpoint;
|
|
1052
|
-
let authorization_endpoint;
|
|
1053
|
-
let authorization_challenge_endpoint;
|
|
1054
|
-
let authorizationServerType = "OID4VCI";
|
|
1055
|
-
let authorization_server = issuer;
|
|
1056
|
-
const oid4vciResponse = await _MetadataClientV1_0_11.retrieveOpenID4VCIServerMetadata(issuer, {
|
|
1057
|
-
errorOnNotFound: false
|
|
1058
|
-
});
|
|
1059
|
-
let credentialIssuerMetadata = oid4vciResponse?.successBody;
|
|
1060
|
-
if (credentialIssuerMetadata) {
|
|
1061
|
-
logger4.debug(`Issuer ${issuer} OID4VCI well-known server metadata\r
|
|
1062
|
-
${JSON.stringify(credentialIssuerMetadata)}`);
|
|
1063
|
-
credential_endpoint = credentialIssuerMetadata.credential_endpoint;
|
|
1064
|
-
deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint;
|
|
1065
|
-
if (credentialIssuerMetadata.token_endpoint) {
|
|
1066
|
-
token_endpoint = credentialIssuerMetadata.token_endpoint;
|
|
1067
|
-
}
|
|
1068
|
-
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
|
|
1069
|
-
if (credentialIssuerMetadata.authorization_server) {
|
|
1070
|
-
authorization_server = credentialIssuerMetadata.authorization_server;
|
|
1071
|
-
}
|
|
1072
|
-
if (credentialIssuerMetadata.authorization_endpoint) {
|
|
1073
|
-
authorization_endpoint = credentialIssuerMetadata.authorization_endpoint;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
let response = await retrieveWellknown(authorization_server, WellKnownEndpoints2.OPENID_CONFIGURATION, {
|
|
1077
|
-
errorOnNotFound: false
|
|
1078
|
-
});
|
|
1079
|
-
let authMetadata = response.successBody;
|
|
1080
|
-
if (authMetadata) {
|
|
1081
|
-
logger4.debug(`Issuer ${issuer} has OpenID Connect Server metadata in well-known location`);
|
|
1082
|
-
authorizationServerType = "OIDC";
|
|
1083
|
-
} else {
|
|
1084
|
-
response = await retrieveWellknown(authorization_server, WellKnownEndpoints2.OAUTH_AS, {
|
|
1085
|
-
errorOnNotFound: false
|
|
1086
|
-
});
|
|
1087
|
-
authMetadata = response.successBody;
|
|
1088
|
-
}
|
|
1089
|
-
if (!authMetadata) {
|
|
1090
|
-
if (issuer !== authorization_server) {
|
|
1091
|
-
throw Error(`Issuer ${issuer} provided a separate authorization server ${authorization_server}, but that server did not provide metadata`);
|
|
886
|
+
if (!authMetadata) {
|
|
887
|
+
if (!authorization_servers.includes(issuer)) {
|
|
888
|
+
throw Error(`Issuer ${issuer} provided a separate authorization server ${authorization_servers}, but that server did not provide metadata`);
|
|
1092
889
|
}
|
|
1093
890
|
} else {
|
|
1094
891
|
if (!authorizationServerType) {
|
|
1095
892
|
authorizationServerType = "OAuth 2.0";
|
|
1096
893
|
}
|
|
1097
|
-
|
|
894
|
+
logger3.debug(`Issuer ${issuer} has ${authorizationServerType} Server metadata in well-known location`);
|
|
1098
895
|
if (!authMetadata.authorization_endpoint) {
|
|
1099
896
|
console.warn(`Issuer ${issuer} of type ${authorizationServerType} has no authorization_endpoint! Will use ${authorization_endpoint}. This only works for pre-authorized flows`);
|
|
1100
897
|
} else if (authorization_endpoint && authMetadata.authorization_endpoint !== authorization_endpoint) {
|
|
@@ -1106,31 +903,31 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
1106
903
|
}
|
|
1107
904
|
authorization_challenge_endpoint = authMetadata.authorization_challenge_endpoint;
|
|
1108
905
|
if (!authMetadata.token_endpoint) {
|
|
1109
|
-
throw Error(`Authorization Server ${
|
|
906
|
+
throw Error(`Authorization Server ${authorization_servers} did not provide a token_endpoint`);
|
|
1110
907
|
} else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
|
|
1111
908
|
throw Error(`Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`);
|
|
1112
909
|
}
|
|
1113
910
|
token_endpoint = authMetadata.token_endpoint;
|
|
1114
911
|
if (authMetadata.credential_endpoint) {
|
|
1115
912
|
if (credential_endpoint && authMetadata.credential_endpoint !== credential_endpoint) {
|
|
1116
|
-
|
|
913
|
+
logger3.debug(`Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.credential_endpoint}). Will use the issuer value`);
|
|
1117
914
|
} else {
|
|
1118
915
|
credential_endpoint = authMetadata.credential_endpoint;
|
|
1119
916
|
}
|
|
1120
917
|
}
|
|
1121
918
|
if (authMetadata.deferred_credential_endpoint) {
|
|
1122
919
|
if (deferred_credential_endpoint && authMetadata.deferred_credential_endpoint !== deferred_credential_endpoint) {
|
|
1123
|
-
|
|
920
|
+
logger3.debug(`Credential issuer has a different deferred_credential_endpoint (${deferred_credential_endpoint}) from the Authorization Server (${authMetadata.deferred_credential_endpoint}). Will use the issuer value`);
|
|
1124
921
|
} else {
|
|
1125
922
|
deferred_credential_endpoint = authMetadata.deferred_credential_endpoint;
|
|
1126
923
|
}
|
|
1127
924
|
}
|
|
1128
925
|
}
|
|
1129
926
|
if (!authorization_endpoint) {
|
|
1130
|
-
|
|
927
|
+
logger3.debug(`Issuer ${issuer} does not expose authorization_endpoint, so only pre-auth will be supported`);
|
|
1131
928
|
}
|
|
1132
929
|
if (!token_endpoint) {
|
|
1133
|
-
|
|
930
|
+
logger3.debug(`Issuer ${issuer} does not have a token_endpoint listed in well-known locations!`);
|
|
1134
931
|
if (opts?.errorOnNotFound) {
|
|
1135
932
|
throw Error(`Could not deduce the token_endpoint for ${issuer}`);
|
|
1136
933
|
} else {
|
|
@@ -1138,7 +935,7 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
1138
935
|
}
|
|
1139
936
|
}
|
|
1140
937
|
if (!credential_endpoint) {
|
|
1141
|
-
|
|
938
|
+
logger3.debug(`Issuer ${issuer} does not have a credential_endpoint listed in well-known locations!`);
|
|
1142
939
|
if (opts?.errorOnNotFound) {
|
|
1143
940
|
throw Error(`Could not deduce the credential endpoint for ${issuer}`);
|
|
1144
941
|
} else {
|
|
@@ -1146,15 +943,20 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
1146
943
|
}
|
|
1147
944
|
}
|
|
1148
945
|
if (!credentialIssuerMetadata && authMetadata) {
|
|
1149
|
-
|
|
946
|
+
return Promise.reject(Error(`No /.well-known/openid-credential-issuer at ${issuer}.`));
|
|
1150
947
|
}
|
|
1151
|
-
|
|
948
|
+
logger3.debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
|
|
1152
949
|
return {
|
|
1153
950
|
issuer,
|
|
1154
951
|
token_endpoint,
|
|
1155
952
|
credential_endpoint,
|
|
1156
953
|
deferred_credential_endpoint,
|
|
1157
|
-
|
|
954
|
+
nonce_endpoint: credentialIssuerMetadata.nonce_endpoint,
|
|
955
|
+
authorization_servers: authorization_server ? [
|
|
956
|
+
authorization_server
|
|
957
|
+
] : authorization_servers ?? [
|
|
958
|
+
issuer
|
|
959
|
+
],
|
|
1158
960
|
authorization_endpoint,
|
|
1159
961
|
authorization_challenge_endpoint,
|
|
1160
962
|
authorizationServerType,
|
|
@@ -1166,6 +968,7 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
1166
968
|
* Retrieve only the OID4VCI metadata for the issuer. So no OIDC/OAuth2 metadata
|
|
1167
969
|
*
|
|
1168
970
|
* @param issuerHost The issuer hostname
|
|
971
|
+
* @param opts
|
|
1169
972
|
*/
|
|
1170
973
|
static async retrieveOpenID4VCIServerMetadata(issuerHost, opts) {
|
|
1171
974
|
return retrieveWellknown(issuerHost, WellKnownEndpoints2.OPENID4VCI_ISSUER, {
|
|
@@ -1174,228 +977,51 @@ ${JSON.stringify(credentialIssuerMetadata)}`);
|
|
|
1174
977
|
}
|
|
1175
978
|
};
|
|
1176
979
|
|
|
1177
|
-
// lib/
|
|
1178
|
-
var
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
*/
|
|
1188
|
-
static async retrieveAllMetadataFromCredentialOffer(credentialOffer) {
|
|
1189
|
-
if (determineSpecVersionFromOffer(credentialOffer.credential_offer) >= OpenId4VCIVersion4.VER_1_0_13) {
|
|
1190
|
-
return await MetadataClientV1_0_13.retrieveAllMetadataFromCredentialOffer(credentialOffer);
|
|
1191
|
-
} else {
|
|
1192
|
-
return await MetadataClientV1_0_11.retrieveAllMetadataFromCredentialOffer(credentialOffer);
|
|
980
|
+
// lib/AuthorizationCodeClient.ts
|
|
981
|
+
var logger4 = Loggers4.DEFAULT.get("sphereon:oid4vci");
|
|
982
|
+
async function createSignedAuthRequestWhenNeeded(requestObject, opts) {
|
|
983
|
+
if (opts.requestObjectMode === CreateRequestObjectMode.REQUEST_URI) {
|
|
984
|
+
throw Error(`Request Object Mode ${opts.requestObjectMode} is not supported yet`);
|
|
985
|
+
} else if (opts.requestObjectMode === CreateRequestObjectMode.REQUEST_OBJECT) {
|
|
986
|
+
if (typeof opts.signCallbacks?.signCallback !== "function") {
|
|
987
|
+
throw Error(`No request object sign callback found, whilst request object mode was set to ${opts.requestObjectMode}`);
|
|
988
|
+
} else if (!opts.kid) {
|
|
989
|
+
throw Error(`No kid found, whilst request object mode was set to ${opts.requestObjectMode}`);
|
|
1193
990
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
static async retrieveAllMetadataFromCredentialOfferRequest(request) {
|
|
1200
|
-
const issuer = getIssuerFromCredentialOfferPayload5(request);
|
|
1201
|
-
if (issuer) {
|
|
1202
|
-
if (determineSpecVersionFromOffer(request) >= OpenId4VCIVersion4.VER_1_0_13) {
|
|
1203
|
-
return MetadataClientV1_0_13.retrieveAllMetadataFromCredentialOfferRequest(request);
|
|
1204
|
-
} else {
|
|
1205
|
-
return MetadataClientV1_0_11.retrieveAllMetadataFromCredentialOfferRequest(request);
|
|
991
|
+
let client_metadata;
|
|
992
|
+
if (opts.clientMetadata || opts.jwksUri) {
|
|
993
|
+
client_metadata = opts.clientMetadata ?? {};
|
|
994
|
+
if (opts.jwksUri) {
|
|
995
|
+
client_metadata["jwks_uri"] = opts.jwksUri;
|
|
1206
996
|
}
|
|
1207
997
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
* Retrieve all metadata from an issuer
|
|
1212
|
-
* @param issuer The issuer URL
|
|
1213
|
-
* @param opts
|
|
1214
|
-
*/
|
|
1215
|
-
static async retrieveAllMetadata(issuer, opts) {
|
|
1216
|
-
let token_endpoint;
|
|
1217
|
-
let credential_endpoint;
|
|
1218
|
-
let deferred_credential_endpoint;
|
|
1219
|
-
let authorization_endpoint;
|
|
1220
|
-
let authorization_challenge_endpoint;
|
|
1221
|
-
let authorizationServerType = "OID4VCI";
|
|
1222
|
-
let authorization_servers = [
|
|
1223
|
-
issuer
|
|
1224
|
-
];
|
|
1225
|
-
let authorization_server = void 0;
|
|
1226
|
-
const oid4vciResponse = await _MetadataClient.retrieveOpenID4VCIServerMetadata(issuer, {
|
|
1227
|
-
errorOnNotFound: false
|
|
1228
|
-
});
|
|
1229
|
-
let credentialIssuerMetadata = oid4vciResponse?.successBody;
|
|
1230
|
-
if (credentialIssuerMetadata) {
|
|
1231
|
-
logger5.debug(`Issuer ${issuer} OID4VCI well-known server metadata\r
|
|
1232
|
-
${JSON.stringify(credentialIssuerMetadata)}`);
|
|
1233
|
-
credential_endpoint = credentialIssuerMetadata.credential_endpoint;
|
|
1234
|
-
deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint ? credentialIssuerMetadata.deferred_credential_endpoint : void 0;
|
|
1235
|
-
if (credentialIssuerMetadata.token_endpoint) {
|
|
1236
|
-
token_endpoint = credentialIssuerMetadata.token_endpoint;
|
|
1237
|
-
}
|
|
1238
|
-
authorization_challenge_endpoint = credentialIssuerMetadata.authorization_challenge_endpoint;
|
|
1239
|
-
if (credentialIssuerMetadata.authorization_servers) {
|
|
1240
|
-
authorization_servers = credentialIssuerMetadata.authorization_servers;
|
|
1241
|
-
} else if (credentialIssuerMetadata.authorization_server) {
|
|
1242
|
-
authorization_server = credentialIssuerMetadata.authorization_server;
|
|
1243
|
-
authorization_servers = [
|
|
1244
|
-
authorization_server
|
|
1245
|
-
];
|
|
1246
|
-
}
|
|
998
|
+
let authorization_details = requestObject["authorization_details"];
|
|
999
|
+
if (typeof authorization_details === "string") {
|
|
1000
|
+
authorization_details = JSON.parse(requestObject.authorization_details);
|
|
1247
1001
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
});
|
|
1251
|
-
let authMetadata = response.successBody;
|
|
1252
|
-
if (authMetadata) {
|
|
1253
|
-
logger5.debug(`Issuer ${issuer} has OpenID Connect Server metadata in well-known location`);
|
|
1254
|
-
authorizationServerType = "OIDC";
|
|
1255
|
-
} else {
|
|
1256
|
-
response = await retrieveWellknown(authorization_servers[0], WellKnownEndpoints3.OAUTH_AS, {
|
|
1257
|
-
errorOnNotFound: false
|
|
1258
|
-
});
|
|
1259
|
-
authMetadata = response.successBody;
|
|
1002
|
+
if (!requestObject.aud && opts.aud) {
|
|
1003
|
+
requestObject.aud = opts.aud;
|
|
1260
1004
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
authorization_endpoint = authMetadata.authorization_endpoint;
|
|
1276
|
-
if (authorization_challenge_endpoint && authMetadata.authorization_challenge_endpoint !== authorization_challenge_endpoint) {
|
|
1277
|
-
throw Error(`Credential issuer has a different authorization_challenge_endpoint (${authorization_challenge_endpoint}) from the Authorization Server (${authMetadata.authorization_challenge_endpoint})`);
|
|
1278
|
-
}
|
|
1279
|
-
authorization_challenge_endpoint = authMetadata.authorization_challenge_endpoint;
|
|
1280
|
-
if (!authMetadata.token_endpoint) {
|
|
1281
|
-
throw Error(`Authorization Server ${authorization_servers} did not provide a token_endpoint`);
|
|
1282
|
-
} else if (token_endpoint && authMetadata.token_endpoint !== token_endpoint) {
|
|
1283
|
-
throw Error(`Credential issuer has a different token_endpoint (${token_endpoint}) from the Authorization Server (${authMetadata.token_endpoint})`);
|
|
1284
|
-
}
|
|
1285
|
-
token_endpoint = authMetadata.token_endpoint;
|
|
1286
|
-
if (authMetadata.credential_endpoint) {
|
|
1287
|
-
if (credential_endpoint && authMetadata.credential_endpoint !== credential_endpoint) {
|
|
1288
|
-
logger5.debug(`Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.credential_endpoint}). Will use the issuer value`);
|
|
1289
|
-
} else {
|
|
1290
|
-
credential_endpoint = authMetadata.credential_endpoint;
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
if (authMetadata.deferred_credential_endpoint) {
|
|
1294
|
-
if (deferred_credential_endpoint && authMetadata.deferred_credential_endpoint !== deferred_credential_endpoint) {
|
|
1295
|
-
logger5.debug(`Credential issuer has a different deferred_credential_endpoint (${deferred_credential_endpoint}) from the Authorization Server (${authMetadata.deferred_credential_endpoint}). Will use the issuer value`);
|
|
1296
|
-
} else {
|
|
1297
|
-
deferred_credential_endpoint = authMetadata.deferred_credential_endpoint;
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
if (!authorization_endpoint) {
|
|
1302
|
-
logger5.debug(`Issuer ${issuer} does not expose authorization_endpoint, so only pre-auth will be supported`);
|
|
1303
|
-
}
|
|
1304
|
-
if (!token_endpoint) {
|
|
1305
|
-
logger5.debug(`Issuer ${issuer} does not have a token_endpoint listed in well-known locations!`);
|
|
1306
|
-
if (opts?.errorOnNotFound) {
|
|
1307
|
-
throw Error(`Could not deduce the token_endpoint for ${issuer}`);
|
|
1308
|
-
} else {
|
|
1309
|
-
token_endpoint = `${issuer}${issuer.endsWith("/") ? "token" : "/token"}`;
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
if (!credential_endpoint) {
|
|
1313
|
-
logger5.debug(`Issuer ${issuer} does not have a credential_endpoint listed in well-known locations!`);
|
|
1314
|
-
if (opts?.errorOnNotFound) {
|
|
1315
|
-
throw Error(`Could not deduce the credential endpoint for ${issuer}`);
|
|
1316
|
-
} else {
|
|
1317
|
-
credential_endpoint = `${issuer}${issuer.endsWith("/") ? "credential" : "/credential"}`;
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
if (!credentialIssuerMetadata && authMetadata) {
|
|
1321
|
-
credentialIssuerMetadata = authorization_server ? authMetadata : authMetadata;
|
|
1322
|
-
}
|
|
1323
|
-
logger5.debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
|
|
1324
|
-
return {
|
|
1325
|
-
issuer,
|
|
1326
|
-
token_endpoint,
|
|
1327
|
-
credential_endpoint,
|
|
1328
|
-
deferred_credential_endpoint,
|
|
1329
|
-
...authorization_server ? {
|
|
1330
|
-
authorization_server
|
|
1331
|
-
} : {
|
|
1332
|
-
authorization_servers
|
|
1333
|
-
},
|
|
1334
|
-
authorization_endpoint,
|
|
1335
|
-
authorization_challenge_endpoint,
|
|
1336
|
-
authorizationServerType,
|
|
1337
|
-
credentialIssuerMetadata: authorization_server ? credentialIssuerMetadata : credentialIssuerMetadata,
|
|
1338
|
-
authorizationServerMetadata: authMetadata
|
|
1339
|
-
};
|
|
1340
|
-
}
|
|
1341
|
-
/**
|
|
1342
|
-
* Retrieve only the OID4VCI metadata for the issuer. So no OIDC/OAuth2 metadata
|
|
1343
|
-
*
|
|
1344
|
-
* @param issuerHost The issuer hostname
|
|
1345
|
-
* @param opts
|
|
1346
|
-
*/
|
|
1347
|
-
static async retrieveOpenID4VCIServerMetadata(issuerHost, opts) {
|
|
1348
|
-
return retrieveWellknown(issuerHost, WellKnownEndpoints3.OPENID4VCI_ISSUER, {
|
|
1349
|
-
errorOnNotFound: opts?.errorOnNotFound === void 0 ? true : opts.errorOnNotFound
|
|
1350
|
-
});
|
|
1351
|
-
}
|
|
1352
|
-
};
|
|
1353
|
-
|
|
1354
|
-
// lib/AuthorizationCodeClient.ts
|
|
1355
|
-
var logger6 = Loggers6.DEFAULT.get("sphereon:oid4vci");
|
|
1356
|
-
async function createSignedAuthRequestWhenNeeded(requestObject, opts) {
|
|
1357
|
-
if (opts.requestObjectMode === CreateRequestObjectMode.REQUEST_URI) {
|
|
1358
|
-
throw Error(`Request Object Mode ${opts.requestObjectMode} is not supported yet`);
|
|
1359
|
-
} else if (opts.requestObjectMode === CreateRequestObjectMode.REQUEST_OBJECT) {
|
|
1360
|
-
if (typeof opts.signCallbacks?.signCallback !== "function") {
|
|
1361
|
-
throw Error(`No request object sign callback found, whilst request object mode was set to ${opts.requestObjectMode}`);
|
|
1362
|
-
} else if (!opts.kid) {
|
|
1363
|
-
throw Error(`No kid found, whilst request object mode was set to ${opts.requestObjectMode}`);
|
|
1364
|
-
}
|
|
1365
|
-
let client_metadata;
|
|
1366
|
-
if (opts.clientMetadata || opts.jwksUri) {
|
|
1367
|
-
client_metadata = opts.clientMetadata ?? {};
|
|
1368
|
-
if (opts.jwksUri) {
|
|
1369
|
-
client_metadata["jwks_uri"] = opts.jwksUri;
|
|
1370
|
-
}
|
|
1371
|
-
}
|
|
1372
|
-
let authorization_details = requestObject["authorization_details"];
|
|
1373
|
-
if (typeof authorization_details === "string") {
|
|
1374
|
-
authorization_details = JSON.parse(requestObject.authorization_details);
|
|
1375
|
-
}
|
|
1376
|
-
if (!requestObject.aud && opts.aud) {
|
|
1377
|
-
requestObject.aud = opts.aud;
|
|
1378
|
-
}
|
|
1379
|
-
const iss = requestObject.iss ?? opts.iss ?? requestObject.client_id;
|
|
1380
|
-
const jwt = {
|
|
1381
|
-
header: {
|
|
1382
|
-
alg: "ES256",
|
|
1383
|
-
kid: opts.kid,
|
|
1384
|
-
typ: "JWT"
|
|
1385
|
-
},
|
|
1386
|
-
payload: {
|
|
1387
|
-
...requestObject,
|
|
1388
|
-
iss,
|
|
1389
|
-
authorization_details,
|
|
1390
|
-
...client_metadata && {
|
|
1391
|
-
client_metadata
|
|
1392
|
-
}
|
|
1005
|
+
const iss = requestObject.iss ?? opts.iss ?? requestObject.client_id;
|
|
1006
|
+
const jwt = {
|
|
1007
|
+
header: {
|
|
1008
|
+
alg: "ES256",
|
|
1009
|
+
kid: opts.kid,
|
|
1010
|
+
typ: "JWT"
|
|
1011
|
+
},
|
|
1012
|
+
payload: {
|
|
1013
|
+
...requestObject,
|
|
1014
|
+
iss,
|
|
1015
|
+
authorization_details,
|
|
1016
|
+
...client_metadata && {
|
|
1017
|
+
client_metadata
|
|
1018
|
+
}
|
|
1393
1019
|
}
|
|
1394
1020
|
};
|
|
1395
1021
|
const pop = await ProofOfPossessionBuilder.fromJwt({
|
|
1396
1022
|
jwt,
|
|
1397
1023
|
callbacks: opts.signCallbacks,
|
|
1398
|
-
version:
|
|
1024
|
+
version: OpenId4VCIVersion3.VER_1_0_15,
|
|
1399
1025
|
mode: "JWT"
|
|
1400
1026
|
}).build();
|
|
1401
1027
|
requestObject["request"] = pop.jwt;
|
|
@@ -1446,8 +1072,8 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1446
1072
|
if ("credentials" in credentialOffer.credential_offer) {
|
|
1447
1073
|
throw new Error("CredentialOffer format is wrong.");
|
|
1448
1074
|
}
|
|
1449
|
-
const ver = version ?? determineSpecVersionFromOffer2(credentialOffer.credential_offer) ??
|
|
1450
|
-
const creds = ver ===
|
|
1075
|
+
const ver = version ?? determineSpecVersionFromOffer2(credentialOffer.credential_offer) ?? OpenId4VCIVersion3.VER_1_0_15;
|
|
1076
|
+
const creds = ver === OpenId4VCIVersion3.VER_1_0_15 ? filterSupportedCredentials(credentialOffer.credential_offer, credentialConfigurationSupported) : [];
|
|
1451
1077
|
authorizationDetails = creds.flatMap((cred) => {
|
|
1452
1078
|
const locations = [
|
|
1453
1079
|
credentialOffer?.credential_offer.credential_issuer ?? endpointMetadata.issuer
|
|
@@ -1457,10 +1083,10 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1457
1083
|
if (!credential_configuration_id && !cred.format) {
|
|
1458
1084
|
throw Error("format is required in authorization details");
|
|
1459
1085
|
}
|
|
1460
|
-
const vct = cred.format === "
|
|
1086
|
+
const vct = cred.format === "dc+sd-jwt" ? cred.vct : void 0;
|
|
1461
1087
|
const doctype = cred.format === "mso_mdoc" ? cred.doctype : void 0;
|
|
1462
1088
|
let credential_definition = void 0;
|
|
1463
|
-
if (isW3cCredentialSupported(cred)) {
|
|
1089
|
+
if (isW3cCredentialSupported(cred) && hasCredentialDefinition(cred)) {
|
|
1464
1090
|
credential_definition = {
|
|
1465
1091
|
...cred.credential_definition,
|
|
1466
1092
|
// type: OPTIONAL. Array as defined in Appendix A.1.1.2. This claim contains the type values the Wallet requests authorization for at the Credential Issuer. It MUST be present if the claim format is present in the root of the authorization details object. It MUST not be present otherwise.
|
|
@@ -1495,7 +1121,8 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1495
1121
|
throw Error(`Could not create authorization details from credential offer. Please pass in explicit details`);
|
|
1496
1122
|
}
|
|
1497
1123
|
}
|
|
1498
|
-
|
|
1124
|
+
const authorizationEndpoint = endpointMetadata.authorization_endpoint ?? endpointMetadata.authorizationServerMetadata?.authorization_endpoint ?? endpointMetadata.credentialIssuerMetadata?.authorization_endpoint;
|
|
1125
|
+
if (!authorizationEndpoint) {
|
|
1499
1126
|
throw Error("Server metadata does not contain authorization endpoint");
|
|
1500
1127
|
}
|
|
1501
1128
|
const parEndpoint = authorizationMetadata?.pushed_authorization_request_endpoint;
|
|
@@ -1523,9 +1150,9 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1523
1150
|
if (!parEndpoint && parMode === PARMode.REQUIRE) {
|
|
1524
1151
|
throw Error(`PAR mode is set to required by Authorization Server does not support PAR!`);
|
|
1525
1152
|
} else if (parEndpoint && parMode !== PARMode.NEVER) {
|
|
1526
|
-
|
|
1527
|
-
const parResponse = await
|
|
1528
|
-
mode:
|
|
1153
|
+
logger4.debug(`USING PAR with endpoint ${parEndpoint}`);
|
|
1154
|
+
const parResponse = await formPost2(parEndpoint, convertJsonToURI2(queryObj, {
|
|
1155
|
+
mode: JsonURIMode2.X_FORM_WWW_URLENCODED,
|
|
1529
1156
|
uriTypeProperties: [
|
|
1530
1157
|
"client_id",
|
|
1531
1158
|
"request_uri",
|
|
@@ -1543,9 +1170,9 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1543
1170
|
if (parMode === PARMode.REQUIRE) {
|
|
1544
1171
|
throw Error(`PAR error: ${parResponse.origResponse.statusText}`);
|
|
1545
1172
|
}
|
|
1546
|
-
|
|
1173
|
+
logger4.debug("Falling back to regular request URI, since PAR failed", JSON.stringify(parResponse.errorBody));
|
|
1547
1174
|
} else {
|
|
1548
|
-
|
|
1175
|
+
logger4.debug(`PAR response: ${JSON.stringify(parResponse.successBody, null, 2)}`);
|
|
1549
1176
|
queryObj = {
|
|
1550
1177
|
client_id,
|
|
1551
1178
|
request_uri: parResponse.successBody.request_uri
|
|
@@ -1554,11 +1181,11 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1554
1181
|
}
|
|
1555
1182
|
await createSignedAuthRequestWhenNeeded(queryObj, {
|
|
1556
1183
|
...requestObjectOpts,
|
|
1557
|
-
aud: endpointMetadata.authorization_server
|
|
1184
|
+
aud: endpointMetadata.authorization_server ?? endpointMetadata.authorizationServerMetadata?.issuer
|
|
1558
1185
|
});
|
|
1559
|
-
|
|
1560
|
-
const url =
|
|
1561
|
-
baseUrl:
|
|
1186
|
+
logger4.debug(`Object that will become query params: ` + JSON.stringify(queryObj, null, 2));
|
|
1187
|
+
const url = convertJsonToURI2(queryObj, {
|
|
1188
|
+
baseUrl: authorizationEndpoint,
|
|
1562
1189
|
uriTypeProperties: [
|
|
1563
1190
|
"client_id",
|
|
1564
1191
|
"request_uri",
|
|
@@ -1569,11 +1196,12 @@ var createAuthorizationRequestUrl = /* @__PURE__ */ __name(async ({ pkce, endpoi
|
|
|
1569
1196
|
"state"
|
|
1570
1197
|
],
|
|
1571
1198
|
// arrayTypeProperties: ['authorization_details'],
|
|
1572
|
-
mode:
|
|
1199
|
+
mode: JsonURIMode2.X_FORM_WWW_URLENCODED
|
|
1573
1200
|
});
|
|
1574
|
-
|
|
1201
|
+
logger4.debug(`Authorization Request URL: ${url}`);
|
|
1575
1202
|
return url;
|
|
1576
1203
|
}, "createAuthorizationRequestUrl");
|
|
1204
|
+
var hasCredentialDefinition = /* @__PURE__ */ __name((cred) => "credential_definition" in cred && cred.credential_definition && typeof cred.credential_definition === "object" && cred.credential_definition !== null && "type" in cred.credential_definition && Array.isArray(cred.credential_definition.type), "hasCredentialDefinition");
|
|
1577
1205
|
var handleAuthorizationDetails = /* @__PURE__ */ __name((endpointMetadata, authorizationDetails) => {
|
|
1578
1206
|
if (authorizationDetails) {
|
|
1579
1207
|
if (typeof authorizationDetails === "string") {
|
|
@@ -1595,7 +1223,10 @@ var handleLocations = /* @__PURE__ */ __name((endpointMetadata, authorizationDet
|
|
|
1595
1223
|
if (typeof authorizationDetails === "string") {
|
|
1596
1224
|
return authorizationDetails;
|
|
1597
1225
|
}
|
|
1598
|
-
|
|
1226
|
+
const ciMeta = endpointMetadata.credentialIssuerMetadata;
|
|
1227
|
+
const hasAuthorizationServers = Array.isArray(ciMeta?.authorization_servers) && ciMeta.authorization_servers.length > 0;
|
|
1228
|
+
const legacyHasAuthzEndpoint = Boolean(endpointMetadata.authorization_endpoint);
|
|
1229
|
+
if (hasAuthorizationServers || legacyHasAuthzEndpoint) {
|
|
1599
1230
|
if (authorizationDetails.locations) {
|
|
1600
1231
|
if (Array.isArray(authorizationDetails.locations)) {
|
|
1601
1232
|
authorizationDetails.locations.push(endpointMetadata.issuer);
|
|
@@ -1654,169 +1285,18 @@ var createAuthorizationChallengeRequest = /* @__PURE__ */ __name(async (opts) =>
|
|
|
1654
1285
|
return request;
|
|
1655
1286
|
}, "createAuthorizationChallengeRequest");
|
|
1656
1287
|
var sendAuthorizationChallengeRequest = /* @__PURE__ */ __name(async (authorizationChallengeCodeUrl, authorizationChallengeRequest, opts) => {
|
|
1657
|
-
return await
|
|
1658
|
-
mode:
|
|
1288
|
+
return await formPost2(authorizationChallengeCodeUrl, convertJsonToURI2(authorizationChallengeRequest, {
|
|
1289
|
+
mode: JsonURIMode2.X_FORM_WWW_URLENCODED
|
|
1659
1290
|
}), {
|
|
1660
1291
|
customHeaders: opts?.headers ? opts.headers : void 0
|
|
1661
1292
|
});
|
|
1662
1293
|
}, "sendAuthorizationChallengeRequest");
|
|
1663
1294
|
|
|
1664
|
-
// lib/AuthorizationCodeClientV1_0_11.ts
|
|
1665
|
-
import { CodeChallengeMethod as CodeChallengeMethod3, convertJsonToURI as convertJsonToURI4, CreateRequestObjectMode as CreateRequestObjectMode2, formPost as formPost4, JsonURIMode as JsonURIMode4, PARMode as PARMode2, ResponseType as ResponseType2 } from "@sphereon/oid4vci-common";
|
|
1666
|
-
import { Loggers as Loggers7 } from "@sphereon/ssi-types";
|
|
1667
|
-
var logger7 = Loggers7.DEFAULT.get("sphereon:oid4vci");
|
|
1668
|
-
var createAuthorizationRequestUrlV1_0_11 = /* @__PURE__ */ __name(async ({ pkce, endpointMetadata, authorizationRequest, credentialOffer, credentialsSupported }) => {
|
|
1669
|
-
const { redirectUri, clientId, requestObjectOpts = {
|
|
1670
|
-
requestObjectMode: CreateRequestObjectMode2.NONE
|
|
1671
|
-
} } = authorizationRequest;
|
|
1672
|
-
let { scope, authorizationDetails } = authorizationRequest;
|
|
1673
|
-
const parMode = endpointMetadata?.credentialIssuerMetadata?.require_pushed_authorization_requests ? PARMode2.REQUIRE : authorizationRequest.parMode ?? PARMode2.AUTO;
|
|
1674
|
-
if (!scope && !authorizationDetails) {
|
|
1675
|
-
if (!credentialOffer) {
|
|
1676
|
-
throw Error("Please provide a scope or authorization_details if no credential offer is present");
|
|
1677
|
-
}
|
|
1678
|
-
const creds = credentialOffer.credential_offer.credentials;
|
|
1679
|
-
authorizationDetails = creds.flatMap((cred) => typeof cred === "string" ? credentialsSupported : cred).filter((cred) => !!cred).map((cred) => {
|
|
1680
|
-
return {
|
|
1681
|
-
...cred,
|
|
1682
|
-
type: "openid_credential",
|
|
1683
|
-
locations: [
|
|
1684
|
-
endpointMetadata.issuer
|
|
1685
|
-
],
|
|
1686
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1687
|
-
// @ts-ignore
|
|
1688
|
-
format: cred.format
|
|
1689
|
-
};
|
|
1690
|
-
});
|
|
1691
|
-
if (!authorizationDetails || Array.isArray(authorizationDetails) && authorizationDetails.length === 0) {
|
|
1692
|
-
throw Error(`Could not create authorization details from credential offer. Please pass in explicit details`);
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
if (!endpointMetadata?.authorization_endpoint) {
|
|
1696
|
-
throw Error("Server metadata does not contain authorization endpoint");
|
|
1697
|
-
}
|
|
1698
|
-
const parEndpoint = endpointMetadata.credentialIssuerMetadata?.pushed_authorization_request_endpoint;
|
|
1699
|
-
if (!scope?.includes("openid")) {
|
|
1700
|
-
scope = [
|
|
1701
|
-
"openid",
|
|
1702
|
-
scope
|
|
1703
|
-
].filter((s) => !!s).join(" ");
|
|
1704
|
-
}
|
|
1705
|
-
let queryObj = {
|
|
1706
|
-
response_type: ResponseType2.AUTH_CODE,
|
|
1707
|
-
...!pkce.disabled && {
|
|
1708
|
-
code_challenge_method: pkce.codeChallengeMethod ?? CodeChallengeMethod3.S256,
|
|
1709
|
-
code_challenge: pkce.codeChallenge
|
|
1710
|
-
},
|
|
1711
|
-
authorization_details: JSON.stringify(handleAuthorizationDetailsV1_0_11(endpointMetadata, authorizationDetails)),
|
|
1712
|
-
...redirectUri && {
|
|
1713
|
-
redirect_uri: redirectUri
|
|
1714
|
-
},
|
|
1715
|
-
...clientId && {
|
|
1716
|
-
client_id: clientId
|
|
1717
|
-
},
|
|
1718
|
-
...credentialOffer?.issuerState && {
|
|
1719
|
-
issuer_state: credentialOffer.issuerState
|
|
1720
|
-
},
|
|
1721
|
-
scope
|
|
1722
|
-
};
|
|
1723
|
-
if (!parEndpoint && parMode === PARMode2.REQUIRE) {
|
|
1724
|
-
throw Error(`PAR mode is set to required by Authorization Server does not support PAR!`);
|
|
1725
|
-
} else if (parEndpoint && parMode !== PARMode2.NEVER) {
|
|
1726
|
-
logger7.debug(`USING PAR with endpoint ${parEndpoint}`);
|
|
1727
|
-
const parResponse = await formPost4(parEndpoint, convertJsonToURI4(queryObj, {
|
|
1728
|
-
mode: JsonURIMode4.X_FORM_WWW_URLENCODED,
|
|
1729
|
-
uriTypeProperties: [
|
|
1730
|
-
"client_id",
|
|
1731
|
-
"request_uri",
|
|
1732
|
-
"redirect_uri",
|
|
1733
|
-
"scope",
|
|
1734
|
-
"authorization_details",
|
|
1735
|
-
"issuer_state"
|
|
1736
|
-
]
|
|
1737
|
-
}), {
|
|
1738
|
-
contentType: "application/x-www-form-urlencoded",
|
|
1739
|
-
accept: "application/json"
|
|
1740
|
-
});
|
|
1741
|
-
if (parResponse.errorBody || !parResponse.successBody) {
|
|
1742
|
-
console.log(JSON.stringify(parResponse.errorBody));
|
|
1743
|
-
console.log("Falling back to regular request URI, since PAR failed");
|
|
1744
|
-
if (parMode === PARMode2.REQUIRE) {
|
|
1745
|
-
throw Error(`PAR error: ${parResponse.origResponse.statusText}`);
|
|
1746
|
-
}
|
|
1747
|
-
} else {
|
|
1748
|
-
logger7.debug(`PAR response: ${JSON.stringify(parResponse.successBody, null, 2)}`);
|
|
1749
|
-
queryObj = {
|
|
1750
|
-
request_uri: parResponse.successBody.request_uri
|
|
1751
|
-
};
|
|
1752
|
-
}
|
|
1753
|
-
}
|
|
1754
|
-
await createSignedAuthRequestWhenNeeded(queryObj, {
|
|
1755
|
-
...requestObjectOpts,
|
|
1756
|
-
aud: endpointMetadata.authorization_server
|
|
1757
|
-
});
|
|
1758
|
-
logger7.debug(`Object that will become query params: ` + JSON.stringify(queryObj, null, 2));
|
|
1759
|
-
const url = convertJsonToURI4(queryObj, {
|
|
1760
|
-
baseUrl: endpointMetadata.authorization_endpoint,
|
|
1761
|
-
uriTypeProperties: [
|
|
1762
|
-
"client_id",
|
|
1763
|
-
"request_uri",
|
|
1764
|
-
"redirect_uri",
|
|
1765
|
-
"scope",
|
|
1766
|
-
"authorization_details",
|
|
1767
|
-
"issuer_state"
|
|
1768
|
-
],
|
|
1769
|
-
// arrayTypeProperties: ['authorization_details'],
|
|
1770
|
-
mode: JsonURIMode4.X_FORM_WWW_URLENCODED
|
|
1771
|
-
});
|
|
1772
|
-
logger7.debug(`Authorization Request URL: ${url}`);
|
|
1773
|
-
return url;
|
|
1774
|
-
}, "createAuthorizationRequestUrlV1_0_11");
|
|
1775
|
-
var handleAuthorizationDetailsV1_0_11 = /* @__PURE__ */ __name((endpointMetadata, authorizationDetails) => {
|
|
1776
|
-
if (authorizationDetails) {
|
|
1777
|
-
if (typeof authorizationDetails === "string") {
|
|
1778
|
-
return authorizationDetails;
|
|
1779
|
-
}
|
|
1780
|
-
if (Array.isArray(authorizationDetails)) {
|
|
1781
|
-
return authorizationDetails.filter((value) => typeof value !== "string").map((value) => handleLocations2(endpointMetadata, typeof value === "string" ? value : {
|
|
1782
|
-
...value
|
|
1783
|
-
}));
|
|
1784
|
-
} else {
|
|
1785
|
-
return handleLocations2(endpointMetadata, {
|
|
1786
|
-
...authorizationDetails
|
|
1787
|
-
});
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
return authorizationDetails;
|
|
1791
|
-
}, "handleAuthorizationDetailsV1_0_11");
|
|
1792
|
-
var handleLocations2 = /* @__PURE__ */ __name((endpointMetadata, authorizationDetails) => {
|
|
1793
|
-
if (typeof authorizationDetails === "string") {
|
|
1794
|
-
return authorizationDetails;
|
|
1795
|
-
}
|
|
1796
|
-
if (authorizationDetails && (endpointMetadata.credentialIssuerMetadata?.authorization_server || endpointMetadata.authorization_endpoint)) {
|
|
1797
|
-
if (authorizationDetails.locations) {
|
|
1798
|
-
if (Array.isArray(authorizationDetails.locations)) {
|
|
1799
|
-
authorizationDetails.locations.push(endpointMetadata.issuer);
|
|
1800
|
-
} else {
|
|
1801
|
-
authorizationDetails.locations = [
|
|
1802
|
-
authorizationDetails.locations,
|
|
1803
|
-
endpointMetadata.issuer
|
|
1804
|
-
];
|
|
1805
|
-
}
|
|
1806
|
-
} else {
|
|
1807
|
-
authorizationDetails.locations = [
|
|
1808
|
-
endpointMetadata.issuer
|
|
1809
|
-
];
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
return authorizationDetails;
|
|
1813
|
-
}, "handleLocations");
|
|
1814
|
-
|
|
1815
1295
|
// lib/CredentialRequestClient.ts
|
|
1816
|
-
import { createDPoP as
|
|
1817
|
-
import { acquireDeferredCredential,
|
|
1818
|
-
import { Loggers as
|
|
1819
|
-
var
|
|
1296
|
+
import { createDPoP as createDPoP2, getCreateDPoPOptions as getCreateDPoPOptions2 } from "@sphereon/oid4vc-common";
|
|
1297
|
+
import { acquireDeferredCredential, isDeferredCredentialResponse, isValidURL, OpenId4VCIVersion as OpenId4VCIVersion4, post as post2, supportedOID4VCICredentialFormat, URL_NOT_VALID } from "@sphereon/oid4vci-common";
|
|
1298
|
+
import { Loggers as Loggers5 } from "@sphereon/ssi-types";
|
|
1299
|
+
var logger5 = Loggers5.DEFAULT.get("sphereon:oid4vci:credential");
|
|
1820
1300
|
async function buildProof(proofInput, opts) {
|
|
1821
1301
|
if ("proof_type" in proofInput) {
|
|
1822
1302
|
if (opts.cNonce) {
|
|
@@ -1830,6 +1310,27 @@ async function buildProof(proofInput, opts) {
|
|
|
1830
1310
|
return await proofInput.build();
|
|
1831
1311
|
}
|
|
1832
1312
|
__name(buildProof, "buildProof");
|
|
1313
|
+
function isOpenIdCredentialDetail(ad) {
|
|
1314
|
+
return typeof ad === "object" && ad !== null && ad.type === "openid_credential";
|
|
1315
|
+
}
|
|
1316
|
+
__name(isOpenIdCredentialDetail, "isOpenIdCredentialDetail");
|
|
1317
|
+
function findAuthorizationDetail(authorizationDetails, preferredConfigId) {
|
|
1318
|
+
if (!authorizationDetails) {
|
|
1319
|
+
return void 0;
|
|
1320
|
+
}
|
|
1321
|
+
const openIdCredentialDetails = authorizationDetails.filter(isOpenIdCredentialDetail);
|
|
1322
|
+
if (openIdCredentialDetails.length === 0) {
|
|
1323
|
+
return void 0;
|
|
1324
|
+
}
|
|
1325
|
+
if (preferredConfigId) {
|
|
1326
|
+
const match = openIdCredentialDetails.find((detail) => typeof detail === "object" && detail !== null && detail.credential_configuration_id === preferredConfigId);
|
|
1327
|
+
if (match) {
|
|
1328
|
+
return match;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
return openIdCredentialDetails[0];
|
|
1332
|
+
}
|
|
1333
|
+
__name(findAuthorizationDetail, "findAuthorizationDetail");
|
|
1833
1334
|
var CredentialRequestClient = class {
|
|
1834
1335
|
static {
|
|
1835
1336
|
__name(this, "CredentialRequestClient");
|
|
@@ -1869,7 +1370,10 @@ var CredentialRequestClient = class {
|
|
|
1869
1370
|
credentialIdentifier,
|
|
1870
1371
|
subjectIssuance
|
|
1871
1372
|
});
|
|
1872
|
-
|
|
1373
|
+
if (!supportedOID4VCICredentialFormat.includes(format)) {
|
|
1374
|
+
return Promise.reject(Error(`Unsupported credential format: ${format}`));
|
|
1375
|
+
}
|
|
1376
|
+
return await this.acquireCredentialsUsingRequestWithoutProof(request, format, opts.createDPoPOpts);
|
|
1873
1377
|
}
|
|
1874
1378
|
async acquireCredentialsUsingProof(opts) {
|
|
1875
1379
|
const { credentialIdentifier, credentialTypes, proofInput, format, context, subjectIssuance } = opts;
|
|
@@ -1882,32 +1386,28 @@ var CredentialRequestClient = class {
|
|
|
1882
1386
|
credentialIdentifier,
|
|
1883
1387
|
subjectIssuance
|
|
1884
1388
|
});
|
|
1885
|
-
return await this.acquireCredentialsUsingRequest(request, opts.createDPoPOpts);
|
|
1389
|
+
return await this.acquireCredentialsUsingRequest(request, format, opts.createDPoPOpts);
|
|
1886
1390
|
}
|
|
1887
|
-
async acquireCredentialsUsingRequestWithoutProof(uniformRequest, createDPoPOpts) {
|
|
1888
|
-
return await this.acquireCredentialsUsingRequestImpl(uniformRequest, createDPoPOpts);
|
|
1391
|
+
async acquireCredentialsUsingRequestWithoutProof(uniformRequest, format, createDPoPOpts) {
|
|
1392
|
+
return await this.acquireCredentialsUsingRequestImpl(uniformRequest, format, createDPoPOpts);
|
|
1889
1393
|
}
|
|
1890
|
-
async acquireCredentialsUsingRequest(uniformRequest, createDPoPOpts) {
|
|
1891
|
-
return await this.acquireCredentialsUsingRequestImpl(uniformRequest, createDPoPOpts);
|
|
1394
|
+
async acquireCredentialsUsingRequest(uniformRequest, format, createDPoPOpts) {
|
|
1395
|
+
return await this.acquireCredentialsUsingRequestImpl(uniformRequest, format, createDPoPOpts);
|
|
1892
1396
|
}
|
|
1893
|
-
async acquireCredentialsUsingRequestImpl(uniformRequest, createDPoPOpts) {
|
|
1894
|
-
if (this.version() < OpenId4VCIVersion6.VER_1_0_13) {
|
|
1895
|
-
throw new Error("Versions below v1.0.13 (draft 13) are not supported by the V13 credential request client.");
|
|
1896
|
-
}
|
|
1897
|
-
const request = getCredentialRequestForVersion(uniformRequest, this.version());
|
|
1397
|
+
async acquireCredentialsUsingRequestImpl(uniformRequest, format, createDPoPOpts) {
|
|
1898
1398
|
const credentialEndpoint = this.credentialRequestOpts.credentialEndpoint;
|
|
1899
1399
|
if (!isValidURL(credentialEndpoint)) {
|
|
1900
|
-
|
|
1400
|
+
logger5.debug(`Invalid credential endpoint: ${credentialEndpoint}`);
|
|
1901
1401
|
throw new Error(URL_NOT_VALID);
|
|
1902
1402
|
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
: ${JSON.stringify(
|
|
1403
|
+
logger5.debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
|
|
1404
|
+
logger5.debug(`request
|
|
1405
|
+
: ${JSON.stringify(uniformRequest, null, 2)}`);
|
|
1906
1406
|
const requestToken = this.credentialRequestOpts.token;
|
|
1907
|
-
let dPoP = createDPoPOpts ? await
|
|
1407
|
+
let dPoP = createDPoPOpts ? await createDPoP2(getCreateDPoPOptions2(createDPoPOpts, credentialEndpoint, {
|
|
1908
1408
|
accessToken: requestToken
|
|
1909
1409
|
})) : void 0;
|
|
1910
|
-
let response = await post2(credentialEndpoint, JSON.stringify(
|
|
1410
|
+
let response = await post2(credentialEndpoint, JSON.stringify(uniformRequest), {
|
|
1911
1411
|
bearerToken: requestToken,
|
|
1912
1412
|
...dPoP && {
|
|
1913
1413
|
customHeaders: {
|
|
@@ -1919,10 +1419,10 @@ var CredentialRequestClient = class {
|
|
|
1919
1419
|
const retryWithNonce = shouldRetryResourceRequestWithDPoPNonce(response);
|
|
1920
1420
|
if (retryWithNonce.ok && createDPoPOpts) {
|
|
1921
1421
|
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
1922
|
-
dPoP = await
|
|
1422
|
+
dPoP = await createDPoP2(getCreateDPoPOptions2(createDPoPOpts, credentialEndpoint, {
|
|
1923
1423
|
accessToken: requestToken
|
|
1924
1424
|
}));
|
|
1925
|
-
response = await post2(credentialEndpoint, JSON.stringify(
|
|
1425
|
+
response = await post2(credentialEndpoint, JSON.stringify(uniformRequest), {
|
|
1926
1426
|
bearerToken: requestToken,
|
|
1927
1427
|
...createDPoPOpts && {
|
|
1928
1428
|
customHeaders: {
|
|
@@ -1945,7 +1445,7 @@ var CredentialRequestClient = class {
|
|
|
1945
1445
|
throw Error("Subject signing was requested, but issuer did not provide the options in its response");
|
|
1946
1446
|
}
|
|
1947
1447
|
}
|
|
1948
|
-
|
|
1448
|
+
logger5.debug(`Credential endpoint ${credentialEndpoint} response:\r
|
|
1949
1449
|
${JSON.stringify(response, null, 2)}`);
|
|
1950
1450
|
return {
|
|
1951
1451
|
...response,
|
|
@@ -1982,44 +1482,15 @@ ${JSON.stringify(response, null, 2)}`);
|
|
|
1982
1482
|
return await this.createCredentialRequestImpl(opts);
|
|
1983
1483
|
}
|
|
1984
1484
|
async createCredentialRequestImpl(opts) {
|
|
1985
|
-
const { proofInput, credentialIdentifier
|
|
1485
|
+
const { proofInput, credentialIdentifier, credentialConfigurationId } = opts;
|
|
1986
1486
|
let proof = void 0;
|
|
1987
1487
|
if (proofInput) {
|
|
1988
1488
|
proof = await buildProof(proofInput, opts);
|
|
1989
1489
|
}
|
|
1990
|
-
if (
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
return {
|
|
1995
|
-
credential_identifier,
|
|
1996
|
-
...proof && {
|
|
1997
|
-
proof
|
|
1998
|
-
}
|
|
1999
|
-
};
|
|
2000
|
-
}
|
|
2001
|
-
const formatSelection = opts.format ?? this.credentialRequestOpts.format;
|
|
2002
|
-
if (!formatSelection) {
|
|
2003
|
-
throw Error(`Format of credential to be issued is missing`);
|
|
2004
|
-
}
|
|
2005
|
-
const format = getUniformFormat(formatSelection);
|
|
2006
|
-
const typesSelection = opts?.credentialTypes && (typeof opts.credentialTypes === "string" || opts.credentialTypes.length > 0) ? opts.credentialTypes : this.credentialRequestOpts.credentialTypes;
|
|
2007
|
-
if (!typesSelection) {
|
|
2008
|
-
throw Error(`Credential type(s) need to be provided`);
|
|
2009
|
-
}
|
|
2010
|
-
const types = Array.isArray(typesSelection) ? typesSelection : [
|
|
2011
|
-
typesSelection
|
|
2012
|
-
];
|
|
2013
|
-
if (types.length === 0) {
|
|
2014
|
-
throw Error(`Credential type(s) need to be provided`);
|
|
2015
|
-
}
|
|
2016
|
-
const issuer_state = this.credentialRequestOpts.issuerState;
|
|
2017
|
-
if (format === "jwt_vc_json" || format === "jwt_vc") {
|
|
2018
|
-
return {
|
|
2019
|
-
credential_definition: {
|
|
2020
|
-
type: types
|
|
2021
|
-
},
|
|
2022
|
-
format,
|
|
1490
|
+
if (this.version() >= OpenId4VCIVersion4.VER_1_0_15) {
|
|
1491
|
+
const authDetail = findAuthorizationDetail(this.credentialRequestOpts.authorizationDetails, credentialConfigurationId ?? credentialIdentifier);
|
|
1492
|
+
const issuer_state = this.credentialRequestOpts.issuerState;
|
|
1493
|
+
const commonBody = {
|
|
2023
1494
|
...issuer_state && {
|
|
2024
1495
|
issuer_state
|
|
2025
1496
|
},
|
|
@@ -2028,64 +1499,43 @@ ${JSON.stringify(response, null, 2)}`);
|
|
|
2028
1499
|
},
|
|
2029
1500
|
...opts.subjectIssuance
|
|
2030
1501
|
};
|
|
2031
|
-
|
|
2032
|
-
if (
|
|
2033
|
-
|
|
1502
|
+
const authDetailObj = authDetail && typeof authDetail === "object" ? authDetail : null;
|
|
1503
|
+
if (authDetailObj?.credential_identifier) {
|
|
1504
|
+
return {
|
|
1505
|
+
credential_identifier: authDetailObj.credential_identifier,
|
|
1506
|
+
...commonBody
|
|
1507
|
+
};
|
|
2034
1508
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
}
|
|
2040
|
-
...proof && {
|
|
2041
|
-
proof
|
|
2042
|
-
},
|
|
2043
|
-
...opts.subjectIssuance,
|
|
2044
|
-
credential_definition: {
|
|
2045
|
-
type: types,
|
|
2046
|
-
"@context": opts.context
|
|
2047
|
-
}
|
|
2048
|
-
};
|
|
2049
|
-
} else if (format === "vc+sd-jwt") {
|
|
2050
|
-
if (types.length > 1) {
|
|
2051
|
-
throw Error(`Only a single credential type is supported for ${format}`);
|
|
1509
|
+
if (authDetailObj?.credential_identifiers && authDetailObj.credential_identifiers.length > 0) {
|
|
1510
|
+
return {
|
|
1511
|
+
credential_identifier: authDetailObj.credential_identifiers[0],
|
|
1512
|
+
...commonBody
|
|
1513
|
+
};
|
|
2052
1514
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
proof
|
|
2060
|
-
},
|
|
2061
|
-
vct: types[0],
|
|
2062
|
-
...opts.subjectIssuance
|
|
2063
|
-
};
|
|
2064
|
-
} else if (format === "mso_mdoc") {
|
|
2065
|
-
if (types.length > 1) {
|
|
2066
|
-
throw Error(`Only a single credential type is supported for ${format}`);
|
|
1515
|
+
const configId = credentialConfigurationId ?? authDetailObj?.credential_configuration_id ?? this._credentialRequestOpts.credentialConfigurationId;
|
|
1516
|
+
if (configId) {
|
|
1517
|
+
return {
|
|
1518
|
+
credential_configuration_id: configId,
|
|
1519
|
+
...commonBody
|
|
1520
|
+
};
|
|
2067
1521
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
},
|
|
2076
|
-
doctype: types[0],
|
|
2077
|
-
...opts.subjectIssuance
|
|
2078
|
-
};
|
|
1522
|
+
if (credentialIdentifier) {
|
|
1523
|
+
return {
|
|
1524
|
+
credential_identifier: credentialIdentifier,
|
|
1525
|
+
...commonBody
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
return Promise.reject(Error("No credential_identifier or credential_configuration_id available for v1.0-15 request"));
|
|
2079
1529
|
}
|
|
2080
|
-
throw new Error(`Unsupported
|
|
1530
|
+
throw new Error(`Unsupported version: ${this.version()}`);
|
|
2081
1531
|
}
|
|
2082
1532
|
version() {
|
|
2083
|
-
return this.credentialRequestOpts?.version ??
|
|
1533
|
+
return this.credentialRequestOpts?.version ?? OpenId4VCIVersion4.VER_1_0_15;
|
|
2084
1534
|
}
|
|
2085
1535
|
};
|
|
2086
1536
|
|
|
2087
1537
|
// lib/CredentialOfferClient.ts
|
|
2088
|
-
import { convertJsonToURI as
|
|
1538
|
+
import { convertJsonToURI as convertJsonToURI3, convertURIToJsonObject, determineSpecVersionFromURI, OpenId4VCIVersion as OpenId4VCIVersion5, PRE_AUTH_GRANT_LITERAL as PRE_AUTH_GRANT_LITERAL3, toUniformCredentialOfferRequest as toUniformCredentialOfferRequest2 } from "@sphereon/oid4vci-common";
|
|
2089
1539
|
var CredentialOfferClient = class {
|
|
2090
1540
|
static {
|
|
2091
1541
|
__name(this, "CredentialOfferClient");
|
|
@@ -2101,132 +1551,15 @@ var CredentialOfferClient = class {
|
|
|
2101
1551
|
const version = determineSpecVersionFromURI(uri);
|
|
2102
1552
|
LOG.log(`Offer URL determined to be of version ${version}`);
|
|
2103
1553
|
let credentialOffer;
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
credentialOfferPayload = convertURIToJsonObject(uri, {
|
|
2107
|
-
arrayTypeProperties: [
|
|
2108
|
-
"credential_type"
|
|
2109
|
-
],
|
|
2110
|
-
requiredProperties: uri.includes("credential_offer=") ? [
|
|
2111
|
-
"credential_offer"
|
|
2112
|
-
] : [
|
|
2113
|
-
"issuer",
|
|
2114
|
-
"credential_type"
|
|
2115
|
-
]
|
|
2116
|
-
});
|
|
2117
|
-
credentialOffer = {
|
|
2118
|
-
credential_offer: credentialOfferPayload
|
|
2119
|
-
};
|
|
1554
|
+
if (uri.includes("credential_offer_uri")) {
|
|
1555
|
+
credentialOffer = await handleCredentialOfferUri(uri);
|
|
2120
1556
|
} else {
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
credentialOffer = convertURIToJsonObject(uri, {
|
|
2125
|
-
// It must have the '=' sign after credential_offer otherwise the uri will get split at openid_credential_offer
|
|
2126
|
-
arrayTypeProperties: uri.includes("credential_offer_uri=") ? [
|
|
2127
|
-
"credential_offer_uri="
|
|
2128
|
-
] : [
|
|
2129
|
-
"credential_offer="
|
|
2130
|
-
],
|
|
2131
|
-
requiredProperties: uri.includes("credential_offer_uri=") ? [
|
|
2132
|
-
"credential_offer_uri="
|
|
2133
|
-
] : [
|
|
2134
|
-
"credential_offer="
|
|
2135
|
-
]
|
|
2136
|
-
});
|
|
2137
|
-
}
|
|
2138
|
-
if (credentialOffer?.credential_offer_uri === void 0 && !credentialOffer?.credential_offer) {
|
|
2139
|
-
throw Error("Either a credential_offer or credential_offer_uri should be present in " + uri);
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
const request = await toUniformCredentialOfferRequest3(credentialOffer, {
|
|
2143
|
-
...opts,
|
|
2144
|
-
version
|
|
2145
|
-
});
|
|
2146
|
-
return {
|
|
2147
|
-
...constructBaseResponse(request, scheme, baseUrl),
|
|
2148
|
-
userPinRequired: request.credential_offer?.grants?.[PRE_AUTH_GRANT_LITERAL4]?.user_pin_required ?? !!request.credential_offer?.grants?.[PRE_AUTH_GRANT_LITERAL4]?.tx_code ?? false
|
|
2149
|
-
};
|
|
2150
|
-
}
|
|
2151
|
-
static toURI(requestWithBaseUrl, opts) {
|
|
2152
|
-
LOG.debug(`Credential Offer Request with base URL: ${JSON.stringify(requestWithBaseUrl)}`);
|
|
2153
|
-
const version = opts?.version ?? requestWithBaseUrl.version;
|
|
2154
|
-
let baseUrl = requestWithBaseUrl.baseUrl.includes(requestWithBaseUrl.scheme) ? requestWithBaseUrl.baseUrl : `${requestWithBaseUrl.scheme.replace("://", "")}://${requestWithBaseUrl.baseUrl}`;
|
|
2155
|
-
let param;
|
|
2156
|
-
const isUri = requestWithBaseUrl.credential_offer_uri !== void 0;
|
|
2157
|
-
if (version.valueOf() >= OpenId4VCIVersion7.VER_1_0_11.valueOf()) {
|
|
2158
|
-
if (!baseUrl.includes("?")) {
|
|
2159
|
-
param = isUri ? "credential_offer_uri" : "credential_offer";
|
|
2160
|
-
} else {
|
|
2161
|
-
const split = baseUrl.split("?");
|
|
2162
|
-
if (split.length > 1 && split[1] !== "") {
|
|
2163
|
-
if (baseUrl.endsWith("&")) {
|
|
2164
|
-
param = isUri ? "credential_offer_uri" : "credential_offer";
|
|
2165
|
-
} else if (!baseUrl.endsWith("=")) {
|
|
2166
|
-
baseUrl += `&`;
|
|
2167
|
-
param = isUri ? "credential_offer_uri" : "credential_offer";
|
|
2168
|
-
}
|
|
2169
|
-
}
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
return convertJsonToURI5(requestWithBaseUrl.credential_offer_uri ?? requestWithBaseUrl.original_credential_offer, {
|
|
2173
|
-
baseUrl,
|
|
2174
|
-
arrayTypeProperties: isUri ? [] : [
|
|
2175
|
-
"credential_type"
|
|
2176
|
-
],
|
|
2177
|
-
uriTypeProperties: isUri ? [
|
|
2178
|
-
"credential_offer_uri"
|
|
2179
|
-
] : version >= OpenId4VCIVersion7.VER_1_0_13 ? [
|
|
2180
|
-
"credential_issuer",
|
|
2181
|
-
"credential_type"
|
|
2182
|
-
] : [
|
|
2183
|
-
"issuer",
|
|
2184
|
-
"credential_type"
|
|
2185
|
-
],
|
|
2186
|
-
param,
|
|
2187
|
-
version
|
|
2188
|
-
});
|
|
2189
|
-
}
|
|
2190
|
-
};
|
|
2191
|
-
|
|
2192
|
-
// lib/CredentialOfferClientV1_0_11.ts
|
|
2193
|
-
import { convertJsonToURI as convertJsonToURI6, convertURIToJsonObject as convertURIToJsonObject2, determineSpecVersionFromURI as determineSpecVersionFromURI2, getClientIdFromCredentialOfferPayload as getClientIdFromCredentialOfferPayload2, OpenId4VCIVersion as OpenId4VCIVersion8, PRE_AUTH_CODE_LITERAL as PRE_AUTH_CODE_LITERAL4, PRE_AUTH_GRANT_LITERAL as PRE_AUTH_GRANT_LITERAL5, toUniformCredentialOfferRequest as toUniformCredentialOfferRequest4 } from "@sphereon/oid4vci-common";
|
|
2194
|
-
import { Loggers as Loggers9 } from "@sphereon/ssi-types";
|
|
2195
|
-
var logger9 = Loggers9.DEFAULT.get("sphereon:oid4vci:offer");
|
|
2196
|
-
var CredentialOfferClientV1_0_11 = class {
|
|
2197
|
-
static {
|
|
2198
|
-
__name(this, "CredentialOfferClientV1_0_11");
|
|
2199
|
-
}
|
|
2200
|
-
static async fromURI(uri, opts) {
|
|
2201
|
-
logger9.debug(`Credential Offer URI: ${uri}`);
|
|
2202
|
-
if (!uri.includes("?") || !uri.includes("://")) {
|
|
2203
|
-
logger9.debug(`Invalid Credential Offer URI: ${uri}`);
|
|
2204
|
-
throw Error(`Invalid Credential Offer Request`);
|
|
2205
|
-
}
|
|
2206
|
-
const scheme = uri.split("://")[0];
|
|
2207
|
-
const baseUrl = uri.split("?")[0];
|
|
2208
|
-
const version = determineSpecVersionFromURI2(uri);
|
|
2209
|
-
let credentialOffer;
|
|
2210
|
-
let credentialOfferPayload;
|
|
2211
|
-
if (version < OpenId4VCIVersion8.VER_1_0_11) {
|
|
2212
|
-
credentialOfferPayload = convertURIToJsonObject2(uri, {
|
|
2213
|
-
arrayTypeProperties: [
|
|
2214
|
-
"credential_type"
|
|
2215
|
-
],
|
|
2216
|
-
requiredProperties: uri.includes("credential_offer_uri=") ? [
|
|
1557
|
+
credentialOffer = convertURIToJsonObject(uri, {
|
|
1558
|
+
// It must have the '=' sign after credential_offer otherwise the uri will get split at openid_credential_offer
|
|
1559
|
+
arrayTypeProperties: uri.includes("credential_offer_uri=") ? [
|
|
2217
1560
|
"credential_offer_uri="
|
|
2218
1561
|
] : [
|
|
2219
|
-
"
|
|
2220
|
-
"credential_type="
|
|
2221
|
-
]
|
|
2222
|
-
});
|
|
2223
|
-
credentialOffer = {
|
|
2224
|
-
credential_offer: credentialOfferPayload
|
|
2225
|
-
};
|
|
2226
|
-
} else {
|
|
2227
|
-
credentialOffer = convertURIToJsonObject2(uri, {
|
|
2228
|
-
arrayTypeProperties: [
|
|
2229
|
-
"credentials"
|
|
1562
|
+
"credential_offer="
|
|
2230
1563
|
],
|
|
2231
1564
|
requiredProperties: uri.includes("credential_offer_uri=") ? [
|
|
2232
1565
|
"credential_offer_uri="
|
|
@@ -2234,39 +1567,26 @@ var CredentialOfferClientV1_0_11 = class {
|
|
|
2234
1567
|
"credential_offer="
|
|
2235
1568
|
]
|
|
2236
1569
|
});
|
|
2237
|
-
if (credentialOffer?.credential_offer_uri === void 0 && !credentialOffer?.credential_offer) {
|
|
2238
|
-
throw Error("Either a credential_offer or credential_offer_uri should be present in " + uri);
|
|
2239
|
-
}
|
|
2240
1570
|
}
|
|
2241
|
-
|
|
1571
|
+
if (credentialOffer?.credential_offer_uri === void 0 && !credentialOffer?.credential_offer) {
|
|
1572
|
+
throw Error("Either a credential_offer or credential_offer_uri should be present in " + uri);
|
|
1573
|
+
}
|
|
1574
|
+
const request = await toUniformCredentialOfferRequest2(credentialOffer, {
|
|
2242
1575
|
...opts,
|
|
2243
1576
|
version
|
|
2244
1577
|
});
|
|
2245
|
-
const clientId = getClientIdFromCredentialOfferPayload2(request.credential_offer);
|
|
2246
|
-
const grants = request.credential_offer?.grants;
|
|
2247
1578
|
return {
|
|
2248
|
-
scheme,
|
|
2249
|
-
|
|
2250
|
-
...clientId && {
|
|
2251
|
-
clientId
|
|
2252
|
-
},
|
|
2253
|
-
...request,
|
|
2254
|
-
...grants?.authorization_code?.issuer_state && {
|
|
2255
|
-
issuerState: grants.authorization_code.issuer_state
|
|
2256
|
-
},
|
|
2257
|
-
...grants?.[PRE_AUTH_GRANT_LITERAL5]?.[PRE_AUTH_CODE_LITERAL4] && {
|
|
2258
|
-
preAuthorizedCode: grants[PRE_AUTH_GRANT_LITERAL5][PRE_AUTH_CODE_LITERAL4]
|
|
2259
|
-
},
|
|
2260
|
-
userPinRequired: !!(request.credential_offer?.grants?.[PRE_AUTH_GRANT_LITERAL5]?.user_pin_required ?? false)
|
|
1579
|
+
...constructBaseResponse(request, scheme, baseUrl),
|
|
1580
|
+
userPinRequired: request.credential_offer?.grants?.[PRE_AUTH_GRANT_LITERAL3]?.user_pin_required ?? !!request.credential_offer?.grants?.[PRE_AUTH_GRANT_LITERAL3]?.tx_code ?? false
|
|
2261
1581
|
};
|
|
2262
1582
|
}
|
|
2263
1583
|
static toURI(requestWithBaseUrl, opts) {
|
|
2264
|
-
|
|
1584
|
+
LOG.debug(`Credential Offer Request with base URL: ${JSON.stringify(requestWithBaseUrl)}`);
|
|
2265
1585
|
const version = opts?.version ?? requestWithBaseUrl.version;
|
|
2266
1586
|
let baseUrl = requestWithBaseUrl.baseUrl.includes(requestWithBaseUrl.scheme) ? requestWithBaseUrl.baseUrl : `${requestWithBaseUrl.scheme.replace("://", "")}://${requestWithBaseUrl.baseUrl}`;
|
|
2267
1587
|
let param;
|
|
2268
1588
|
const isUri = requestWithBaseUrl.credential_offer_uri !== void 0;
|
|
2269
|
-
if (version.valueOf() >=
|
|
1589
|
+
if (version.valueOf() >= OpenId4VCIVersion5.VER_1_0_15.valueOf()) {
|
|
2270
1590
|
if (!baseUrl.includes("?")) {
|
|
2271
1591
|
param = isUri ? "credential_offer_uri" : "credential_offer";
|
|
2272
1592
|
} else {
|
|
@@ -2281,14 +1601,14 @@ var CredentialOfferClientV1_0_11 = class {
|
|
|
2281
1601
|
}
|
|
2282
1602
|
}
|
|
2283
1603
|
}
|
|
2284
|
-
return
|
|
1604
|
+
return convertJsonToURI3(requestWithBaseUrl.credential_offer_uri ?? requestWithBaseUrl.original_credential_offer, {
|
|
2285
1605
|
baseUrl,
|
|
2286
1606
|
arrayTypeProperties: isUri ? [] : [
|
|
2287
1607
|
"credential_type"
|
|
2288
1608
|
],
|
|
2289
1609
|
uriTypeProperties: isUri ? [
|
|
2290
1610
|
"credential_offer_uri"
|
|
2291
|
-
] : version >=
|
|
1611
|
+
] : version >= OpenId4VCIVersion5.VER_1_0_15 ? [
|
|
2292
1612
|
"credential_issuer",
|
|
2293
1613
|
"credential_type"
|
|
2294
1614
|
] : [
|
|
@@ -2301,28 +1621,28 @@ var CredentialOfferClientV1_0_11 = class {
|
|
|
2301
1621
|
}
|
|
2302
1622
|
};
|
|
2303
1623
|
|
|
2304
|
-
// lib/
|
|
2305
|
-
import { convertJsonToURI as
|
|
2306
|
-
import { Loggers as
|
|
2307
|
-
var
|
|
2308
|
-
var
|
|
1624
|
+
// lib/CredentialOfferClientV1_0_15.ts
|
|
1625
|
+
import { convertJsonToURI as convertJsonToURI4, convertURIToJsonObject as convertURIToJsonObject2, determineSpecVersionFromURI as determineSpecVersionFromURI2, JsonURIMode as JsonURIMode3, PRE_AUTH_GRANT_LITERAL as PRE_AUTH_GRANT_LITERAL4, toUniformCredentialOfferRequest as toUniformCredentialOfferRequest3 } from "@sphereon/oid4vci-common";
|
|
1626
|
+
import { Loggers as Loggers6 } from "@sphereon/ssi-types";
|
|
1627
|
+
var logger6 = Loggers6.DEFAULT.get("sphereon:oid4vci:offer");
|
|
1628
|
+
var CredentialOfferClientV1_0_15 = class {
|
|
2309
1629
|
static {
|
|
2310
|
-
__name(this, "
|
|
1630
|
+
__name(this, "CredentialOfferClientV1_0_15");
|
|
2311
1631
|
}
|
|
2312
1632
|
static async fromURI(uri, opts) {
|
|
2313
|
-
|
|
1633
|
+
logger6.debug(`Credential Offer URI: ${uri}`);
|
|
2314
1634
|
if (!uri.includes("?") || !uri.includes("://")) {
|
|
2315
|
-
|
|
2316
|
-
|
|
1635
|
+
logger6.debug(`Invalid Credential Offer URI: ${uri}`);
|
|
1636
|
+
return Promise.reject(Error(`Invalid Credential Offer Request`));
|
|
2317
1637
|
}
|
|
2318
1638
|
const scheme = uri.split("://")[0];
|
|
2319
1639
|
const baseUrl = uri.split("?")[0];
|
|
2320
|
-
const version =
|
|
1640
|
+
const version = determineSpecVersionFromURI2(uri);
|
|
2321
1641
|
let credentialOffer;
|
|
2322
1642
|
if (uri.includes("credential_offer_uri")) {
|
|
2323
1643
|
credentialOffer = await handleCredentialOfferUri(uri);
|
|
2324
1644
|
} else {
|
|
2325
|
-
credentialOffer =
|
|
1645
|
+
credentialOffer = convertURIToJsonObject2(uri, {
|
|
2326
1646
|
// It must have the '=' sign after credential_offer otherwise the uri will get split at openid_credential_offer
|
|
2327
1647
|
arrayTypeProperties: uri.includes("credential_offer_uri=") ? [
|
|
2328
1648
|
"credential_configuration_ids",
|
|
@@ -2339,276 +1659,91 @@ var CredentialOfferClientV1_0_13 = class {
|
|
|
2339
1659
|
});
|
|
2340
1660
|
}
|
|
2341
1661
|
if (credentialOffer?.credential_offer_uri === void 0 && !credentialOffer?.credential_offer) {
|
|
2342
|
-
|
|
1662
|
+
return Promise.reject(Error("Either a credential_offer or credential_offer_uri should be present in " + uri));
|
|
2343
1663
|
}
|
|
2344
|
-
const request = await
|
|
1664
|
+
const request = await toUniformCredentialOfferRequest3(credentialOffer, {
|
|
2345
1665
|
...opts,
|
|
2346
1666
|
version
|
|
2347
1667
|
});
|
|
2348
1668
|
return {
|
|
2349
1669
|
...constructBaseResponse(request, scheme, baseUrl),
|
|
2350
|
-
userPinRequired: !!(request.credential_offer?.grants?.[
|
|
1670
|
+
userPinRequired: !!(request.credential_offer?.grants?.[PRE_AUTH_GRANT_LITERAL4]?.tx_code ?? false)
|
|
2351
1671
|
};
|
|
2352
1672
|
}
|
|
2353
1673
|
static toURI(requestWithBaseUrl, opts) {
|
|
2354
|
-
|
|
1674
|
+
logger6.debug(`Credential Offer Request with base URL: ${JSON.stringify(requestWithBaseUrl)}`);
|
|
2355
1675
|
const version = opts?.version ?? requestWithBaseUrl.version;
|
|
2356
1676
|
let baseUrl = requestWithBaseUrl.baseUrl.includes(requestWithBaseUrl.scheme) ? requestWithBaseUrl.baseUrl : `${requestWithBaseUrl.scheme.replace("://", "")}://${requestWithBaseUrl.baseUrl}`;
|
|
2357
|
-
let param;
|
|
2358
1677
|
const isUri = requestWithBaseUrl.credential_offer_uri !== void 0;
|
|
2359
|
-
if (
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
}
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
param = isUri ? "credential_offer_uri" : "credential_offer";
|
|
2370
|
-
}
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
return convertJsonToURI7(requestWithBaseUrl.credential_offer_uri ?? requestWithBaseUrl.original_credential_offer, {
|
|
2375
|
-
baseUrl,
|
|
2376
|
-
arrayTypeProperties: isUri ? [] : [
|
|
2377
|
-
"credential_type"
|
|
2378
|
-
],
|
|
2379
|
-
uriTypeProperties: isUri ? [
|
|
2380
|
-
"credential_offer_uri"
|
|
2381
|
-
] : version >= OpenId4VCIVersion9.VER_1_0_13 ? [
|
|
2382
|
-
"credential_issuer",
|
|
2383
|
-
"credential_type"
|
|
2384
|
-
] : [
|
|
2385
|
-
"issuer",
|
|
2386
|
-
"credential_type"
|
|
2387
|
-
],
|
|
2388
|
-
param,
|
|
2389
|
-
version
|
|
2390
|
-
});
|
|
2391
|
-
}
|
|
2392
|
-
};
|
|
2393
|
-
|
|
2394
|
-
// lib/CredentialRequestClientV1_0_11.ts
|
|
2395
|
-
import { createDPoP as createDPoP4, getCreateDPoPOptions as getCreateDPoPOptions4 } from "@sphereon/oid4vc-common";
|
|
2396
|
-
import { acquireDeferredCredential as acquireDeferredCredential2, getCredentialRequestForVersion as getCredentialRequestForVersion2, getUniformFormat as getUniformFormat2, isDeferredCredentialResponse as isDeferredCredentialResponse2, isValidURL as isValidURL2, OpenId4VCIVersion as OpenId4VCIVersion10, post as post3, URL_NOT_VALID as URL_NOT_VALID2 } from "@sphereon/oid4vci-common";
|
|
2397
|
-
import { Loggers as Loggers11 } from "@sphereon/ssi-types";
|
|
2398
|
-
var logger11 = Loggers11.DEFAULT.get("sphereon:oid4vci:credential");
|
|
2399
|
-
var CredentialRequestClientV1_0_11 = class {
|
|
2400
|
-
static {
|
|
2401
|
-
__name(this, "CredentialRequestClientV1_0_11");
|
|
2402
|
-
}
|
|
2403
|
-
_credentialRequestOpts;
|
|
2404
|
-
_isDeferred = false;
|
|
2405
|
-
get credentialRequestOpts() {
|
|
2406
|
-
return this._credentialRequestOpts;
|
|
2407
|
-
}
|
|
2408
|
-
isDeferred() {
|
|
2409
|
-
return this._isDeferred;
|
|
2410
|
-
}
|
|
2411
|
-
getCredentialEndpoint() {
|
|
2412
|
-
return this.credentialRequestOpts.credentialEndpoint;
|
|
2413
|
-
}
|
|
2414
|
-
getDeferredCredentialEndpoint() {
|
|
2415
|
-
return this.credentialRequestOpts.deferredCredentialEndpoint;
|
|
2416
|
-
}
|
|
2417
|
-
constructor(builder) {
|
|
2418
|
-
this._credentialRequestOpts = {
|
|
2419
|
-
...builder
|
|
2420
|
-
};
|
|
2421
|
-
}
|
|
2422
|
-
async acquireCredentialsUsingProof(opts) {
|
|
2423
|
-
const { credentialTypes, proofInput, format, context } = opts;
|
|
2424
|
-
const request = await this.createCredentialRequest({
|
|
2425
|
-
proofInput,
|
|
2426
|
-
credentialTypes,
|
|
2427
|
-
context,
|
|
2428
|
-
format,
|
|
2429
|
-
version: this.version()
|
|
2430
|
-
});
|
|
2431
|
-
return await this.acquireCredentialsUsingRequest(request, opts.createDPoPOpts);
|
|
2432
|
-
}
|
|
2433
|
-
async acquireCredentialsUsingRequest(uniformRequest, createDPoPOpts) {
|
|
2434
|
-
const request = getCredentialRequestForVersion2(uniformRequest, this.version());
|
|
2435
|
-
const credentialEndpoint = this.credentialRequestOpts.credentialEndpoint;
|
|
2436
|
-
if (!isValidURL2(credentialEndpoint)) {
|
|
2437
|
-
logger11.debug(`Invalid credential endpoint: ${credentialEndpoint}`);
|
|
2438
|
-
throw new Error(URL_NOT_VALID2);
|
|
2439
|
-
}
|
|
2440
|
-
logger11.debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
|
|
2441
|
-
logger11.debug(`request
|
|
2442
|
-
: ${JSON.stringify(request, null, 2)}`);
|
|
2443
|
-
const requestToken = this.credentialRequestOpts.token;
|
|
2444
|
-
let dPoP = createDPoPOpts ? await createDPoP4(getCreateDPoPOptions4(createDPoPOpts, credentialEndpoint, {
|
|
2445
|
-
accessToken: requestToken
|
|
2446
|
-
})) : void 0;
|
|
2447
|
-
let response = await post3(credentialEndpoint, JSON.stringify(request), {
|
|
2448
|
-
bearerToken: requestToken,
|
|
2449
|
-
customHeaders: {
|
|
2450
|
-
...createDPoPOpts && {
|
|
2451
|
-
dpop: dPoP
|
|
2452
|
-
}
|
|
2453
|
-
}
|
|
2454
|
-
});
|
|
2455
|
-
let nextDPoPNonce = createDPoPOpts?.jwtPayloadProps.nonce;
|
|
2456
|
-
const retryWithNonce = shouldRetryResourceRequestWithDPoPNonce(response);
|
|
2457
|
-
if (retryWithNonce.ok && createDPoPOpts) {
|
|
2458
|
-
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
2459
|
-
dPoP = await createDPoP4(getCreateDPoPOptions4(createDPoPOpts, credentialEndpoint, {
|
|
2460
|
-
accessToken: requestToken
|
|
2461
|
-
}));
|
|
2462
|
-
response = await post3(credentialEndpoint, JSON.stringify(request), {
|
|
2463
|
-
bearerToken: requestToken,
|
|
2464
|
-
customHeaders: {
|
|
2465
|
-
...createDPoPOpts && {
|
|
2466
|
-
dpop: dPoP
|
|
2467
|
-
}
|
|
2468
|
-
}
|
|
1678
|
+
if (isUri) {
|
|
1679
|
+
return convertJsonToURI4({
|
|
1680
|
+
credential_offer_uri: requestWithBaseUrl.credential_offer_uri
|
|
1681
|
+
}, {
|
|
1682
|
+
baseUrl,
|
|
1683
|
+
uriTypeProperties: [
|
|
1684
|
+
"credential_offer_uri"
|
|
1685
|
+
],
|
|
1686
|
+
param: "credential_offer_uri",
|
|
1687
|
+
version
|
|
2469
1688
|
});
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
bearerToken: this.credentialRequestOpts.token
|
|
1689
|
+
} else {
|
|
1690
|
+
return convertJsonToURI4(requestWithBaseUrl.original_credential_offer, {
|
|
1691
|
+
baseUrl,
|
|
1692
|
+
param: "credential_offer",
|
|
1693
|
+
mode: JsonURIMode3.JSON_STRINGIFY,
|
|
1694
|
+
version
|
|
2477
1695
|
});
|
|
2478
1696
|
}
|
|
2479
|
-
response.access_token = requestToken;
|
|
2480
|
-
logger11.debug(`Credential endpoint ${credentialEndpoint} response:\r
|
|
2481
|
-
${JSON.stringify(response, null, 2)}`);
|
|
2482
|
-
return {
|
|
2483
|
-
...response,
|
|
2484
|
-
...nextDPoPNonce && {
|
|
2485
|
-
params: {
|
|
2486
|
-
dpop: {
|
|
2487
|
-
dpopNonce: nextDPoPNonce
|
|
2488
|
-
}
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
};
|
|
2492
|
-
}
|
|
2493
|
-
async acquireDeferredCredential(response, opts) {
|
|
2494
|
-
const transactionId = response.transaction_id;
|
|
2495
|
-
const bearerToken = response.acceptance_token ?? opts?.bearerToken;
|
|
2496
|
-
const deferredCredentialEndpoint = this.getDeferredCredentialEndpoint();
|
|
2497
|
-
if (!deferredCredentialEndpoint) {
|
|
2498
|
-
throw Error(`No deferred credential endpoint supplied.`);
|
|
2499
|
-
} else if (!bearerToken) {
|
|
2500
|
-
throw Error(`No bearer token present and refresh for defered endpoint not supported yet`);
|
|
2501
|
-
}
|
|
2502
|
-
return await acquireDeferredCredential2({
|
|
2503
|
-
bearerToken,
|
|
2504
|
-
transactionId,
|
|
2505
|
-
deferredCredentialEndpoint,
|
|
2506
|
-
deferredCredentialAwait: this.credentialRequestOpts.deferredCredentialAwait,
|
|
2507
|
-
deferredCredentialIntervalInMS: this.credentialRequestOpts.deferredCredentialIntervalInMS
|
|
2508
|
-
});
|
|
2509
|
-
}
|
|
2510
|
-
async createCredentialRequest(opts) {
|
|
2511
|
-
const { proofInput } = opts;
|
|
2512
|
-
const formatSelection = opts.format ?? this.credentialRequestOpts.format;
|
|
2513
|
-
if (!formatSelection) {
|
|
2514
|
-
throw Error(`Format of credential to be issued is missing`);
|
|
2515
|
-
}
|
|
2516
|
-
const format = getUniformFormat2(formatSelection);
|
|
2517
|
-
const typesSelection = opts?.credentialTypes && (typeof opts.credentialTypes === "string" || opts.credentialTypes.length > 0) ? opts.credentialTypes : this.credentialRequestOpts.credentialTypes;
|
|
2518
|
-
const types = Array.isArray(typesSelection) ? typesSelection : [
|
|
2519
|
-
typesSelection
|
|
2520
|
-
];
|
|
2521
|
-
if (types.length === 0) {
|
|
2522
|
-
throw Error(`Credential type(s) need to be provided`);
|
|
2523
|
-
} else if (!this.isV11OrHigher() && types.length !== 1) {
|
|
2524
|
-
throw Error("Only a single credential type is supported for V8/V9");
|
|
2525
|
-
}
|
|
2526
|
-
const proof = await buildProof(proofInput, opts);
|
|
2527
|
-
if (format === "jwt_vc_json" || format === "jwt_vc") {
|
|
2528
|
-
return {
|
|
2529
|
-
types,
|
|
2530
|
-
format,
|
|
2531
|
-
proof
|
|
2532
|
-
};
|
|
2533
|
-
} else if (format === "jwt_vc_json-ld" || format === "ldp_vc") {
|
|
2534
|
-
if (this.version() >= OpenId4VCIVersion10.VER_1_0_12 && !opts.context) {
|
|
2535
|
-
throw Error("No @context value present, but it is required");
|
|
2536
|
-
}
|
|
2537
|
-
return {
|
|
2538
|
-
format,
|
|
2539
|
-
proof,
|
|
2540
|
-
// Ignored because v11 does not have the context value, but it is required in v12
|
|
2541
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2542
|
-
// @ts-ignore
|
|
2543
|
-
credential_definition: {
|
|
2544
|
-
types,
|
|
2545
|
-
...opts.context && {
|
|
2546
|
-
"@context": opts.context
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
};
|
|
2550
|
-
} else if (format === "vc+sd-jwt") {
|
|
2551
|
-
if (types.length > 1) {
|
|
2552
|
-
throw Error(`Only a single credential type is supported for ${format}`);
|
|
2553
|
-
}
|
|
2554
|
-
return {
|
|
2555
|
-
format,
|
|
2556
|
-
proof,
|
|
2557
|
-
vct: types[0]
|
|
2558
|
-
};
|
|
2559
|
-
} else if (format === "mso_mdoc") {
|
|
2560
|
-
if (types.length > 1) {
|
|
2561
|
-
throw Error(`Only a single credential type is supported for ${format}`);
|
|
2562
|
-
}
|
|
2563
|
-
return {
|
|
2564
|
-
format,
|
|
2565
|
-
proof,
|
|
2566
|
-
doctype: types[0]
|
|
2567
|
-
};
|
|
2568
|
-
}
|
|
2569
|
-
throw new Error(`Unsupported format: ${format}`);
|
|
2570
|
-
}
|
|
2571
|
-
version() {
|
|
2572
|
-
return this.credentialRequestOpts?.version ?? OpenId4VCIVersion10.VER_1_0_11;
|
|
2573
|
-
}
|
|
2574
|
-
isV11OrHigher() {
|
|
2575
|
-
return this.version() >= OpenId4VCIVersion10.VER_1_0_11;
|
|
2576
1697
|
}
|
|
2577
1698
|
};
|
|
2578
1699
|
|
|
2579
1700
|
// lib/CredentialRequestClientBuilder.ts
|
|
2580
|
-
import {
|
|
1701
|
+
import { OpenId4VCIVersion as OpenId4VCIVersion7 } from "@sphereon/oid4vci-common";
|
|
2581
1702
|
|
|
2582
|
-
// lib/
|
|
2583
|
-
import { determineSpecVersionFromOffer as determineSpecVersionFromOffer3, getIssuerFromCredentialOfferPayload as
|
|
2584
|
-
var
|
|
1703
|
+
// lib/CredentialRequestClientBuilderV1_0_15.ts
|
|
1704
|
+
import { determineSpecVersionFromOffer as determineSpecVersionFromOffer3, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload4, OpenId4VCIVersion as OpenId4VCIVersion6 } from "@sphereon/oid4vci-common";
|
|
1705
|
+
var CredentialRequestClientBuilderV1_0_15 = class _CredentialRequestClientBuilderV1_0_15 {
|
|
2585
1706
|
static {
|
|
2586
|
-
__name(this, "
|
|
1707
|
+
__name(this, "CredentialRequestClientBuilderV1_0_15");
|
|
2587
1708
|
}
|
|
2588
1709
|
credentialEndpoint;
|
|
2589
1710
|
deferredCredentialEndpoint;
|
|
1711
|
+
nonceEndpoint;
|
|
2590
1712
|
deferredCredentialAwait = false;
|
|
2591
1713
|
deferredCredentialIntervalInMS = 5e3;
|
|
1714
|
+
credentialIdentifier;
|
|
1715
|
+
credentialConfigurationId;
|
|
2592
1716
|
credentialTypes = [];
|
|
2593
|
-
format;
|
|
2594
1717
|
token;
|
|
2595
1718
|
version;
|
|
2596
1719
|
subjectIssuance;
|
|
2597
1720
|
issuerState;
|
|
2598
|
-
|
|
1721
|
+
// Note: format removed from v15 - credential requests no longer include format parameter
|
|
1722
|
+
static fromCredentialIssuer({ credentialIssuer, metadata, version, credentialIdentifier, credentialConfigurationId, credentialTypes }) {
|
|
2599
1723
|
const issuer = credentialIssuer;
|
|
2600
|
-
const builder = new
|
|
2601
|
-
builder.withVersion(version ??
|
|
1724
|
+
const builder = new _CredentialRequestClientBuilderV1_0_15();
|
|
1725
|
+
builder.withVersion(version ?? OpenId4VCIVersion6.VER_1_0_15);
|
|
2602
1726
|
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith("/") ? `${issuer}credential` : `${issuer}/credential`));
|
|
2603
1727
|
if (metadata?.deferred_credential_endpoint) {
|
|
2604
1728
|
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
2605
1729
|
}
|
|
2606
|
-
|
|
1730
|
+
if (metadata?.credentialIssuerMetadata?.nonce_endpoint) {
|
|
1731
|
+
builder.withNonceEndpoint(metadata.credentialIssuerMetadata?.nonce_endpoint);
|
|
1732
|
+
}
|
|
1733
|
+
if (credentialIdentifier) {
|
|
1734
|
+
builder.withCredentialIdentifier(credentialIdentifier);
|
|
1735
|
+
}
|
|
1736
|
+
if (credentialConfigurationId) {
|
|
1737
|
+
builder.withCredentialConfigurationId(credentialConfigurationId);
|
|
1738
|
+
}
|
|
1739
|
+
if (credentialTypes) {
|
|
1740
|
+
builder.withCredentialType(credentialTypes);
|
|
1741
|
+
}
|
|
2607
1742
|
return builder;
|
|
2608
1743
|
}
|
|
2609
1744
|
static async fromURI({ uri, metadata }) {
|
|
2610
|
-
const offer = await
|
|
2611
|
-
return
|
|
1745
|
+
const offer = await CredentialOfferClient.fromURI(uri);
|
|
1746
|
+
return _CredentialRequestClientBuilderV1_0_15.fromCredentialOfferRequest({
|
|
2612
1747
|
request: offer,
|
|
2613
1748
|
...offer,
|
|
2614
1749
|
metadata,
|
|
@@ -2618,154 +1753,35 @@ var CredentialRequestClientBuilderV1_0_11 = class _CredentialRequestClientBuilde
|
|
|
2618
1753
|
static fromCredentialOfferRequest(opts) {
|
|
2619
1754
|
const { request, metadata } = opts;
|
|
2620
1755
|
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer3(request.original_credential_offer);
|
|
2621
|
-
|
|
2622
|
-
|
|
1756
|
+
if (version < OpenId4VCIVersion6.VER_1_0_15) {
|
|
1757
|
+
throw new Error("Versions below v1.0.15 (draft 15) are not supported.");
|
|
1758
|
+
}
|
|
1759
|
+
const builder = new _CredentialRequestClientBuilderV1_0_15();
|
|
1760
|
+
const issuer = getIssuerFromCredentialOfferPayload4(request.credential_offer) ?? (metadata ? metadata.issuer : void 0);
|
|
1761
|
+
if (!issuer && !metadata?.credential_endpoint) {
|
|
1762
|
+
throw Error(`Issuer could not be determined`);
|
|
1763
|
+
}
|
|
2623
1764
|
builder.withVersion(version);
|
|
2624
1765
|
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith("/") ? `${issuer}credential` : `${issuer}/credential`));
|
|
2625
1766
|
if (metadata?.deferred_credential_endpoint) {
|
|
2626
1767
|
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
2627
1768
|
}
|
|
2628
|
-
if (
|
|
2629
|
-
builder.
|
|
2630
|
-
}
|
|
2631
|
-
|
|
1769
|
+
if (metadata?.credentialIssuerMetadata?.nonce_endpoint) {
|
|
1770
|
+
builder.withNonceEndpoint(metadata.credentialIssuerMetadata.nonce_endpoint);
|
|
1771
|
+
}
|
|
1772
|
+
const ids = request.credential_offer.credential_configuration_ids;
|
|
1773
|
+
if (ids.length && ids.length === 1) {
|
|
1774
|
+
builder.withCredentialConfigurationId(ids[0]);
|
|
2632
1775
|
}
|
|
2633
1776
|
return builder;
|
|
2634
1777
|
}
|
|
2635
1778
|
static fromCredentialOffer({ credentialOffer, metadata }) {
|
|
2636
|
-
|
|
1779
|
+
const builder = _CredentialRequestClientBuilderV1_0_15.fromCredentialOfferRequest({
|
|
2637
1780
|
request: credentialOffer,
|
|
2638
1781
|
metadata,
|
|
2639
1782
|
version: credentialOffer.version
|
|
2640
1783
|
});
|
|
2641
|
-
|
|
2642
|
-
withIssuerState(issuerState) {
|
|
2643
|
-
this.issuerState = issuerState;
|
|
2644
|
-
return this;
|
|
2645
|
-
}
|
|
2646
|
-
withCredentialEndpointFromMetadata(metadata) {
|
|
2647
|
-
this.credentialEndpoint = metadata.credential_endpoint;
|
|
2648
|
-
return this;
|
|
2649
|
-
}
|
|
2650
|
-
withCredentialEndpoint(credentialEndpoint) {
|
|
2651
|
-
this.credentialEndpoint = credentialEndpoint;
|
|
2652
|
-
return this;
|
|
2653
|
-
}
|
|
2654
|
-
withDeferredCredentialEndpointFromMetadata(metadata) {
|
|
2655
|
-
this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
|
|
2656
|
-
return this;
|
|
2657
|
-
}
|
|
2658
|
-
withDeferredCredentialEndpoint(deferredCredentialEndpoint) {
|
|
2659
|
-
this.deferredCredentialEndpoint = deferredCredentialEndpoint;
|
|
2660
|
-
return this;
|
|
2661
|
-
}
|
|
2662
|
-
withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS) {
|
|
2663
|
-
this.deferredCredentialAwait = deferredCredentialAwait;
|
|
2664
|
-
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5e3;
|
|
2665
|
-
return this;
|
|
2666
|
-
}
|
|
2667
|
-
withCredentialType(credentialTypes) {
|
|
2668
|
-
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [
|
|
2669
|
-
credentialTypes
|
|
2670
|
-
];
|
|
2671
|
-
return this;
|
|
2672
|
-
}
|
|
2673
|
-
withFormat(format) {
|
|
2674
|
-
this.format = format;
|
|
2675
|
-
return this;
|
|
2676
|
-
}
|
|
2677
|
-
withSubjectIssuance(subjectIssuance) {
|
|
2678
|
-
this.subjectIssuance = subjectIssuance;
|
|
2679
|
-
return this;
|
|
2680
|
-
}
|
|
2681
|
-
withToken(accessToken) {
|
|
2682
|
-
this.token = accessToken;
|
|
2683
|
-
return this;
|
|
2684
|
-
}
|
|
2685
|
-
withTokenFromResponse(response) {
|
|
2686
|
-
this.token = response.access_token;
|
|
2687
|
-
return this;
|
|
2688
|
-
}
|
|
2689
|
-
withVersion(version) {
|
|
2690
|
-
this.version = version;
|
|
2691
|
-
return this;
|
|
2692
|
-
}
|
|
2693
|
-
build() {
|
|
2694
|
-
if (!this.version) {
|
|
2695
|
-
this.withVersion(OpenId4VCIVersion11.VER_1_0_11);
|
|
2696
|
-
}
|
|
2697
|
-
return new CredentialRequestClientV1_0_11(this);
|
|
2698
|
-
}
|
|
2699
|
-
};
|
|
2700
|
-
|
|
2701
|
-
// lib/CredentialRequestClientBuilderV1_0_13.ts
|
|
2702
|
-
import { determineSpecVersionFromOffer as determineSpecVersionFromOffer4, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload7, OpenId4VCIVersion as OpenId4VCIVersion12 } from "@sphereon/oid4vci-common";
|
|
2703
|
-
var CredentialRequestClientBuilderV1_0_13 = class _CredentialRequestClientBuilderV1_0_13 {
|
|
2704
|
-
static {
|
|
2705
|
-
__name(this, "CredentialRequestClientBuilderV1_0_13");
|
|
2706
|
-
}
|
|
2707
|
-
credentialEndpoint;
|
|
2708
|
-
deferredCredentialEndpoint;
|
|
2709
|
-
deferredCredentialAwait = false;
|
|
2710
|
-
deferredCredentialIntervalInMS = 5e3;
|
|
2711
|
-
credentialIdentifier;
|
|
2712
|
-
credentialTypes = [];
|
|
2713
|
-
format;
|
|
2714
|
-
token;
|
|
2715
|
-
version;
|
|
2716
|
-
subjectIssuance;
|
|
2717
|
-
issuerState;
|
|
2718
|
-
static fromCredentialIssuer({ credentialIssuer, metadata, version, credentialIdentifier, credentialTypes }) {
|
|
2719
|
-
const issuer = credentialIssuer;
|
|
2720
|
-
const builder = new _CredentialRequestClientBuilderV1_0_13();
|
|
2721
|
-
builder.withVersion(version ?? OpenId4VCIVersion12.VER_1_0_13);
|
|
2722
|
-
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith("/") ? `${issuer}credential` : `${issuer}/credential`));
|
|
2723
|
-
if (metadata?.deferred_credential_endpoint) {
|
|
2724
|
-
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
2725
|
-
}
|
|
2726
|
-
if (credentialIdentifier) {
|
|
2727
|
-
builder.withCredentialIdentifier(credentialIdentifier);
|
|
2728
|
-
}
|
|
2729
|
-
if (credentialTypes) {
|
|
2730
|
-
builder.withCredentialType(credentialTypes);
|
|
2731
|
-
}
|
|
2732
|
-
return builder;
|
|
2733
|
-
}
|
|
2734
|
-
static async fromURI({ uri, metadata }) {
|
|
2735
|
-
const offer = await CredentialOfferClient.fromURI(uri);
|
|
2736
|
-
return _CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
|
|
2737
|
-
request: offer,
|
|
2738
|
-
...offer,
|
|
2739
|
-
metadata,
|
|
2740
|
-
version: offer.version
|
|
2741
|
-
});
|
|
2742
|
-
}
|
|
2743
|
-
static fromCredentialOfferRequest(opts) {
|
|
2744
|
-
const { request, metadata } = opts;
|
|
2745
|
-
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer4(request.original_credential_offer);
|
|
2746
|
-
if (version < OpenId4VCIVersion12.VER_1_0_13) {
|
|
2747
|
-
throw new Error("Versions below v1.0.13 (draft 13) are not supported.");
|
|
2748
|
-
}
|
|
2749
|
-
const builder = new _CredentialRequestClientBuilderV1_0_13();
|
|
2750
|
-
const issuer = getIssuerFromCredentialOfferPayload7(request.credential_offer) ?? metadata?.issuer;
|
|
2751
|
-
builder.withVersion(version);
|
|
2752
|
-
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith("/") ? `${issuer}credential` : `${issuer}/credential`));
|
|
2753
|
-
if (metadata?.deferred_credential_endpoint) {
|
|
2754
|
-
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
2755
|
-
}
|
|
2756
|
-
const ids = request.credential_offer.credential_configuration_ids;
|
|
2757
|
-
if (ids.length && ids.length === 1) {
|
|
2758
|
-
builder.withCredentialIdentifier(ids[0]);
|
|
2759
|
-
}
|
|
2760
|
-
return builder;
|
|
2761
|
-
}
|
|
2762
|
-
static fromCredentialOffer({ credentialOffer, metadata }) {
|
|
2763
|
-
const builder = _CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
|
|
2764
|
-
request: credentialOffer,
|
|
2765
|
-
metadata,
|
|
2766
|
-
version: credentialOffer.version
|
|
2767
|
-
});
|
|
2768
|
-
return builder;
|
|
1784
|
+
return builder;
|
|
2769
1785
|
}
|
|
2770
1786
|
withCredentialEndpointFromMetadata(metadata) {
|
|
2771
1787
|
this.credentialEndpoint = metadata.credential_endpoint;
|
|
@@ -2787,25 +1803,38 @@ var CredentialRequestClientBuilderV1_0_13 = class _CredentialRequestClientBuilde
|
|
|
2787
1803
|
this.deferredCredentialEndpoint = deferredCredentialEndpoint;
|
|
2788
1804
|
return this;
|
|
2789
1805
|
}
|
|
1806
|
+
// New in v15: Support for nonce endpoint
|
|
1807
|
+
withNonceEndpointFromMetadata(metadata) {
|
|
1808
|
+
this.nonceEndpoint = metadata.nonce_endpoint;
|
|
1809
|
+
return this;
|
|
1810
|
+
}
|
|
1811
|
+
withNonceEndpoint(nonceEndpoint) {
|
|
1812
|
+
this.nonceEndpoint = nonceEndpoint;
|
|
1813
|
+
return this;
|
|
1814
|
+
}
|
|
2790
1815
|
withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS) {
|
|
2791
1816
|
this.deferredCredentialAwait = deferredCredentialAwait;
|
|
2792
1817
|
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5e3;
|
|
2793
1818
|
return this;
|
|
2794
1819
|
}
|
|
1820
|
+
// New in v15: Support for credential_identifier (used when authorization_details with credential_identifiers was used)
|
|
2795
1821
|
withCredentialIdentifier(credentialIdentifier) {
|
|
2796
1822
|
this.credentialIdentifier = credentialIdentifier;
|
|
2797
1823
|
return this;
|
|
2798
1824
|
}
|
|
1825
|
+
// New in v15: Support for credential_configuration_id (used when scope was used and no credential_identifiers returned)
|
|
1826
|
+
withCredentialConfigurationId(credentialConfigurationId) {
|
|
1827
|
+
this.credentialConfigurationId = credentialConfigurationId;
|
|
1828
|
+
return this;
|
|
1829
|
+
}
|
|
1830
|
+
// Legacy support for credential types (may be used internally to map to configuration IDs)
|
|
2799
1831
|
withCredentialType(credentialTypes) {
|
|
2800
1832
|
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [
|
|
2801
1833
|
credentialTypes
|
|
2802
1834
|
];
|
|
2803
1835
|
return this;
|
|
2804
1836
|
}
|
|
2805
|
-
withFormat(
|
|
2806
|
-
this.format = format;
|
|
2807
|
-
return this;
|
|
2808
|
-
}
|
|
1837
|
+
// Note: withFormat() method removed in v15 - format is no longer part of credential requests
|
|
2809
1838
|
withSubjectIssuance(subjectIssuance) {
|
|
2810
1839
|
this.subjectIssuance = subjectIssuance;
|
|
2811
1840
|
return this;
|
|
@@ -2824,723 +1853,158 @@ var CredentialRequestClientBuilderV1_0_13 = class _CredentialRequestClientBuilde
|
|
|
2824
1853
|
}
|
|
2825
1854
|
build() {
|
|
2826
1855
|
if (!this.version) {
|
|
2827
|
-
this.withVersion(
|
|
1856
|
+
this.withVersion(OpenId4VCIVersion6.VER_1_0_15);
|
|
2828
1857
|
}
|
|
2829
1858
|
return new CredentialRequestClient(this);
|
|
2830
1859
|
}
|
|
2831
1860
|
};
|
|
2832
1861
|
|
|
2833
1862
|
// lib/CredentialRequestClientBuilder.ts
|
|
2834
|
-
function
|
|
1863
|
+
function isV1_0_15(builder) {
|
|
2835
1864
|
return builder.withCredentialIdentifier !== void 0;
|
|
2836
1865
|
}
|
|
2837
|
-
__name(
|
|
1866
|
+
__name(isV1_0_15, "isV1_0_15");
|
|
2838
1867
|
var CredentialRequestClientBuilder = class _CredentialRequestClientBuilder {
|
|
2839
1868
|
static {
|
|
2840
1869
|
__name(this, "CredentialRequestClientBuilder");
|
|
2841
1870
|
}
|
|
2842
1871
|
_builder;
|
|
2843
|
-
constructor(builder) {
|
|
2844
|
-
this._builder = builder;
|
|
2845
|
-
}
|
|
2846
|
-
static fromCredentialIssuer({ credentialIssuer, metadata, version, credentialIdentifier, credentialTypes }) {
|
|
2847
|
-
const specVersion = version ?? OpenId4VCIVersion13.VER_1_0_13;
|
|
2848
|
-
let builder;
|
|
2849
|
-
if (specVersion >= OpenId4VCIVersion13.VER_1_0_13) {
|
|
2850
|
-
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
|
|
2851
|
-
credentialIssuer,
|
|
2852
|
-
metadata,
|
|
2853
|
-
version,
|
|
2854
|
-
credentialIdentifier,
|
|
2855
|
-
credentialTypes
|
|
2856
|
-
});
|
|
2857
|
-
} else {
|
|
2858
|
-
if (!credentialTypes || credentialTypes.length === 0) {
|
|
2859
|
-
throw new Error("CredentialTypes must be provided for v1_0_11");
|
|
2860
|
-
}
|
|
2861
|
-
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialIssuer({
|
|
2862
|
-
credentialIssuer,
|
|
2863
|
-
metadata,
|
|
2864
|
-
version,
|
|
2865
|
-
credentialTypes
|
|
2866
|
-
});
|
|
2867
|
-
}
|
|
2868
|
-
return new _CredentialRequestClientBuilder(builder);
|
|
2869
|
-
}
|
|
2870
|
-
static async fromURI({ uri, metadata }) {
|
|
2871
|
-
const offer = await CredentialOfferClient.fromURI(uri);
|
|
2872
|
-
return _CredentialRequestClientBuilder.fromCredentialOfferRequest({
|
|
2873
|
-
request: offer,
|
|
2874
|
-
...offer,
|
|
2875
|
-
metadata,
|
|
2876
|
-
version: offer.version
|
|
2877
|
-
});
|
|
2878
|
-
}
|
|
2879
|
-
static fromCredentialOfferRequest(opts) {
|
|
2880
|
-
const { request } = opts;
|
|
2881
|
-
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer5(request.original_credential_offer);
|
|
2882
|
-
let builder;
|
|
2883
|
-
if (version < OpenId4VCIVersion13.VER_1_0_13) {
|
|
2884
|
-
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest(opts);
|
|
2885
|
-
} else {
|
|
2886
|
-
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest(opts);
|
|
2887
|
-
}
|
|
2888
|
-
return new _CredentialRequestClientBuilder(builder);
|
|
2889
|
-
}
|
|
2890
|
-
static fromCredentialOffer({ credentialOffer, metadata }) {
|
|
2891
|
-
const version = determineSpecVersionFromOffer5(credentialOffer.credential_offer);
|
|
2892
|
-
let builder;
|
|
2893
|
-
if (version < OpenId4VCIVersion13.VER_1_0_13) {
|
|
2894
|
-
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
|
|
2895
|
-
credentialOffer,
|
|
2896
|
-
metadata
|
|
2897
|
-
});
|
|
2898
|
-
} else {
|
|
2899
|
-
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
|
|
2900
|
-
credentialOffer,
|
|
2901
|
-
metadata
|
|
2902
|
-
});
|
|
2903
|
-
}
|
|
2904
|
-
return new _CredentialRequestClientBuilder(builder);
|
|
2905
|
-
}
|
|
2906
|
-
getVersion() {
|
|
2907
|
-
return this._builder.version;
|
|
2908
|
-
}
|
|
2909
|
-
withCredentialEndpointFromMetadata(metadata) {
|
|
2910
|
-
if (isV1_0_13(this._builder)) {
|
|
2911
|
-
this._builder.withCredentialEndpointFromMetadata(metadata);
|
|
2912
|
-
} else {
|
|
2913
|
-
this._builder.withCredentialEndpointFromMetadata(metadata);
|
|
2914
|
-
}
|
|
2915
|
-
return this;
|
|
2916
|
-
}
|
|
2917
|
-
withCredentialEndpoint(credentialEndpoint) {
|
|
2918
|
-
this._builder.withCredentialEndpoint(credentialEndpoint);
|
|
2919
|
-
return this;
|
|
2920
|
-
}
|
|
2921
|
-
withDeferredCredentialEndpointFromMetadata(metadata) {
|
|
2922
|
-
if (isV1_0_13(this._builder)) {
|
|
2923
|
-
this._builder.withDeferredCredentialEndpointFromMetadata(metadata);
|
|
2924
|
-
} else {
|
|
2925
|
-
this._builder.withDeferredCredentialEndpointFromMetadata(metadata);
|
|
2926
|
-
}
|
|
2927
|
-
return this;
|
|
2928
|
-
}
|
|
2929
|
-
withDeferredCredentialEndpoint(deferredCredentialEndpoint) {
|
|
2930
|
-
this._builder.withDeferredCredentialEndpoint(deferredCredentialEndpoint);
|
|
2931
|
-
return this;
|
|
2932
|
-
}
|
|
2933
|
-
withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS) {
|
|
2934
|
-
this._builder.withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS);
|
|
2935
|
-
return this;
|
|
2936
|
-
}
|
|
2937
|
-
withCredentialIdentifier(credentialIdentifier) {
|
|
2938
|
-
if (this._builder.version === void 0 || this._builder.version < OpenId4VCIVersion13.VER_1_0_13) {
|
|
2939
|
-
throw new Error("Version of spec should be equal or higher than v1_0_13");
|
|
2940
|
-
}
|
|
2941
|
-
;
|
|
2942
|
-
this._builder.withCredentialIdentifier(credentialIdentifier);
|
|
2943
|
-
return this;
|
|
2944
|
-
}
|
|
2945
|
-
withIssuerState(issuerState) {
|
|
2946
|
-
this._builder.withIssuerState(issuerState);
|
|
2947
|
-
return this;
|
|
2948
|
-
}
|
|
2949
|
-
withCredentialType(credentialTypes) {
|
|
2950
|
-
this._builder.withCredentialType(credentialTypes);
|
|
2951
|
-
return this;
|
|
2952
|
-
}
|
|
2953
|
-
withFormat(format) {
|
|
2954
|
-
this._builder.withFormat(format);
|
|
2955
|
-
return this;
|
|
2956
|
-
}
|
|
2957
|
-
withSubjectIssuance(subjectIssuance) {
|
|
2958
|
-
this._builder.withSubjectIssuance(subjectIssuance);
|
|
2959
|
-
return this;
|
|
2960
|
-
}
|
|
2961
|
-
withToken(accessToken) {
|
|
2962
|
-
this._builder.withToken(accessToken);
|
|
2963
|
-
return this;
|
|
2964
|
-
}
|
|
2965
|
-
withTokenFromResponse(response) {
|
|
2966
|
-
this._builder.withTokenFromResponse(response);
|
|
2967
|
-
return this;
|
|
2968
|
-
}
|
|
2969
|
-
withVersion(version) {
|
|
2970
|
-
this._builder.withVersion(version);
|
|
2971
|
-
return this;
|
|
2972
|
-
}
|
|
2973
|
-
build() {
|
|
2974
|
-
return this._builder.build();
|
|
2975
|
-
}
|
|
2976
|
-
};
|
|
2977
|
-
|
|
2978
|
-
// lib/OpenID4VCIClient.ts
|
|
2979
|
-
import { AuthzFlowType as AuthzFlowType3, CodeChallengeMethod as CodeChallengeMethod4, DefaultURISchemes, determineVersionsFromIssuerMetadata, getClientIdFromCredentialOfferPayload as getClientIdFromCredentialOfferPayload3, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload8, getSupportedCredentials, getTypesFromCredentialSupported, getTypesFromObject, KID_JWK_X5C_ERROR, OpenId4VCIVersion as OpenId4VCIVersion14, toAuthorizationResponsePayload } from "@sphereon/oid4vci-common";
|
|
2980
|
-
import { Loggers as Loggers12 } from "@sphereon/ssi-types";
|
|
2981
|
-
var logger12 = Loggers12.DEFAULT.get("sphereon:oid4vci");
|
|
2982
|
-
var OpenID4VCIClient = class _OpenID4VCIClient {
|
|
2983
|
-
static {
|
|
2984
|
-
__name(this, "OpenID4VCIClient");
|
|
2985
|
-
}
|
|
2986
|
-
_state;
|
|
2987
|
-
constructor({ credentialOffer, clientId, kid, alg, credentialIssuer, pkce, authorizationRequest, accessToken, jwk, endpointMetadata, accessTokenResponse, authorizationRequestOpts, authorizationCodeResponse, authorizationURL }) {
|
|
2988
|
-
const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload8(credentialOffer.credential_offer) : void 0);
|
|
2989
|
-
if (!issuer) {
|
|
2990
|
-
throw Error("No credential issuer supplied or deduced from offer");
|
|
2991
|
-
}
|
|
2992
|
-
this._state = {
|
|
2993
|
-
credentialOffer,
|
|
2994
|
-
credentialIssuer: issuer,
|
|
2995
|
-
kid,
|
|
2996
|
-
alg,
|
|
2997
|
-
// TODO: We need to refactor this and always explicitly call createAuthorizationRequestUrl, so we can have a credential selection first and use the kid as a default for the client id
|
|
2998
|
-
clientId: clientId ?? (credentialOffer && getClientIdFromCredentialOfferPayload3(credentialOffer.credential_offer)) ?? kid?.split("#")[0],
|
|
2999
|
-
pkce: {
|
|
3000
|
-
disabled: false,
|
|
3001
|
-
codeChallengeMethod: CodeChallengeMethod4.S256,
|
|
3002
|
-
...pkce
|
|
3003
|
-
},
|
|
3004
|
-
authorizationRequestOpts,
|
|
3005
|
-
authorizationCodeResponse,
|
|
3006
|
-
accessToken,
|
|
3007
|
-
jwk,
|
|
3008
|
-
endpointMetadata: endpointMetadata?.credentialIssuerMetadata?.authorization_server ? endpointMetadata : endpointMetadata,
|
|
3009
|
-
accessTokenResponse,
|
|
3010
|
-
authorizationURL
|
|
3011
|
-
};
|
|
3012
|
-
if (!this._state.authorizationRequestOpts) {
|
|
3013
|
-
this._state.authorizationRequestOpts = this.syncAuthorizationRequestOpts(authorizationRequest);
|
|
3014
|
-
}
|
|
3015
|
-
logger12.debug(`Authorization req options: ${JSON.stringify(this._state.authorizationRequestOpts, null, 2)}`);
|
|
3016
|
-
}
|
|
3017
|
-
static async fromCredentialIssuer({ kid, alg, retrieveServerMetadata, clientId, credentialIssuer, pkce, authorizationRequest, createAuthorizationRequestURL, endpointMetadata }) {
|
|
3018
|
-
const client = new _OpenID4VCIClient({
|
|
3019
|
-
kid,
|
|
3020
|
-
alg,
|
|
3021
|
-
clientId: clientId ?? authorizationRequest?.clientId,
|
|
3022
|
-
credentialIssuer,
|
|
3023
|
-
pkce,
|
|
3024
|
-
authorizationRequest,
|
|
3025
|
-
endpointMetadata
|
|
3026
|
-
});
|
|
3027
|
-
if (retrieveServerMetadata === void 0 || retrieveServerMetadata) {
|
|
3028
|
-
await client.retrieveServerMetadata();
|
|
3029
|
-
}
|
|
3030
|
-
if (createAuthorizationRequestURL === void 0 || createAuthorizationRequestURL) {
|
|
3031
|
-
await client.createAuthorizationRequestUrl({
|
|
3032
|
-
authorizationRequest,
|
|
3033
|
-
pkce
|
|
3034
|
-
});
|
|
3035
|
-
}
|
|
3036
|
-
return client;
|
|
3037
|
-
}
|
|
3038
|
-
static async fromState({ state }) {
|
|
3039
|
-
const clientState = typeof state === "string" ? JSON.parse(state) : state;
|
|
3040
|
-
return new _OpenID4VCIClient(clientState);
|
|
3041
|
-
}
|
|
3042
|
-
static async fromURI({ uri, kid, alg, retrieveServerMetadata, clientId, pkce, createAuthorizationRequestURL, authorizationRequest, resolveOfferUri, endpointMetadata }) {
|
|
3043
|
-
const credentialOfferClient = await CredentialOfferClient.fromURI(uri, {
|
|
3044
|
-
resolve: resolveOfferUri
|
|
3045
|
-
});
|
|
3046
|
-
const client = new _OpenID4VCIClient({
|
|
3047
|
-
credentialOffer: credentialOfferClient,
|
|
3048
|
-
kid,
|
|
3049
|
-
alg,
|
|
3050
|
-
clientId: clientId ?? authorizationRequest?.clientId ?? credentialOfferClient.clientId,
|
|
3051
|
-
pkce,
|
|
3052
|
-
authorizationRequest,
|
|
3053
|
-
endpointMetadata
|
|
3054
|
-
});
|
|
3055
|
-
if (retrieveServerMetadata === void 0 || retrieveServerMetadata) {
|
|
3056
|
-
await client.retrieveServerMetadata();
|
|
3057
|
-
}
|
|
3058
|
-
if (credentialOfferClient.supportedFlows.includes(AuthzFlowType3.AUTHORIZATION_CODE_FLOW) && (createAuthorizationRequestURL === void 0 || createAuthorizationRequestURL)) {
|
|
3059
|
-
await client.createAuthorizationRequestUrl({
|
|
3060
|
-
authorizationRequest,
|
|
3061
|
-
pkce
|
|
3062
|
-
});
|
|
3063
|
-
logger12.debug(`Authorization Request URL: ${client._state.authorizationURL}`);
|
|
3064
|
-
}
|
|
3065
|
-
return client;
|
|
3066
|
-
}
|
|
3067
|
-
/**
|
|
3068
|
-
* Allows you to create an Authorization Request URL when using an Authorization Code flow. This URL needs to be accessed using the front channel (browser)
|
|
3069
|
-
*
|
|
3070
|
-
* The Identity provider would present a login screen typically; after you authenticated, it would redirect to the provided redirectUri; which can be same device or cross-device
|
|
3071
|
-
* @param opts
|
|
3072
|
-
*/
|
|
3073
|
-
async createAuthorizationRequestUrl(opts) {
|
|
3074
|
-
if (!this._state.authorizationURL) {
|
|
3075
|
-
this.calculatePKCEOpts(opts?.pkce);
|
|
3076
|
-
this._state.authorizationRequestOpts = this.syncAuthorizationRequestOpts(opts?.authorizationRequest);
|
|
3077
|
-
if (!this._state.authorizationRequestOpts) {
|
|
3078
|
-
throw Error(`No Authorization Request options present or provided in this call`);
|
|
3079
|
-
}
|
|
3080
|
-
if (this._state.endpointMetadata?.credentialIssuerMetadata && "authorization_endpoint" in this._state.endpointMetadata.credentialIssuerMetadata) {
|
|
3081
|
-
this._state.endpointMetadata.authorization_endpoint = this._state.endpointMetadata.credentialIssuerMetadata.authorization_endpoint;
|
|
3082
|
-
}
|
|
3083
|
-
if (this.version() <= OpenId4VCIVersion14.VER_1_0_11) {
|
|
3084
|
-
this._state.authorizationURL = await createAuthorizationRequestUrlV1_0_11({
|
|
3085
|
-
pkce: this._state.pkce,
|
|
3086
|
-
endpointMetadata: this.endpointMetadata,
|
|
3087
|
-
authorizationRequest: this._state.authorizationRequestOpts,
|
|
3088
|
-
credentialOffer: this.credentialOffer,
|
|
3089
|
-
credentialsSupported: Object.values(this.getCredentialsSupported(true))
|
|
3090
|
-
});
|
|
3091
|
-
} else {
|
|
3092
|
-
this._state.authorizationURL = await createAuthorizationRequestUrl({
|
|
3093
|
-
pkce: this._state.pkce,
|
|
3094
|
-
endpointMetadata: this.endpointMetadata,
|
|
3095
|
-
authorizationRequest: this._state.authorizationRequestOpts,
|
|
3096
|
-
credentialOffer: this.credentialOffer,
|
|
3097
|
-
credentialConfigurationSupported: this.getCredentialsSupported(false)
|
|
3098
|
-
});
|
|
3099
|
-
}
|
|
3100
|
-
}
|
|
3101
|
-
return this._state.authorizationURL;
|
|
3102
|
-
}
|
|
3103
|
-
async retrieveServerMetadata() {
|
|
3104
|
-
this.assertIssuerData();
|
|
3105
|
-
if (!this._state.endpointMetadata) {
|
|
3106
|
-
if (this.credentialOffer) {
|
|
3107
|
-
this._state.endpointMetadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(this.credentialOffer);
|
|
3108
|
-
} else if (this._state.credentialIssuer) {
|
|
3109
|
-
this._state.endpointMetadata = await MetadataClient.retrieveAllMetadata(this._state.credentialIssuer);
|
|
3110
|
-
} else {
|
|
3111
|
-
throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`);
|
|
3112
|
-
}
|
|
3113
|
-
}
|
|
3114
|
-
return this.endpointMetadata;
|
|
3115
|
-
}
|
|
3116
|
-
calculatePKCEOpts(pkce) {
|
|
3117
|
-
this._state.pkce = generateMissingPKCEOpts({
|
|
3118
|
-
...this._state.pkce,
|
|
3119
|
-
...pkce
|
|
3120
|
-
});
|
|
3121
|
-
}
|
|
3122
|
-
async acquireAuthorizationChallengeCode(opts) {
|
|
3123
|
-
const response = await acquireAuthorizationChallengeAuthCode({
|
|
3124
|
-
metadata: this.endpointMetadata,
|
|
3125
|
-
credentialIssuer: this.getIssuer(),
|
|
3126
|
-
clientId: this._state.clientId ?? this._state.authorizationRequestOpts?.clientId,
|
|
3127
|
-
...opts
|
|
3128
|
-
});
|
|
3129
|
-
if (response.errorBody) {
|
|
3130
|
-
logger12.debug(`Authorization code error:\r
|
|
3131
|
-
${JSON.stringify(response.errorBody)}`);
|
|
3132
|
-
const error = response.errorBody;
|
|
3133
|
-
return Promise.reject(error);
|
|
3134
|
-
} else if (!response.successBody) {
|
|
3135
|
-
logger12.debug(`Authorization code error. No success body`);
|
|
3136
|
-
return Promise.reject(Error(`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`));
|
|
3137
|
-
}
|
|
3138
|
-
return {
|
|
3139
|
-
...response.successBody
|
|
3140
|
-
};
|
|
3141
|
-
}
|
|
3142
|
-
async acquireAccessToken(opts) {
|
|
3143
|
-
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
|
|
3144
|
-
let { redirectUri } = opts ?? {};
|
|
3145
|
-
const code = this.getAuthorizationCode(opts?.authorizationResponse, opts?.code);
|
|
3146
|
-
if (opts?.codeVerifier) {
|
|
3147
|
-
this._state.pkce.codeVerifier = opts.codeVerifier;
|
|
3148
|
-
}
|
|
3149
|
-
this.assertIssuerData();
|
|
3150
|
-
const asOpts = {
|
|
3151
|
-
...opts?.asOpts
|
|
3152
|
-
};
|
|
3153
|
-
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
3154
|
-
const clientAssertionType = asOpts.clientOpts?.clientAssertionType ?? (kid && clientId && typeof asOpts.clientOpts?.signCallbacks?.signCallback === "function" ? "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" : void 0);
|
|
3155
|
-
if (this.isEBSI() || clientId && kid) {
|
|
3156
|
-
if (!clientId) {
|
|
3157
|
-
throw Error(`Client id expected for EBSI`);
|
|
3158
|
-
}
|
|
3159
|
-
asOpts.clientOpts = {
|
|
3160
|
-
...asOpts.clientOpts,
|
|
3161
|
-
clientId,
|
|
3162
|
-
...kid && {
|
|
3163
|
-
kid
|
|
3164
|
-
},
|
|
3165
|
-
...clientAssertionType && {
|
|
3166
|
-
clientAssertionType
|
|
3167
|
-
},
|
|
3168
|
-
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks
|
|
3169
|
-
};
|
|
3170
|
-
}
|
|
3171
|
-
if (clientId) {
|
|
3172
|
-
this._state.clientId = clientId;
|
|
3173
|
-
if (!asOpts.clientOpts) {
|
|
3174
|
-
asOpts.clientOpts = {
|
|
3175
|
-
clientId
|
|
3176
|
-
};
|
|
3177
|
-
}
|
|
3178
|
-
asOpts.clientOpts.clientId = clientId;
|
|
3179
|
-
}
|
|
3180
|
-
if (!this._state.accessTokenResponse) {
|
|
3181
|
-
const accessTokenClient = this.version() <= OpenId4VCIVersion14.VER_1_0_12 ? new AccessTokenClientV1_0_11() : new AccessTokenClient();
|
|
3182
|
-
if (redirectUri && redirectUri !== this._state.authorizationRequestOpts?.redirectUri) {
|
|
3183
|
-
console.log(`Redirect URI mismatch between access-token (${redirectUri}) and authorization request (${this._state.authorizationRequestOpts?.redirectUri}). According to the specification that is not allowed.`);
|
|
3184
|
-
}
|
|
3185
|
-
if (this._state.authorizationRequestOpts?.redirectUri && !redirectUri) {
|
|
3186
|
-
redirectUri = this._state.authorizationRequestOpts.redirectUri;
|
|
3187
|
-
}
|
|
3188
|
-
const response = await accessTokenClient.acquireAccessToken({
|
|
3189
|
-
credentialOffer: this.credentialOffer,
|
|
3190
|
-
metadata: this.endpointMetadata,
|
|
3191
|
-
credentialIssuer: this.getIssuer(),
|
|
3192
|
-
pin,
|
|
3193
|
-
...!this._state.pkce.disabled && {
|
|
3194
|
-
codeVerifier: this._state.pkce.codeVerifier
|
|
3195
|
-
},
|
|
3196
|
-
code,
|
|
3197
|
-
redirectUri,
|
|
3198
|
-
asOpts,
|
|
3199
|
-
...opts?.createDPoPOpts && {
|
|
3200
|
-
createDPoPOpts: opts.createDPoPOpts
|
|
3201
|
-
},
|
|
3202
|
-
...opts?.additionalRequestParams && {
|
|
3203
|
-
additionalParams: opts.additionalRequestParams
|
|
3204
|
-
}
|
|
3205
|
-
});
|
|
3206
|
-
if (response.errorBody) {
|
|
3207
|
-
logger12.debug(`Access token error:\r
|
|
3208
|
-
${JSON.stringify(response.errorBody)}`);
|
|
3209
|
-
throw Error(`Retrieving an access token from ${this._state.endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed with status: ${response.origResponse.status}`);
|
|
3210
|
-
} else if (!response.successBody) {
|
|
3211
|
-
logger12.debug(`Access token error. No success body`);
|
|
3212
|
-
throw Error(`Retrieving an access token from ${this._state.endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`);
|
|
3213
|
-
}
|
|
3214
|
-
this._state.accessTokenResponse = response.successBody;
|
|
3215
|
-
this._state.dpopResponseParams = response.params;
|
|
3216
|
-
this._state.accessToken = response.successBody.access_token;
|
|
3217
|
-
}
|
|
3218
|
-
return {
|
|
3219
|
-
...this.accessTokenResponse,
|
|
3220
|
-
...this.dpopResponseParams && {
|
|
3221
|
-
params: this.dpopResponseParams
|
|
3222
|
-
}
|
|
3223
|
-
};
|
|
3224
|
-
}
|
|
3225
|
-
async acquireCredentials({ credentialTypes, context, proofCallbacks, format, kid, jwk, alg, jti, deferredCredentialAwait, deferredCredentialIntervalInMS, createDPoPOpts }) {
|
|
3226
|
-
if ([
|
|
3227
|
-
jwk,
|
|
3228
|
-
kid
|
|
3229
|
-
].filter((v) => v !== void 0).length > 1) {
|
|
3230
|
-
throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== void 0}, kid: ${kid !== void 0}`);
|
|
3231
|
-
}
|
|
3232
|
-
if (alg) this._state.alg = alg;
|
|
3233
|
-
if (jwk) this._state.jwk = jwk;
|
|
3234
|
-
if (kid) this._state.kid = kid;
|
|
3235
|
-
let requestBuilder;
|
|
3236
|
-
if (this.version() < OpenId4VCIVersion14.VER_1_0_13) {
|
|
3237
|
-
requestBuilder = this.credentialOffer ? CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
|
|
3238
|
-
credentialOffer: this.credentialOffer,
|
|
3239
|
-
metadata: this.endpointMetadata
|
|
3240
|
-
}) : CredentialRequestClientBuilderV1_0_11.fromCredentialIssuer({
|
|
3241
|
-
credentialIssuer: this.getIssuer(),
|
|
3242
|
-
credentialTypes,
|
|
3243
|
-
metadata: this.endpointMetadata,
|
|
3244
|
-
version: this.version()
|
|
3245
|
-
});
|
|
3246
|
-
} else {
|
|
3247
|
-
requestBuilder = this.credentialOffer ? CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
|
|
3248
|
-
credentialOffer: this.credentialOffer,
|
|
3249
|
-
metadata: this.endpointMetadata
|
|
3250
|
-
}) : CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
|
|
3251
|
-
credentialIssuer: this.getIssuer(),
|
|
3252
|
-
credentialTypes,
|
|
3253
|
-
metadata: this.endpointMetadata,
|
|
3254
|
-
version: this.version()
|
|
3255
|
-
});
|
|
3256
|
-
}
|
|
3257
|
-
const issuerState = this.issuerSupportedFlowTypes().includes(AuthzFlowType3.AUTHORIZATION_CODE_FLOW) && this._state.authorizationCodeResponse && !this.accessTokenResponse?.c_nonce && this._state.credentialOffer?.issuerState ? this._state.credentialOffer.issuerState : void 0;
|
|
3258
|
-
requestBuilder.withIssuerState(issuerState);
|
|
3259
|
-
requestBuilder.withTokenFromResponse(this.accessTokenResponse);
|
|
3260
|
-
requestBuilder.withDeferredCredentialAwait(deferredCredentialAwait ?? false, deferredCredentialIntervalInMS);
|
|
3261
|
-
let subjectIssuance;
|
|
3262
|
-
if (this.endpointMetadata?.credentialIssuerMetadata) {
|
|
3263
|
-
const metadata = this.endpointMetadata.credentialIssuerMetadata;
|
|
3264
|
-
const types = Array.isArray(credentialTypes) ? credentialTypes : [
|
|
3265
|
-
credentialTypes
|
|
3266
|
-
];
|
|
3267
|
-
if (metadata.credentials_supported && Array.isArray(metadata.credentials_supported)) {
|
|
3268
|
-
let typeSupported = false;
|
|
3269
|
-
metadata.credentials_supported.forEach((supportedCredential) => {
|
|
3270
|
-
const subTypes = getTypesFromCredentialSupported(supportedCredential);
|
|
3271
|
-
if (subTypes.every((t, i) => types[i] === t) || types.length === 1 && (types[0] === supportedCredential.id || subTypes.includes(types[0]))) {
|
|
3272
|
-
typeSupported = true;
|
|
3273
|
-
if (supportedCredential.credential_subject_issuance) {
|
|
3274
|
-
subjectIssuance = {
|
|
3275
|
-
credential_subject_issuance: supportedCredential.credential_subject_issuance
|
|
3276
|
-
};
|
|
3277
|
-
}
|
|
3278
|
-
}
|
|
3279
|
-
});
|
|
3280
|
-
if (!typeSupported) {
|
|
3281
|
-
console.log(`Not all credential types ${JSON.stringify(credentialTypes)} are present in metadata for ${this.getIssuer()}`);
|
|
3282
|
-
}
|
|
3283
|
-
} else if (metadata.credentials_supported && !Array.isArray(metadata.credentials_supported)) {
|
|
3284
|
-
const credentialsSupported = metadata.credentials_supported;
|
|
3285
|
-
if (types.some((type) => !metadata.credentials_supported || !credentialsSupported[type])) {
|
|
3286
|
-
throw Error(`Not all credential types ${JSON.stringify(credentialTypes)} are supported by issuer ${this.getIssuer()}`);
|
|
3287
|
-
}
|
|
3288
|
-
}
|
|
3289
|
-
}
|
|
3290
|
-
if (subjectIssuance) {
|
|
3291
|
-
requestBuilder.withSubjectIssuance(subjectIssuance);
|
|
3292
|
-
}
|
|
3293
|
-
const credentialRequestClient = requestBuilder.build();
|
|
3294
|
-
const proofBuilder = ProofOfPossessionBuilder.fromAccessTokenResponse({
|
|
3295
|
-
accessTokenResponse: this.accessTokenResponse,
|
|
3296
|
-
callbacks: proofCallbacks,
|
|
3297
|
-
version: this.version()
|
|
3298
|
-
}).withIssuer(this.getIssuer()).withAlg(this.alg);
|
|
3299
|
-
if (this._state.jwk) {
|
|
3300
|
-
proofBuilder.withJWK(this._state.jwk);
|
|
3301
|
-
}
|
|
3302
|
-
if (this._state.kid) {
|
|
3303
|
-
proofBuilder.withKid(this._state.kid);
|
|
3304
|
-
}
|
|
3305
|
-
if (this.clientId) {
|
|
3306
|
-
proofBuilder.withClientId(this.clientId);
|
|
3307
|
-
}
|
|
3308
|
-
if (jti) {
|
|
3309
|
-
proofBuilder.withJti(jti);
|
|
3310
|
-
}
|
|
3311
|
-
const response = await credentialRequestClient.acquireCredentialsUsingProof({
|
|
3312
|
-
proofInput: proofBuilder,
|
|
3313
|
-
credentialTypes,
|
|
3314
|
-
context,
|
|
3315
|
-
format,
|
|
3316
|
-
subjectIssuance,
|
|
3317
|
-
createDPoPOpts
|
|
3318
|
-
});
|
|
3319
|
-
this._state.dpopResponseParams = response.params;
|
|
3320
|
-
if (response.errorBody) {
|
|
3321
|
-
logger12.debug(`Credential request error:\r
|
|
3322
|
-
${JSON.stringify(response.errorBody)}`);
|
|
3323
|
-
throw Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed with status: ${response.origResponse.status}`);
|
|
3324
|
-
} else if (!response.successBody) {
|
|
3325
|
-
logger12.debug(`Credential request error. No success body`);
|
|
3326
|
-
throw Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`);
|
|
3327
|
-
}
|
|
3328
|
-
return {
|
|
3329
|
-
...response.successBody,
|
|
3330
|
-
...this.dpopResponseParams && {
|
|
3331
|
-
params: this.dpopResponseParams
|
|
3332
|
-
},
|
|
3333
|
-
access_token: response.access_token
|
|
3334
|
-
};
|
|
3335
|
-
}
|
|
3336
|
-
async exportState() {
|
|
3337
|
-
return JSON.stringify(this._state);
|
|
3338
|
-
}
|
|
3339
|
-
getCredentialsSupported(restrictToInitiationTypes, format) {
|
|
3340
|
-
return getSupportedCredentials({
|
|
3341
|
-
issuerMetadata: this.endpointMetadata.credentialIssuerMetadata,
|
|
3342
|
-
version: this.version(),
|
|
3343
|
-
format,
|
|
3344
|
-
types: restrictToInitiationTypes ? this.getCredentialOfferTypes() : void 0
|
|
3345
|
-
});
|
|
3346
|
-
}
|
|
3347
|
-
async sendNotification(credentialRequestOpts, request, accessToken) {
|
|
3348
|
-
return sendNotification(credentialRequestOpts, request, accessToken ?? this._state.accessToken ?? this._state.accessTokenResponse?.access_token);
|
|
3349
|
-
}
|
|
3350
|
-
getCredentialOfferTypes() {
|
|
3351
|
-
if (!this.credentialOffer) {
|
|
3352
|
-
return [];
|
|
3353
|
-
} else if (this.version() < OpenId4VCIVersion14.VER_1_0_11) {
|
|
3354
|
-
const orig = this.credentialOffer.original_credential_offer;
|
|
3355
|
-
const types = typeof orig.credential_type === "string" ? [
|
|
3356
|
-
orig.credential_type
|
|
3357
|
-
] : orig.credential_type;
|
|
3358
|
-
const result = [];
|
|
3359
|
-
result[0] = types;
|
|
3360
|
-
return result;
|
|
3361
|
-
} else if (this.version() < OpenId4VCIVersion14.VER_1_0_13) {
|
|
3362
|
-
return this.credentialOffer.credential_offer.credentials.map((c) => getTypesFromObject(c) ?? []);
|
|
3363
|
-
}
|
|
3364
|
-
return void 0;
|
|
3365
|
-
}
|
|
3366
|
-
issuerSupportedFlowTypes() {
|
|
3367
|
-
return this.credentialOffer?.supportedFlows ?? (this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server ? [
|
|
3368
|
-
AuthzFlowType3.AUTHORIZATION_CODE_FLOW
|
|
3369
|
-
] : []);
|
|
3370
|
-
}
|
|
3371
|
-
isFlowTypeSupported(flowType) {
|
|
3372
|
-
return this.issuerSupportedFlowTypes().includes(flowType);
|
|
3373
|
-
}
|
|
3374
|
-
get authorizationURL() {
|
|
3375
|
-
return this._state.authorizationURL;
|
|
3376
|
-
}
|
|
3377
|
-
hasAuthorizationURL() {
|
|
3378
|
-
return !!this.authorizationURL;
|
|
3379
|
-
}
|
|
3380
|
-
get credentialOffer() {
|
|
3381
|
-
return this._state.credentialOffer;
|
|
3382
|
-
}
|
|
3383
|
-
version() {
|
|
3384
|
-
if (this.credentialOffer?.version && this.credentialOffer.version !== OpenId4VCIVersion14.VER_UNKNOWN) {
|
|
3385
|
-
return this.credentialOffer.version;
|
|
3386
|
-
}
|
|
3387
|
-
const metadata = this._state.endpointMetadata;
|
|
3388
|
-
if (metadata?.credentialIssuerMetadata) {
|
|
3389
|
-
const versions = determineVersionsFromIssuerMetadata(metadata.credentialIssuerMetadata);
|
|
3390
|
-
if (versions.length > 0 && !versions.includes(OpenId4VCIVersion14.VER_UNKNOWN)) {
|
|
3391
|
-
return versions[0];
|
|
3392
|
-
}
|
|
3393
|
-
}
|
|
3394
|
-
return OpenId4VCIVersion14.VER_1_0_13;
|
|
3395
|
-
}
|
|
3396
|
-
get endpointMetadata() {
|
|
3397
|
-
this.assertServerMetadata();
|
|
3398
|
-
return this._state.endpointMetadata;
|
|
3399
|
-
}
|
|
3400
|
-
get kid() {
|
|
3401
|
-
this.assertIssuerData();
|
|
3402
|
-
if (!this._state.kid) {
|
|
3403
|
-
throw new Error("No value for kid is supplied");
|
|
3404
|
-
}
|
|
3405
|
-
return this._state.kid;
|
|
3406
|
-
}
|
|
3407
|
-
get alg() {
|
|
3408
|
-
this.assertIssuerData();
|
|
3409
|
-
if (!this._state.alg) {
|
|
3410
|
-
throw new Error("No value for alg is supplied");
|
|
3411
|
-
}
|
|
3412
|
-
return this._state.alg;
|
|
1872
|
+
constructor(builder) {
|
|
1873
|
+
this._builder = builder;
|
|
3413
1874
|
}
|
|
3414
|
-
|
|
3415
|
-
|
|
1875
|
+
static fromCredentialIssuer({ credentialIssuer, metadata, version, credentialIdentifier, credentialTypes }) {
|
|
1876
|
+
let builder;
|
|
1877
|
+
const metadataV15 = metadata;
|
|
1878
|
+
builder = CredentialRequestClientBuilderV1_0_15.fromCredentialIssuer({
|
|
1879
|
+
credentialIssuer,
|
|
1880
|
+
metadata: metadataV15,
|
|
1881
|
+
version,
|
|
1882
|
+
credentialIdentifier,
|
|
1883
|
+
credentialTypes
|
|
1884
|
+
});
|
|
1885
|
+
return new _CredentialRequestClientBuilder(builder);
|
|
3416
1886
|
}
|
|
3417
|
-
|
|
3418
|
-
|
|
1887
|
+
static async fromURI({ uri, metadata }) {
|
|
1888
|
+
const offer = await CredentialOfferClient.fromURI(uri);
|
|
1889
|
+
return _CredentialRequestClientBuilder.fromCredentialOfferRequest({
|
|
1890
|
+
request: offer,
|
|
1891
|
+
...offer,
|
|
1892
|
+
metadata,
|
|
1893
|
+
version: offer.version
|
|
1894
|
+
});
|
|
3419
1895
|
}
|
|
3420
|
-
|
|
3421
|
-
|
|
1896
|
+
static fromCredentialOfferRequest(opts) {
|
|
1897
|
+
const builder = CredentialRequestClientBuilderV1_0_15.fromCredentialOfferRequest(opts);
|
|
1898
|
+
return new _CredentialRequestClientBuilder(builder);
|
|
3422
1899
|
}
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
1900
|
+
static fromCredentialOffer({ credentialOffer, metadata }) {
|
|
1901
|
+
const builder = CredentialRequestClientBuilderV1_0_15.fromCredentialOffer({
|
|
1902
|
+
credentialOffer,
|
|
1903
|
+
metadata
|
|
1904
|
+
});
|
|
1905
|
+
return new _CredentialRequestClientBuilder(builder);
|
|
3426
1906
|
}
|
|
3427
|
-
|
|
3428
|
-
return this.
|
|
1907
|
+
getVersion() {
|
|
1908
|
+
return this._builder.version;
|
|
3429
1909
|
}
|
|
3430
|
-
|
|
3431
|
-
this.
|
|
3432
|
-
|
|
1910
|
+
withCredentialEndpointFromMetadata(metadata) {
|
|
1911
|
+
if (isV1_0_15(this._builder)) {
|
|
1912
|
+
this._builder.withCredentialEndpointFromMetadata(metadata);
|
|
1913
|
+
}
|
|
1914
|
+
return this;
|
|
3433
1915
|
}
|
|
3434
|
-
|
|
3435
|
-
this.
|
|
3436
|
-
|
|
3437
|
-
|
|
1916
|
+
withCredentialEndpoint(credentialEndpoint) {
|
|
1917
|
+
this._builder.withCredentialEndpoint(credentialEndpoint);
|
|
1918
|
+
return this;
|
|
1919
|
+
}
|
|
1920
|
+
withDeferredCredentialEndpointFromMetadata(metadata) {
|
|
1921
|
+
if (isV1_0_15(this._builder)) {
|
|
1922
|
+
this._builder.withDeferredCredentialEndpointFromMetadata(metadata);
|
|
3438
1923
|
}
|
|
3439
|
-
return this
|
|
3440
|
-
issuerOpts: {
|
|
3441
|
-
issuer: this.getIssuer()
|
|
3442
|
-
}
|
|
3443
|
-
}) : AccessTokenClient.determineTokenURL({
|
|
3444
|
-
issuerOpts: {
|
|
3445
|
-
issuer: this.getIssuer()
|
|
3446
|
-
}
|
|
3447
|
-
});
|
|
1924
|
+
return this;
|
|
3448
1925
|
}
|
|
3449
|
-
|
|
3450
|
-
this.
|
|
3451
|
-
return this
|
|
1926
|
+
withDeferredCredentialEndpoint(deferredCredentialEndpoint) {
|
|
1927
|
+
this._builder.withDeferredCredentialEndpoint(deferredCredentialEndpoint);
|
|
1928
|
+
return this;
|
|
3452
1929
|
}
|
|
3453
|
-
|
|
3454
|
-
this.
|
|
3455
|
-
return this
|
|
1930
|
+
withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS) {
|
|
1931
|
+
this._builder.withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS);
|
|
1932
|
+
return this;
|
|
3456
1933
|
}
|
|
3457
|
-
|
|
3458
|
-
|
|
1934
|
+
withCredentialIdentifier(credentialIdentifier) {
|
|
1935
|
+
if (this._builder.version === void 0 || this._builder.version < OpenId4VCIVersion7.VER_1_0_15) {
|
|
1936
|
+
throw new Error("Version of spec should be equal or higher than v1_0_15");
|
|
1937
|
+
}
|
|
1938
|
+
;
|
|
1939
|
+
this._builder.withCredentialIdentifier(credentialIdentifier);
|
|
1940
|
+
return this;
|
|
3459
1941
|
}
|
|
3460
|
-
|
|
3461
|
-
|
|
1942
|
+
withIssuerState(issuerState) {
|
|
1943
|
+
this._builder.withIssuerState(issuerState);
|
|
1944
|
+
return this;
|
|
3462
1945
|
}
|
|
3463
|
-
|
|
3464
|
-
this.
|
|
3465
|
-
return this
|
|
1946
|
+
withCredentialType(credentialTypes) {
|
|
1947
|
+
this._builder.withCredentialType(credentialTypes);
|
|
1948
|
+
return this;
|
|
3466
1949
|
}
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
isEBSI() {
|
|
3471
|
-
if (this.credentialOffer && this.credentialOffer?.credential_offer?.credentials?.find((cred) => (
|
|
3472
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
3473
|
-
// @ts-ignore
|
|
3474
|
-
typeof cred !== "string" && "trust_framework" in cred && "name" in cred.trust_framework && cred.trust_framework.name.includes("ebsi")
|
|
3475
|
-
))) {
|
|
3476
|
-
return true;
|
|
3477
|
-
}
|
|
3478
|
-
return this.clientId?.includes("ebsi") || this._state.kid?.includes("did:ebsi:") || this.getIssuer().includes("ebsi") || this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes("ebsi.eu") || this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes("ebsi.eu");
|
|
1950
|
+
withSubjectIssuance(subjectIssuance) {
|
|
1951
|
+
this._builder.withSubjectIssuance(subjectIssuance);
|
|
1952
|
+
return this;
|
|
3479
1953
|
}
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
} else if (!this._state.credentialOffer && this._state.endpointMetadata && this.issuerSupportedFlowTypes().length === 0) {
|
|
3484
|
-
throw Error(`No issuance initiation or credential offer present`);
|
|
3485
|
-
}
|
|
1954
|
+
withToken(accessToken) {
|
|
1955
|
+
this._builder.withToken(accessToken);
|
|
1956
|
+
return this;
|
|
3486
1957
|
}
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
}
|
|
1958
|
+
withTokenFromResponse(response) {
|
|
1959
|
+
this._builder.withTokenFromResponse(response);
|
|
1960
|
+
return this;
|
|
3491
1961
|
}
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
}
|
|
1962
|
+
withVersion(version) {
|
|
1963
|
+
this._builder.withVersion(version);
|
|
1964
|
+
return this;
|
|
3496
1965
|
}
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
...this._state?.authorizationRequestOpts?.requestObjectOpts,
|
|
3500
|
-
...opts?.requestObjectOpts
|
|
3501
|
-
};
|
|
3502
|
-
let authorizationRequestOpts = {
|
|
3503
|
-
...this._state?.authorizationRequestOpts,
|
|
3504
|
-
...opts,
|
|
3505
|
-
...requestObjectOpts && {
|
|
3506
|
-
requestObjectOpts
|
|
3507
|
-
}
|
|
3508
|
-
};
|
|
3509
|
-
if (!authorizationRequestOpts) {
|
|
3510
|
-
authorizationRequestOpts = {
|
|
3511
|
-
redirectUri: `${DefaultURISchemes.CREDENTIAL_OFFER}://`
|
|
3512
|
-
};
|
|
3513
|
-
}
|
|
3514
|
-
const clientId = authorizationRequestOpts.clientId ?? this._state.clientId;
|
|
3515
|
-
this._state.clientId = clientId;
|
|
3516
|
-
authorizationRequestOpts.clientId = clientId;
|
|
3517
|
-
return authorizationRequestOpts;
|
|
1966
|
+
build() {
|
|
1967
|
+
return this._builder.build();
|
|
3518
1968
|
}
|
|
3519
|
-
getAuthorizationCode = /* @__PURE__ */ __name((authorizationResponse, code) => {
|
|
3520
|
-
if (authorizationResponse) {
|
|
3521
|
-
this._state.authorizationCodeResponse = {
|
|
3522
|
-
...toAuthorizationResponsePayload(authorizationResponse)
|
|
3523
|
-
};
|
|
3524
|
-
} else if (code) {
|
|
3525
|
-
this._state.authorizationCodeResponse = {
|
|
3526
|
-
code
|
|
3527
|
-
};
|
|
3528
|
-
}
|
|
3529
|
-
return this._state.authorizationCodeResponse?.code ?? this._state.authorizationCodeResponse?.authorization_code;
|
|
3530
|
-
}, "getAuthorizationCode");
|
|
3531
1969
|
};
|
|
3532
1970
|
|
|
3533
|
-
// lib/
|
|
3534
|
-
import { AuthzFlowType as
|
|
3535
|
-
import { Loggers as
|
|
3536
|
-
|
|
3537
|
-
|
|
1971
|
+
// lib/OpenID4VCIClient.ts
|
|
1972
|
+
import { AuthzFlowType as AuthzFlowType3, CodeChallengeMethod as CodeChallengeMethod4, DefaultURISchemes as DefaultURISchemes2, determineVersionsFromIssuerMetadata, getClientIdFromCredentialOfferPayload as getClientIdFromCredentialOfferPayload3, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload6, getSupportedCredentials as getSupportedCredentials2, getTypesFromCredentialSupported, KID_JWK_X5C_ERROR as KID_JWK_X5C_ERROR2, OpenId4VCIVersion as OpenId4VCIVersion9, toAuthorizationResponsePayload as toAuthorizationResponsePayload2 } from "@sphereon/oid4vci-common";
|
|
1973
|
+
import { Loggers as Loggers8 } from "@sphereon/ssi-types";
|
|
1974
|
+
|
|
1975
|
+
// lib/OpenID4VCIClientV1_0_15.ts
|
|
1976
|
+
import { AuthzFlowType as AuthzFlowType2, CodeChallengeMethod as CodeChallengeMethod3, DefaultURISchemes, getClientIdFromCredentialOfferPayload as getClientIdFromCredentialOfferPayload2, getIssuerFromCredentialOfferPayload as getIssuerFromCredentialOfferPayload5, getSupportedCredentials, KID_JWK_X5C_ERROR, OpenId4VCIVersion as OpenId4VCIVersion8, toAuthorizationResponsePayload } from "@sphereon/oid4vci-common";
|
|
1977
|
+
import { Loggers as Loggers7 } from "@sphereon/ssi-types";
|
|
1978
|
+
|
|
1979
|
+
// lib/NonceClient.ts
|
|
1980
|
+
import { formPost as formPost3 } from "@sphereon/oid4vci-common";
|
|
1981
|
+
var sendNonceRequest = /* @__PURE__ */ __name(async (nonceEndpointUrl, opts) => {
|
|
1982
|
+
return await formPost3(nonceEndpointUrl, new URLSearchParams(), {
|
|
1983
|
+
customHeaders: opts?.headers
|
|
1984
|
+
});
|
|
1985
|
+
}, "sendNonceRequest");
|
|
1986
|
+
var acquireNonceFromAuthorizationServer = /* @__PURE__ */ __name(async (opts) => {
|
|
1987
|
+
const metadata = opts?.metadata ? opts.metadata : opts?.issuerOpts?.fetchMetadata ? await MetadataClient.retrieveAllMetadata(opts.issuerOpts.issuer, {
|
|
1988
|
+
errorOnNotFound: false
|
|
1989
|
+
}) : void 0;
|
|
1990
|
+
const nonceEndpointUrl = metadata?.credentialIssuerMetadata?.nonce_endpoint;
|
|
1991
|
+
if (!nonceEndpointUrl) {
|
|
1992
|
+
return Promise.reject(Error("Cannot determine nonce endpoint URL"));
|
|
1993
|
+
}
|
|
1994
|
+
return await sendNonceRequest(nonceEndpointUrl, {
|
|
1995
|
+
headers: opts?.headers
|
|
1996
|
+
});
|
|
1997
|
+
}, "acquireNonceFromAuthorizationServer");
|
|
1998
|
+
|
|
1999
|
+
// lib/OpenID4VCIClientV1_0_15.ts
|
|
2000
|
+
var logger7 = Loggers7.DEFAULT.get("sphereon:oid4vci:v15");
|
|
2001
|
+
var OpenID4VCIClientV1_0_15 = class _OpenID4VCIClientV1_0_15 {
|
|
3538
2002
|
static {
|
|
3539
|
-
__name(this, "
|
|
2003
|
+
__name(this, "OpenID4VCIClientV1_0_15");
|
|
3540
2004
|
}
|
|
3541
2005
|
_state;
|
|
3542
|
-
constructor({ credentialOffer, clientId, kid, alg, credentialIssuer, pkce, authorizationRequest,
|
|
3543
|
-
const issuer = credentialIssuer ?? (credentialOffer ?
|
|
2006
|
+
constructor({ credentialOffer, clientId, kid, alg, credentialIssuer, pkce, authorizationRequest, jwk, endpointMetadata, accessTokenResponse, authorizationRequestOpts, authorizationCodeResponse, authorizationURL, keyAttestation }) {
|
|
2007
|
+
const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload5(credentialOffer.credential_offer) : void 0);
|
|
3544
2008
|
if (!issuer) {
|
|
3545
2009
|
throw Error("No credential issuer supplied or deduced from offer");
|
|
3546
2010
|
}
|
|
@@ -3549,39 +2013,39 @@ var OpenID4VCIClientV1_0_13 = class _OpenID4VCIClientV1_0_13 {
|
|
|
3549
2013
|
credentialIssuer: issuer,
|
|
3550
2014
|
kid,
|
|
3551
2015
|
alg,
|
|
3552
|
-
|
|
3553
|
-
clientId: clientId ?? (credentialOffer && getClientIdFromCredentialOfferPayload4(credentialOffer.credential_offer)) ?? kid?.split("#")[0],
|
|
2016
|
+
clientId: clientId ?? (credentialOffer && getClientIdFromCredentialOfferPayload2(credentialOffer.credential_offer)) ?? kid?.split("#")[0],
|
|
3554
2017
|
pkce: {
|
|
3555
2018
|
disabled: false,
|
|
3556
|
-
codeChallengeMethod:
|
|
2019
|
+
codeChallengeMethod: CodeChallengeMethod3.S256,
|
|
3557
2020
|
...pkce
|
|
3558
2021
|
},
|
|
3559
2022
|
authorizationRequestOpts,
|
|
3560
2023
|
authorizationCodeResponse,
|
|
3561
|
-
accessToken,
|
|
3562
2024
|
jwk,
|
|
3563
2025
|
endpointMetadata,
|
|
3564
2026
|
accessTokenResponse,
|
|
3565
|
-
authorizationURL
|
|
2027
|
+
authorizationURL,
|
|
2028
|
+
keyAttestation
|
|
3566
2029
|
};
|
|
3567
2030
|
if (!this._state.authorizationRequestOpts) {
|
|
3568
2031
|
this._state.authorizationRequestOpts = this.syncAuthorizationRequestOpts(authorizationRequest);
|
|
3569
2032
|
}
|
|
3570
|
-
|
|
2033
|
+
logger7.debug(`Authorization req options: ${JSON.stringify(this._state.authorizationRequestOpts, null, 2)}`);
|
|
3571
2034
|
}
|
|
3572
|
-
static async fromCredentialIssuer({ kid, alg, retrieveServerMetadata, clientId, credentialIssuer, pkce, authorizationRequest, createAuthorizationRequestURL }) {
|
|
3573
|
-
const client = new
|
|
2035
|
+
static async fromCredentialIssuer({ kid, alg, retrieveServerMetadata, clientId, credentialIssuer, pkce, authorizationRequest, createAuthorizationRequestURL, keyAttestation }) {
|
|
2036
|
+
const client = new _OpenID4VCIClientV1_0_15({
|
|
3574
2037
|
kid,
|
|
3575
2038
|
alg,
|
|
3576
2039
|
clientId: clientId ?? authorizationRequest?.clientId,
|
|
3577
2040
|
credentialIssuer,
|
|
3578
2041
|
pkce,
|
|
3579
|
-
authorizationRequest
|
|
2042
|
+
authorizationRequest,
|
|
2043
|
+
keyAttestation
|
|
3580
2044
|
});
|
|
3581
|
-
if (retrieveServerMetadata
|
|
2045
|
+
if (retrieveServerMetadata !== false) {
|
|
3582
2046
|
await client.retrieveServerMetadata();
|
|
3583
2047
|
}
|
|
3584
|
-
if (createAuthorizationRequestURL
|
|
2048
|
+
if (createAuthorizationRequestURL !== false) {
|
|
3585
2049
|
await client.createAuthorizationRequestUrl({
|
|
3586
2050
|
authorizationRequest,
|
|
3587
2051
|
pkce
|
|
@@ -3591,38 +2055,33 @@ var OpenID4VCIClientV1_0_13 = class _OpenID4VCIClientV1_0_13 {
|
|
|
3591
2055
|
}
|
|
3592
2056
|
static async fromState({ state }) {
|
|
3593
2057
|
const clientState = typeof state === "string" ? JSON.parse(state) : state;
|
|
3594
|
-
return new
|
|
2058
|
+
return new _OpenID4VCIClientV1_0_15(clientState);
|
|
3595
2059
|
}
|
|
3596
|
-
static async fromURI({ uri, kid, alg, retrieveServerMetadata, clientId, pkce, createAuthorizationRequestURL, authorizationRequest, resolveOfferUri }) {
|
|
3597
|
-
const credentialOfferClient = await
|
|
2060
|
+
static async fromURI({ uri, kid, alg, retrieveServerMetadata, clientId, pkce, createAuthorizationRequestURL, authorizationRequest, resolveOfferUri, keyAttestation }) {
|
|
2061
|
+
const credentialOfferClient = await CredentialOfferClientV1_0_15.fromURI(uri, {
|
|
3598
2062
|
resolve: resolveOfferUri
|
|
3599
2063
|
});
|
|
3600
|
-
const client = new
|
|
2064
|
+
const client = new _OpenID4VCIClientV1_0_15({
|
|
3601
2065
|
credentialOffer: credentialOfferClient,
|
|
3602
2066
|
kid,
|
|
3603
2067
|
alg,
|
|
3604
2068
|
clientId: clientId ?? authorizationRequest?.clientId ?? credentialOfferClient.clientId,
|
|
3605
2069
|
pkce,
|
|
3606
|
-
authorizationRequest
|
|
2070
|
+
authorizationRequest,
|
|
2071
|
+
keyAttestation
|
|
3607
2072
|
});
|
|
3608
|
-
if (retrieveServerMetadata
|
|
2073
|
+
if (retrieveServerMetadata !== false) {
|
|
3609
2074
|
await client.retrieveServerMetadata();
|
|
3610
2075
|
}
|
|
3611
|
-
if (credentialOfferClient.supportedFlows.includes(
|
|
2076
|
+
if (credentialOfferClient.supportedFlows.includes(AuthzFlowType2.AUTHORIZATION_CODE_FLOW) && createAuthorizationRequestURL !== false) {
|
|
3612
2077
|
await client.createAuthorizationRequestUrl({
|
|
3613
2078
|
authorizationRequest,
|
|
3614
2079
|
pkce
|
|
3615
2080
|
});
|
|
3616
|
-
|
|
2081
|
+
logger7.debug(`Authorization Request URL: ${client._state.authorizationURL}`);
|
|
3617
2082
|
}
|
|
3618
2083
|
return client;
|
|
3619
2084
|
}
|
|
3620
|
-
/**
|
|
3621
|
-
* Allows you to create an Authorization Request URL when using an Authorization Code flow. This URL needs to be accessed using the front channel (browser)
|
|
3622
|
-
*
|
|
3623
|
-
* The Identity provider would present a login screen typically; after you authenticated, it would redirect to the provided redirectUri; which can be same device or cross-device
|
|
3624
|
-
* @param opts
|
|
3625
|
-
*/
|
|
3626
2085
|
async createAuthorizationRequestUrl(opts) {
|
|
3627
2086
|
if (!this._state.authorizationURL) {
|
|
3628
2087
|
this.calculatePKCEOpts(opts?.pkce);
|
|
@@ -3638,8 +2097,7 @@ var OpenID4VCIClientV1_0_13 = class _OpenID4VCIClientV1_0_13 {
|
|
|
3638
2097
|
endpointMetadata: this.endpointMetadata,
|
|
3639
2098
|
authorizationRequest: this._state.authorizationRequestOpts,
|
|
3640
2099
|
credentialOffer: this.credentialOffer,
|
|
3641
|
-
credentialConfigurationSupported: this.getCredentialsSupported()
|
|
3642
|
-
version: this.version()
|
|
2100
|
+
credentialConfigurationSupported: this.getCredentialsSupported(false)
|
|
3643
2101
|
});
|
|
3644
2102
|
}
|
|
3645
2103
|
return this._state.authorizationURL;
|
|
@@ -3648,15 +2106,34 @@ var OpenID4VCIClientV1_0_13 = class _OpenID4VCIClientV1_0_13 {
|
|
|
3648
2106
|
this.assertIssuerData();
|
|
3649
2107
|
if (!this._state.endpointMetadata) {
|
|
3650
2108
|
if (this.credentialOffer) {
|
|
3651
|
-
this._state.endpointMetadata = await
|
|
2109
|
+
this._state.endpointMetadata = await MetadataClientV1_0_15.retrieveAllMetadataFromCredentialOffer(this.credentialOffer);
|
|
3652
2110
|
} else if (this._state.credentialIssuer) {
|
|
3653
|
-
this._state.endpointMetadata = await
|
|
2111
|
+
this._state.endpointMetadata = await MetadataClientV1_0_15.retrieveAllMetadata(this._state.credentialIssuer);
|
|
3654
2112
|
} else {
|
|
3655
2113
|
throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`);
|
|
3656
2114
|
}
|
|
3657
2115
|
}
|
|
3658
2116
|
return this.endpointMetadata;
|
|
3659
2117
|
}
|
|
2118
|
+
async acquireNonce() {
|
|
2119
|
+
const response = await acquireNonceFromAuthorizationServer({
|
|
2120
|
+
metadata: this.endpointMetadata,
|
|
2121
|
+
issuerOpts: {
|
|
2122
|
+
issuer: this.getIssuer(),
|
|
2123
|
+
fetchMetadata: false
|
|
2124
|
+
}
|
|
2125
|
+
});
|
|
2126
|
+
if (response.errorBody) {
|
|
2127
|
+
logger7.debug(`Nonce request error:\r
|
|
2128
|
+
${JSON.stringify(response.errorBody)}`);
|
|
2129
|
+
return Promise.reject(Error(`Retrieving a nonce from ${this._state.endpointMetadata?.credentialIssuerMetadata?.nonce_endpoint} for issuer ${this.getIssuer()} failed with error: ${response.errorBody.error}${response.errorBody.error_description ? ` - ${response.errorBody.error_description}` : ""}`));
|
|
2130
|
+
} else if (!response.successBody) {
|
|
2131
|
+
logger7.debug(`Nonce request error. No success body`);
|
|
2132
|
+
return Promise.reject(Error(`Retrieving a nonce from ${this._state.endpointMetadata?.credentialIssuerMetadata?.nonce_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`));
|
|
2133
|
+
}
|
|
2134
|
+
this._state.cachedCNonce = response.successBody.c_nonce;
|
|
2135
|
+
return response.successBody.c_nonce;
|
|
2136
|
+
}
|
|
3660
2137
|
calculatePKCEOpts(pkce) {
|
|
3661
2138
|
this._state.pkce = generateMissingPKCEOpts({
|
|
3662
2139
|
...this._state.pkce,
|
|
@@ -3671,12 +2148,12 @@ var OpenID4VCIClientV1_0_13 = class _OpenID4VCIClientV1_0_13 {
|
|
|
3671
2148
|
...opts
|
|
3672
2149
|
});
|
|
3673
2150
|
if (response.errorBody) {
|
|
3674
|
-
|
|
2151
|
+
logger7.debug(`Authorization code error:\r
|
|
3675
2152
|
${JSON.stringify(response.errorBody)}`);
|
|
3676
2153
|
const error = response.errorBody;
|
|
3677
2154
|
return Promise.reject(error);
|
|
3678
2155
|
} else if (!response.successBody) {
|
|
3679
|
-
|
|
2156
|
+
logger7.debug(`Authorization code error. No success body`);
|
|
3680
2157
|
return Promise.reject(Error(`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`));
|
|
3681
2158
|
}
|
|
3682
2159
|
return {
|
|
@@ -3748,16 +2225,19 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
3748
2225
|
}
|
|
3749
2226
|
});
|
|
3750
2227
|
if (response.errorBody) {
|
|
3751
|
-
|
|
2228
|
+
logger7.debug(`Access token error:\r
|
|
3752
2229
|
${JSON.stringify(response.errorBody)}`);
|
|
3753
2230
|
throw Error(`Retrieving an access token from ${this._state.endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed with status: ${response.origResponse.status}`);
|
|
3754
2231
|
} else if (!response.successBody) {
|
|
3755
|
-
|
|
2232
|
+
logger7.debug(`Access token error. No success body`);
|
|
3756
2233
|
throw Error(`Retrieving an access token from ${this._state.endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`);
|
|
3757
2234
|
}
|
|
3758
2235
|
this._state.accessTokenResponse = response.successBody;
|
|
3759
2236
|
this._state.dpopResponseParams = response.params;
|
|
3760
2237
|
this._state.accessToken = response.successBody.access_token;
|
|
2238
|
+
if (response.successBody.c_nonce) {
|
|
2239
|
+
this._state.cachedCNonce = response.successBody.c_nonce;
|
|
2240
|
+
}
|
|
3761
2241
|
}
|
|
3762
2242
|
return {
|
|
3763
2243
|
...this.accessTokenResponse,
|
|
@@ -3766,77 +2246,54 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
3766
2246
|
}
|
|
3767
2247
|
};
|
|
3768
2248
|
}
|
|
3769
|
-
async
|
|
3770
|
-
return await this.acquireCredentialsImpl(args);
|
|
3771
|
-
}
|
|
3772
|
-
async acquireCredentials(args) {
|
|
3773
|
-
return await this.acquireCredentialsImpl(args);
|
|
3774
|
-
}
|
|
3775
|
-
async acquireCredentialsImpl({ credentialIdentifier, credentialTypes, context, proofCallbacks, format, kid, jwk, alg, jti, deferredCredentialAwait, deferredCredentialIntervalInMS, createDPoPOpts }) {
|
|
2249
|
+
async acquireCredentials({ credentialIdentifier, credentialConfigurationId, credentialTypes, context, proofCallbacks, format, kid, jwk, alg, jti, deferredCredentialAwait, deferredCredentialIntervalInMS, createDPoPOpts }) {
|
|
3776
2250
|
if ([
|
|
3777
2251
|
jwk,
|
|
3778
2252
|
kid
|
|
3779
2253
|
].filter((v) => v !== void 0).length > 1) {
|
|
3780
|
-
throw new Error(
|
|
2254
|
+
throw new Error(KID_JWK_X5C_ERROR + `. jwk: ${jwk !== void 0}, kid: ${kid !== void 0}`);
|
|
3781
2255
|
}
|
|
3782
2256
|
if (alg) this._state.alg = alg;
|
|
3783
2257
|
if (jwk) this._state.jwk = jwk;
|
|
3784
2258
|
if (kid) this._state.kid = kid;
|
|
3785
|
-
const requestBuilder = this.credentialOffer ?
|
|
2259
|
+
const requestBuilder = this.credentialOffer ? CredentialRequestClientBuilderV1_0_15.fromCredentialOffer({
|
|
3786
2260
|
credentialOffer: this.credentialOffer,
|
|
3787
2261
|
metadata: this.endpointMetadata
|
|
3788
|
-
}) :
|
|
2262
|
+
}) : CredentialRequestClientBuilderV1_0_15.fromCredentialIssuer({
|
|
3789
2263
|
credentialIssuer: this.getIssuer(),
|
|
2264
|
+
credentialTypes,
|
|
3790
2265
|
credentialIdentifier,
|
|
2266
|
+
credentialConfigurationId,
|
|
3791
2267
|
metadata: this.endpointMetadata,
|
|
3792
2268
|
version: this.version()
|
|
3793
2269
|
});
|
|
3794
|
-
|
|
2270
|
+
if (credentialIdentifier) {
|
|
2271
|
+
requestBuilder.withCredentialIdentifier(credentialIdentifier);
|
|
2272
|
+
} else if (credentialConfigurationId) {
|
|
2273
|
+
requestBuilder.withCredentialConfigurationId(credentialConfigurationId);
|
|
2274
|
+
}
|
|
2275
|
+
const issuerState = this.issuerSupportedFlowTypes().includes(AuthzFlowType2.AUTHORIZATION_CODE_FLOW) && this._state.authorizationCodeResponse && !this._state.cachedCNonce && this._state.credentialOffer?.issuerState ? this._state.credentialOffer.issuerState : void 0;
|
|
3795
2276
|
requestBuilder.withIssuerState(issuerState);
|
|
3796
2277
|
requestBuilder.withTokenFromResponse(this.accessTokenResponse);
|
|
3797
2278
|
requestBuilder.withDeferredCredentialAwait(deferredCredentialAwait ?? false, deferredCredentialIntervalInMS);
|
|
3798
2279
|
let subjectIssuance;
|
|
3799
2280
|
if (this.endpointMetadata?.credentialIssuerMetadata) {
|
|
3800
2281
|
const metadata = this.endpointMetadata.credentialIssuerMetadata;
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
const credentialsSupported = metadata.credential_configurations_supported;
|
|
3809
|
-
if (!credentialsSupported || !credentialsSupported[credentialIdentifier]) {
|
|
3810
|
-
throw new Error(`Credential type ${credentialIdentifier} is not supported by issuer ${this.getIssuer()}`);
|
|
3811
|
-
}
|
|
3812
|
-
} else if (!types) {
|
|
3813
|
-
throw Error(`If no credential_identifier is used, we expect types`);
|
|
3814
|
-
} else if (metadata.credentials_supported && Array.isArray(metadata.credentials_supported)) {
|
|
3815
|
-
let typeSupported = false;
|
|
3816
|
-
metadata.credentials_supported.forEach((supportedCredential) => {
|
|
3817
|
-
const subTypes = getTypesFromCredentialSupported2(supportedCredential);
|
|
3818
|
-
if (subTypes.every((t, i) => types[i] === t) || types.length === 1 && (types[0] === supportedCredential.id || subTypes.includes(types[0]))) {
|
|
3819
|
-
typeSupported = true;
|
|
3820
|
-
if (supportedCredential.credential_subject_issuance) {
|
|
2282
|
+
if (metadata.credential_configurations_supported) {
|
|
2283
|
+
const configId = credentialConfigurationId ?? credentialIdentifier;
|
|
2284
|
+
if (configId && metadata.credential_configurations_supported[configId]) {
|
|
2285
|
+
const config = metadata.credential_configurations_supported[configId];
|
|
2286
|
+
if (config.credential_subject_issuance) {
|
|
2287
|
+
const subjIssuance = config.credential_subject_issuance;
|
|
2288
|
+
if (subjIssuance.subject_proof_mode && subjIssuance.notification_events_supported) {
|
|
3821
2289
|
subjectIssuance = {
|
|
3822
|
-
credential_subject_issuance:
|
|
2290
|
+
credential_subject_issuance: {
|
|
2291
|
+
subject_proof_mode: subjIssuance.subject_proof_mode,
|
|
2292
|
+
notification_events_supported: subjIssuance.notification_events_supported
|
|
2293
|
+
}
|
|
3823
2294
|
};
|
|
3824
2295
|
}
|
|
3825
2296
|
}
|
|
3826
|
-
});
|
|
3827
|
-
if (!typeSupported) {
|
|
3828
|
-
console.log(`Not all credential types ${JSON.stringify(credentialTypes)} are present in metadata for ${this.getIssuer()}`);
|
|
3829
|
-
}
|
|
3830
|
-
} else if (metadata.credential_configurations_supported && typeof metadata.credential_configurations_supported === "object") {
|
|
3831
|
-
let typeSupported = false;
|
|
3832
|
-
Object.values(metadata.credential_configurations_supported).forEach((supportedCredential) => {
|
|
3833
|
-
const subTypes = getTypesFromCredentialSupported2(supportedCredential);
|
|
3834
|
-
if (subTypes.every((t, i) => types[i] === t) || types.length === 1 && (types[0] === supportedCredential.id || subTypes.includes(types[0]))) {
|
|
3835
|
-
typeSupported = true;
|
|
3836
|
-
}
|
|
3837
|
-
});
|
|
3838
|
-
if (!typeSupported) {
|
|
3839
|
-
throw Error(`Not all credential types ${JSON.stringify(credentialTypes)} are supported by issuer ${this.getIssuer()}`);
|
|
3840
2297
|
}
|
|
3841
2298
|
}
|
|
3842
2299
|
}
|
|
@@ -3844,50 +2301,48 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
3844
2301
|
requestBuilder.withSubjectIssuance(subjectIssuance);
|
|
3845
2302
|
}
|
|
3846
2303
|
const credentialRequestClient = requestBuilder.build();
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
2304
|
+
if (!this._state.cachedCNonce) {
|
|
2305
|
+
await this.acquireNonce();
|
|
2306
|
+
}
|
|
2307
|
+
const proofBuilder = ProofOfPossessionBuilder.fromAccessTokenResponse({
|
|
2308
|
+
accessTokenResponse: {
|
|
2309
|
+
...this.accessTokenResponse,
|
|
2310
|
+
c_nonce: this._state.cachedCNonce
|
|
2311
|
+
},
|
|
2312
|
+
callbacks: proofCallbacks,
|
|
2313
|
+
version: this.version()
|
|
2314
|
+
}).withIssuer(this.getIssuer()).withAlg(this.alg);
|
|
2315
|
+
if (this._state.jwk) {
|
|
2316
|
+
proofBuilder.withJWK(this._state.jwk);
|
|
2317
|
+
}
|
|
2318
|
+
if (this._state.kid) {
|
|
2319
|
+
proofBuilder.withKid(this._state.kid);
|
|
2320
|
+
}
|
|
2321
|
+
if (this.clientId && (!this.credentialOffer || this.credentialOffer.supportedFlows.includes(AuthzFlowType2.AUTHORIZATION_CODE_FLOW) && !this.credentialOffer.preAuthorizedCode)) {
|
|
2322
|
+
proofBuilder.withClientId(this.clientId);
|
|
2323
|
+
}
|
|
2324
|
+
if (jti) {
|
|
2325
|
+
proofBuilder.withJti(jti);
|
|
2326
|
+
}
|
|
2327
|
+
if (this._state.cachedCNonce) {
|
|
2328
|
+
proofBuilder.withAccessTokenNonce(this._state.cachedCNonce);
|
|
3866
2329
|
}
|
|
3867
|
-
const
|
|
2330
|
+
const response = await credentialRequestClient.acquireCredentialsUsingProof({
|
|
3868
2331
|
proofInput: proofBuilder,
|
|
3869
|
-
credentialTypes,
|
|
3870
|
-
context,
|
|
3871
|
-
format,
|
|
3872
|
-
version: this.version(),
|
|
3873
2332
|
credentialIdentifier,
|
|
3874
|
-
subjectIssuance
|
|
3875
|
-
}) : await credentialRequestClient.createCredentialRequestWithoutProof({
|
|
3876
2333
|
credentialTypes,
|
|
3877
2334
|
context,
|
|
3878
2335
|
format,
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
subjectIssuance
|
|
2336
|
+
subjectIssuance,
|
|
2337
|
+
createDPoPOpts
|
|
3882
2338
|
});
|
|
3883
|
-
const response = await credentialRequestClient.acquireCredentialsUsingRequest(request, createDPoPOpts);
|
|
3884
2339
|
this._state.dpopResponseParams = response.params;
|
|
3885
2340
|
if (response.errorBody) {
|
|
3886
|
-
|
|
2341
|
+
logger7.debug(`Credential request error:\r
|
|
3887
2342
|
${JSON.stringify(response.errorBody)}`);
|
|
3888
2343
|
throw Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed with status: ${response.origResponse.status}`);
|
|
3889
2344
|
} else if (!response.successBody) {
|
|
3890
|
-
|
|
2345
|
+
logger7.debug(`Credential request error. No success body`);
|
|
3891
2346
|
throw Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`);
|
|
3892
2347
|
}
|
|
3893
2348
|
return {
|
|
@@ -3901,59 +2356,44 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
3901
2356
|
async exportState() {
|
|
3902
2357
|
return JSON.stringify(this._state);
|
|
3903
2358
|
}
|
|
3904
|
-
getCredentialsSupported(format) {
|
|
3905
|
-
return
|
|
2359
|
+
getCredentialsSupported(restrictToInitiationTypes, format) {
|
|
2360
|
+
return getSupportedCredentials({
|
|
3906
2361
|
issuerMetadata: this.endpointMetadata.credentialIssuerMetadata,
|
|
3907
2362
|
version: this.version(),
|
|
3908
2363
|
format,
|
|
3909
|
-
types:
|
|
2364
|
+
types: restrictToInitiationTypes ? [
|
|
2365
|
+
this.getCredentialOfferConfigurationIds()
|
|
2366
|
+
] : void 0
|
|
3910
2367
|
});
|
|
3911
2368
|
}
|
|
3912
2369
|
async sendNotification(credentialRequestOpts, request, accessToken) {
|
|
3913
2370
|
return sendNotification(credentialRequestOpts, request, accessToken ?? this._state.accessToken ?? this._state.accessTokenResponse?.access_token);
|
|
3914
2371
|
}
|
|
3915
|
-
|
|
2372
|
+
getCredentialOfferConfigurationIds() {
|
|
3916
2373
|
if (!this.credentialOffer) {
|
|
3917
2374
|
return [];
|
|
3918
|
-
} else if (this.credentialOffer.version < OpenId4VCIVersion.VER_1_0_11) {
|
|
3919
|
-
const orig = this.credentialOffer.original_credential_offer as CredentialOfferPayloadV1_0_08;
|
|
3920
|
-
const types: string[] = typeof orig.credential_type === 'string' ? [orig.credential_type] : orig.credential_type;
|
|
3921
|
-
const result: string[][] = [];
|
|
3922
|
-
result[0] = types;
|
|
3923
|
-
return result;
|
|
3924
|
-
} else {
|
|
3925
|
-
return this.credentialOffer.credential_offer.credentials.map((c) => {
|
|
3926
|
-
if (typeof c === 'string') {
|
|
3927
|
-
return [c];
|
|
3928
|
-
} else if ('types' in c) {
|
|
3929
|
-
return c.types;
|
|
3930
|
-
} else if ('vct' in c) {
|
|
3931
|
-
return [c.vct];
|
|
3932
|
-
} else {
|
|
3933
|
-
return c.credential_definition.types;
|
|
3934
|
-
}
|
|
3935
|
-
});
|
|
3936
2375
|
}
|
|
3937
|
-
|
|
2376
|
+
return this.credentialOffer.credential_offer?.credential_configuration_ids ?? [];
|
|
2377
|
+
}
|
|
3938
2378
|
issuerSupportedFlowTypes() {
|
|
3939
|
-
return this.credentialOffer?.supportedFlows ?? (this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ? [
|
|
3940
|
-
|
|
2379
|
+
return this.credentialOffer?.supportedFlows ?? (this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server ? [
|
|
2380
|
+
AuthzFlowType2.AUTHORIZATION_CODE_FLOW
|
|
3941
2381
|
] : []);
|
|
3942
2382
|
}
|
|
3943
2383
|
isFlowTypeSupported(flowType) {
|
|
3944
2384
|
return this.issuerSupportedFlowTypes().includes(flowType);
|
|
3945
2385
|
}
|
|
3946
|
-
hasAuthorizationURL() {
|
|
3947
|
-
return !!this.authorizationURL;
|
|
3948
|
-
}
|
|
3949
2386
|
get authorizationURL() {
|
|
3950
2387
|
return this._state.authorizationURL;
|
|
3951
2388
|
}
|
|
2389
|
+
hasAuthorizationURL() {
|
|
2390
|
+
return !!this.authorizationURL;
|
|
2391
|
+
}
|
|
3952
2392
|
get credentialOffer() {
|
|
3953
2393
|
return this._state.credentialOffer;
|
|
3954
2394
|
}
|
|
3955
2395
|
version() {
|
|
3956
|
-
return
|
|
2396
|
+
return OpenId4VCIVersion8.VER_1_0_15;
|
|
3957
2397
|
}
|
|
3958
2398
|
get endpointMetadata() {
|
|
3959
2399
|
this.assertServerMetadata();
|
|
@@ -3989,13 +2429,16 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
3989
2429
|
get dpopResponseParams() {
|
|
3990
2430
|
return this._state.dpopResponseParams;
|
|
3991
2431
|
}
|
|
2432
|
+
get state() {
|
|
2433
|
+
return this._state;
|
|
2434
|
+
}
|
|
3992
2435
|
getIssuer() {
|
|
3993
2436
|
this.assertIssuerData();
|
|
3994
2437
|
return this._state.credentialIssuer;
|
|
3995
2438
|
}
|
|
3996
2439
|
getAccessTokenEndpoint() {
|
|
3997
2440
|
this.assertIssuerData();
|
|
3998
|
-
return this.endpointMetadata
|
|
2441
|
+
return this.endpointMetadata?.token_endpoint ?? AccessTokenClient.determineTokenURL({
|
|
3999
2442
|
issuerOpts: {
|
|
4000
2443
|
issuer: this.getIssuer()
|
|
4001
2444
|
}
|
|
@@ -4003,34 +2446,30 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4003
2446
|
}
|
|
4004
2447
|
getCredentialEndpoint() {
|
|
4005
2448
|
this.assertIssuerData();
|
|
4006
|
-
return this.endpointMetadata
|
|
2449
|
+
return this.endpointMetadata?.credential_endpoint ?? `${this.getIssuer()}/credential`;
|
|
2450
|
+
}
|
|
2451
|
+
getNonceEndpoint() {
|
|
2452
|
+
return this.endpointMetadata?.credentialIssuerMetadata?.nonce_endpoint;
|
|
2453
|
+
}
|
|
2454
|
+
hasNonceEndpoint() {
|
|
2455
|
+
return !!this.getNonceEndpoint();
|
|
2456
|
+
}
|
|
2457
|
+
getAuthorizationChallengeEndpoint() {
|
|
2458
|
+
this.assertIssuerData();
|
|
2459
|
+
return this.endpointMetadata?.authorization_challenge_endpoint;
|
|
2460
|
+
}
|
|
2461
|
+
hasAuthorizationChallengeEndpoint() {
|
|
2462
|
+
return !!this.getAuthorizationChallengeEndpoint();
|
|
4007
2463
|
}
|
|
4008
2464
|
hasDeferredCredentialEndpoint() {
|
|
4009
|
-
return !!this.
|
|
2465
|
+
return !!this.endpointMetadata?.deferred_credential_endpoint;
|
|
4010
2466
|
}
|
|
4011
2467
|
getDeferredCredentialEndpoint() {
|
|
4012
2468
|
this.assertIssuerData();
|
|
4013
|
-
return this.endpointMetadata
|
|
2469
|
+
return this.endpointMetadata?.deferred_credential_endpoint;
|
|
4014
2470
|
}
|
|
4015
|
-
/**
|
|
4016
|
-
* Too bad we need a method like this, but EBSI is not exposing metadata
|
|
4017
|
-
*/
|
|
4018
2471
|
isEBSI() {
|
|
4019
|
-
|
|
4020
|
-
if (credentialOffer?.credential_configuration_ids) {
|
|
4021
|
-
const credentialConfigurations = this.endpointMetadata.credentialIssuerMetadata?.credential_configurations_supported;
|
|
4022
|
-
if (credentialConfigurations) {
|
|
4023
|
-
const isEBSITrustFramework = credentialOffer.credential_configuration_ids.map((id) => credentialConfigurations[id]).filter((config) => (
|
|
4024
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4025
|
-
// @ts-ignore
|
|
4026
|
-
config !== void 0 && "trust_framework" in config && "name" in config.trust_framework
|
|
4027
|
-
)).some((config) => config.trust_framework.name.includes("ebsi"));
|
|
4028
|
-
if (isEBSITrustFramework) {
|
|
4029
|
-
return true;
|
|
4030
|
-
}
|
|
4031
|
-
}
|
|
4032
|
-
}
|
|
4033
|
-
return this.clientId?.includes("ebsi") || this._state.kid?.includes("did:ebsi:") || this.getIssuer().includes("ebsi") || this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes("ebsi.eu") || this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes("ebsi.eu");
|
|
2472
|
+
return this.clientId?.includes("ebsi") || this._state.kid?.includes("did:ebsi:") || this.getIssuer().includes("ebsi") || this.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint?.includes("ebsi.eu") || this.endpointMetadata?.credentialIssuerMetadata?.authorization_server?.includes("ebsi.eu");
|
|
4034
2473
|
}
|
|
4035
2474
|
assertIssuerData() {
|
|
4036
2475
|
if (!this._state.credentialIssuer) {
|
|
@@ -4050,13 +2489,20 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4050
2489
|
}
|
|
4051
2490
|
}
|
|
4052
2491
|
syncAuthorizationRequestOpts(opts) {
|
|
2492
|
+
const requestObjectOpts = {
|
|
2493
|
+
...this._state?.authorizationRequestOpts?.requestObjectOpts,
|
|
2494
|
+
...opts?.requestObjectOpts
|
|
2495
|
+
};
|
|
4053
2496
|
let authorizationRequestOpts = {
|
|
4054
2497
|
...this._state?.authorizationRequestOpts,
|
|
4055
|
-
...opts
|
|
2498
|
+
...opts,
|
|
2499
|
+
...requestObjectOpts && {
|
|
2500
|
+
requestObjectOpts
|
|
2501
|
+
}
|
|
4056
2502
|
};
|
|
4057
2503
|
if (!authorizationRequestOpts) {
|
|
4058
2504
|
authorizationRequestOpts = {
|
|
4059
|
-
redirectUri: `${
|
|
2505
|
+
redirectUri: `${DefaultURISchemes.CREDENTIAL_OFFER}://`
|
|
4060
2506
|
};
|
|
4061
2507
|
}
|
|
4062
2508
|
const clientId = authorizationRequestOpts.clientId ?? this._state.clientId;
|
|
@@ -4067,7 +2513,7 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4067
2513
|
getAuthorizationCode = /* @__PURE__ */ __name((authorizationResponse, code) => {
|
|
4068
2514
|
if (authorizationResponse) {
|
|
4069
2515
|
this._state.authorizationCodeResponse = {
|
|
4070
|
-
...
|
|
2516
|
+
...toAuthorizationResponsePayload(authorizationResponse)
|
|
4071
2517
|
};
|
|
4072
2518
|
} else if (code) {
|
|
4073
2519
|
this._state.authorizationCodeResponse = {
|
|
@@ -4078,17 +2524,15 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4078
2524
|
}, "getAuthorizationCode");
|
|
4079
2525
|
};
|
|
4080
2526
|
|
|
4081
|
-
// lib/
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
var logger14 = Loggers14.DEFAULT.get("sphereon:oid4vci");
|
|
4085
|
-
var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
2527
|
+
// lib/OpenID4VCIClient.ts
|
|
2528
|
+
var logger8 = Loggers8.DEFAULT.get("sphereon:oid4vci");
|
|
2529
|
+
var OpenID4VCIClient = class _OpenID4VCIClient {
|
|
4086
2530
|
static {
|
|
4087
|
-
__name(this, "
|
|
2531
|
+
__name(this, "OpenID4VCIClient");
|
|
4088
2532
|
}
|
|
4089
2533
|
_state;
|
|
4090
|
-
constructor({ credentialOffer, clientId, kid, alg, credentialIssuer, pkce, authorizationRequest, jwk, endpointMetadata, accessTokenResponse, authorizationRequestOpts, authorizationCodeResponse, authorizationURL }) {
|
|
4091
|
-
const issuer = credentialIssuer ?? (credentialOffer ?
|
|
2534
|
+
constructor({ credentialOffer, clientId, kid, alg, credentialIssuer, pkce, authorizationRequest, accessToken, jwk, endpointMetadata, accessTokenResponse, authorizationRequestOpts, authorizationCodeResponse, authorizationURL }) {
|
|
2535
|
+
const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload6(credentialOffer.credential_offer) : void 0);
|
|
4092
2536
|
if (!issuer) {
|
|
4093
2537
|
throw Error("No credential issuer supplied or deduced from offer");
|
|
4094
2538
|
}
|
|
@@ -4098,14 +2542,15 @@ var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
|
4098
2542
|
kid,
|
|
4099
2543
|
alg,
|
|
4100
2544
|
// TODO: We need to refactor this and always explicitly call createAuthorizationRequestUrl, so we can have a credential selection first and use the kid as a default for the client id
|
|
4101
|
-
clientId: clientId ?? (credentialOffer &&
|
|
2545
|
+
clientId: clientId ?? (credentialOffer && getClientIdFromCredentialOfferPayload3(credentialOffer.credential_offer)) ?? kid?.split("#")[0],
|
|
4102
2546
|
pkce: {
|
|
4103
2547
|
disabled: false,
|
|
4104
|
-
codeChallengeMethod:
|
|
2548
|
+
codeChallengeMethod: CodeChallengeMethod4.S256,
|
|
4105
2549
|
...pkce
|
|
4106
2550
|
},
|
|
4107
2551
|
authorizationRequestOpts,
|
|
4108
2552
|
authorizationCodeResponse,
|
|
2553
|
+
accessToken,
|
|
4109
2554
|
jwk,
|
|
4110
2555
|
endpointMetadata,
|
|
4111
2556
|
accessTokenResponse,
|
|
@@ -4114,16 +2559,17 @@ var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
|
4114
2559
|
if (!this._state.authorizationRequestOpts) {
|
|
4115
2560
|
this._state.authorizationRequestOpts = this.syncAuthorizationRequestOpts(authorizationRequest);
|
|
4116
2561
|
}
|
|
4117
|
-
|
|
2562
|
+
logger8.debug(`Authorization req options: ${JSON.stringify(this._state.authorizationRequestOpts, null, 2)}`);
|
|
4118
2563
|
}
|
|
4119
|
-
static async fromCredentialIssuer({ kid, alg, retrieveServerMetadata, clientId, credentialIssuer, pkce, authorizationRequest, createAuthorizationRequestURL }) {
|
|
4120
|
-
const client = new
|
|
2564
|
+
static async fromCredentialIssuer({ kid, alg, retrieveServerMetadata, clientId, credentialIssuer, pkce, authorizationRequest, createAuthorizationRequestURL, endpointMetadata }) {
|
|
2565
|
+
const client = new _OpenID4VCIClient({
|
|
4121
2566
|
kid,
|
|
4122
2567
|
alg,
|
|
4123
2568
|
clientId: clientId ?? authorizationRequest?.clientId,
|
|
4124
2569
|
credentialIssuer,
|
|
4125
2570
|
pkce,
|
|
4126
|
-
authorizationRequest
|
|
2571
|
+
authorizationRequest,
|
|
2572
|
+
endpointMetadata
|
|
4127
2573
|
});
|
|
4128
2574
|
if (retrieveServerMetadata === void 0 || retrieveServerMetadata) {
|
|
4129
2575
|
await client.retrieveServerMetadata();
|
|
@@ -4138,29 +2584,30 @@ var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
|
4138
2584
|
}
|
|
4139
2585
|
static async fromState({ state }) {
|
|
4140
2586
|
const clientState = typeof state === "string" ? JSON.parse(state) : state;
|
|
4141
|
-
return new
|
|
2587
|
+
return new _OpenID4VCIClient(clientState);
|
|
4142
2588
|
}
|
|
4143
|
-
static async fromURI({ uri, kid, alg, retrieveServerMetadata, clientId, pkce, createAuthorizationRequestURL, authorizationRequest, resolveOfferUri }) {
|
|
4144
|
-
const credentialOfferClient = await
|
|
2589
|
+
static async fromURI({ uri, kid, alg, retrieveServerMetadata, clientId, pkce, createAuthorizationRequestURL, authorizationRequest, resolveOfferUri, endpointMetadata }) {
|
|
2590
|
+
const credentialOfferClient = await CredentialOfferClient.fromURI(uri, {
|
|
4145
2591
|
resolve: resolveOfferUri
|
|
4146
2592
|
});
|
|
4147
|
-
const client = new
|
|
2593
|
+
const client = new _OpenID4VCIClient({
|
|
4148
2594
|
credentialOffer: credentialOfferClient,
|
|
4149
2595
|
kid,
|
|
4150
2596
|
alg,
|
|
4151
2597
|
clientId: clientId ?? authorizationRequest?.clientId ?? credentialOfferClient.clientId,
|
|
4152
2598
|
pkce,
|
|
4153
|
-
authorizationRequest
|
|
2599
|
+
authorizationRequest,
|
|
2600
|
+
endpointMetadata
|
|
4154
2601
|
});
|
|
4155
2602
|
if (retrieveServerMetadata === void 0 || retrieveServerMetadata) {
|
|
4156
2603
|
await client.retrieveServerMetadata();
|
|
4157
2604
|
}
|
|
4158
|
-
if (credentialOfferClient.supportedFlows.includes(
|
|
2605
|
+
if (credentialOfferClient.supportedFlows.includes(AuthzFlowType3.AUTHORIZATION_CODE_FLOW) && (createAuthorizationRequestURL === void 0 || createAuthorizationRequestURL)) {
|
|
4159
2606
|
await client.createAuthorizationRequestUrl({
|
|
4160
2607
|
authorizationRequest,
|
|
4161
2608
|
pkce
|
|
4162
2609
|
});
|
|
4163
|
-
|
|
2610
|
+
logger8.debug(`Authorization Request URL: ${client._state.authorizationURL}`);
|
|
4164
2611
|
}
|
|
4165
2612
|
return client;
|
|
4166
2613
|
}
|
|
@@ -4180,12 +2627,12 @@ var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
|
4180
2627
|
if (this._state.endpointMetadata?.credentialIssuerMetadata && "authorization_endpoint" in this._state.endpointMetadata.credentialIssuerMetadata) {
|
|
4181
2628
|
this._state.endpointMetadata.authorization_endpoint = this._state.endpointMetadata.credentialIssuerMetadata.authorization_endpoint;
|
|
4182
2629
|
}
|
|
4183
|
-
this._state.authorizationURL = await
|
|
2630
|
+
this._state.authorizationURL = await createAuthorizationRequestUrl({
|
|
4184
2631
|
pkce: this._state.pkce,
|
|
4185
2632
|
endpointMetadata: this.endpointMetadata,
|
|
4186
2633
|
authorizationRequest: this._state.authorizationRequestOpts,
|
|
4187
2634
|
credentialOffer: this.credentialOffer,
|
|
4188
|
-
|
|
2635
|
+
credentialConfigurationSupported: this.getCredentialsSupported()
|
|
4189
2636
|
});
|
|
4190
2637
|
}
|
|
4191
2638
|
return this._state.authorizationURL;
|
|
@@ -4194,9 +2641,9 @@ var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
|
4194
2641
|
this.assertIssuerData();
|
|
4195
2642
|
if (!this._state.endpointMetadata) {
|
|
4196
2643
|
if (this.credentialOffer) {
|
|
4197
|
-
this._state.endpointMetadata = await
|
|
2644
|
+
this._state.endpointMetadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(this.credentialOffer);
|
|
4198
2645
|
} else if (this._state.credentialIssuer) {
|
|
4199
|
-
this._state.endpointMetadata = await
|
|
2646
|
+
this._state.endpointMetadata = await MetadataClient.retrieveAllMetadata(this._state.credentialIssuer);
|
|
4200
2647
|
} else {
|
|
4201
2648
|
throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`);
|
|
4202
2649
|
}
|
|
@@ -4217,12 +2664,12 @@ var OpenID4VCIClientV1_0_11 = class _OpenID4VCIClientV1_0_11 {
|
|
|
4217
2664
|
...opts
|
|
4218
2665
|
});
|
|
4219
2666
|
if (response.errorBody) {
|
|
4220
|
-
|
|
2667
|
+
logger8.debug(`Authorization code error:\r
|
|
4221
2668
|
${JSON.stringify(response.errorBody)}`);
|
|
4222
2669
|
const error = response.errorBody;
|
|
4223
2670
|
return Promise.reject(error);
|
|
4224
2671
|
} else if (!response.successBody) {
|
|
4225
|
-
|
|
2672
|
+
logger8.debug(`Authorization code error. No success body`);
|
|
4226
2673
|
return Promise.reject(Error(`Retrieving an authorization code token from ${this._state.endpointMetadata?.authorization_challenge_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`));
|
|
4227
2674
|
}
|
|
4228
2675
|
return {
|
|
@@ -4240,6 +2687,24 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4240
2687
|
const asOpts = {
|
|
4241
2688
|
...opts?.asOpts
|
|
4242
2689
|
};
|
|
2690
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
2691
|
+
const clientAssertionType = asOpts.clientOpts?.clientAssertionType ?? (kid && clientId && typeof asOpts.clientOpts?.signCallbacks?.signCallback === "function" ? "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" : void 0);
|
|
2692
|
+
if (this.isEBSI() || clientId && kid) {
|
|
2693
|
+
if (!clientId) {
|
|
2694
|
+
throw Error(`Client id expected for EBSI`);
|
|
2695
|
+
}
|
|
2696
|
+
asOpts.clientOpts = {
|
|
2697
|
+
...asOpts.clientOpts,
|
|
2698
|
+
clientId,
|
|
2699
|
+
...kid && {
|
|
2700
|
+
kid
|
|
2701
|
+
},
|
|
2702
|
+
...clientAssertionType && {
|
|
2703
|
+
clientAssertionType
|
|
2704
|
+
},
|
|
2705
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
4243
2708
|
if (clientId) {
|
|
4244
2709
|
this._state.clientId = clientId;
|
|
4245
2710
|
if (!asOpts.clientOpts) {
|
|
@@ -4250,31 +2715,13 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4250
2715
|
asOpts.clientOpts.clientId = clientId;
|
|
4251
2716
|
}
|
|
4252
2717
|
if (!this._state.accessTokenResponse) {
|
|
4253
|
-
const accessTokenClient = new
|
|
2718
|
+
const accessTokenClient = new AccessTokenClient();
|
|
4254
2719
|
if (redirectUri && redirectUri !== this._state.authorizationRequestOpts?.redirectUri) {
|
|
4255
2720
|
console.log(`Redirect URI mismatch between access-token (${redirectUri}) and authorization request (${this._state.authorizationRequestOpts?.redirectUri}). According to the specification that is not allowed.`);
|
|
4256
2721
|
}
|
|
4257
2722
|
if (this._state.authorizationRequestOpts?.redirectUri && !redirectUri) {
|
|
4258
2723
|
redirectUri = this._state.authorizationRequestOpts.redirectUri;
|
|
4259
2724
|
}
|
|
4260
|
-
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
4261
|
-
const clientAssertionType = asOpts.clientOpts?.clientAssertionType ?? (kid && clientId && typeof asOpts.clientOpts?.signCallbacks?.signCallback === "function" ? "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" : void 0);
|
|
4262
|
-
if (this.isEBSI() || clientId && kid) {
|
|
4263
|
-
if (!clientId) {
|
|
4264
|
-
throw Error(`Client id expected for EBSI`);
|
|
4265
|
-
}
|
|
4266
|
-
asOpts.clientOpts = {
|
|
4267
|
-
...asOpts.clientOpts,
|
|
4268
|
-
clientId,
|
|
4269
|
-
...kid && {
|
|
4270
|
-
kid
|
|
4271
|
-
},
|
|
4272
|
-
...clientAssertionType && {
|
|
4273
|
-
clientAssertionType
|
|
4274
|
-
},
|
|
4275
|
-
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks
|
|
4276
|
-
};
|
|
4277
|
-
}
|
|
4278
2725
|
const response = await accessTokenClient.acquireAccessToken({
|
|
4279
2726
|
credentialOffer: this.credentialOffer,
|
|
4280
2727
|
metadata: this.endpointMetadata,
|
|
@@ -4294,16 +2741,19 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4294
2741
|
}
|
|
4295
2742
|
});
|
|
4296
2743
|
if (response.errorBody) {
|
|
4297
|
-
|
|
2744
|
+
logger8.debug(`Access token error:\r
|
|
4298
2745
|
${JSON.stringify(response.errorBody)}`);
|
|
4299
2746
|
throw Error(`Retrieving an access token from ${this._state.endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed with status: ${response.origResponse.status}`);
|
|
4300
2747
|
} else if (!response.successBody) {
|
|
4301
|
-
|
|
2748
|
+
logger8.debug(`Access token error. No success body`);
|
|
4302
2749
|
throw Error(`Retrieving an access token from ${this._state.endpointMetadata?.token_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`);
|
|
4303
2750
|
}
|
|
4304
2751
|
this._state.accessTokenResponse = response.successBody;
|
|
4305
2752
|
this._state.dpopResponseParams = response.params;
|
|
4306
2753
|
this._state.accessToken = response.successBody.access_token;
|
|
2754
|
+
if (response.successBody.c_nonce) {
|
|
2755
|
+
this._state.cachedCNonce = response.successBody.c_nonce;
|
|
2756
|
+
}
|
|
4307
2757
|
}
|
|
4308
2758
|
return {
|
|
4309
2759
|
...this.accessTokenResponse,
|
|
@@ -4317,22 +2767,34 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4317
2767
|
jwk,
|
|
4318
2768
|
kid
|
|
4319
2769
|
].filter((v) => v !== void 0).length > 1) {
|
|
4320
|
-
throw new Error(
|
|
2770
|
+
throw new Error(KID_JWK_X5C_ERROR2 + `. jwk: ${jwk !== void 0}, kid: ${kid !== void 0}`);
|
|
4321
2771
|
}
|
|
4322
2772
|
if (alg) this._state.alg = alg;
|
|
4323
2773
|
if (jwk) this._state.jwk = jwk;
|
|
4324
2774
|
if (kid) this._state.kid = kid;
|
|
4325
|
-
|
|
2775
|
+
if (this.version() === OpenId4VCIVersion9.VER_1_0_15 && this.hasNonceEndpoint()) {
|
|
2776
|
+
if (!this._state.cachedCNonce) {
|
|
2777
|
+
try {
|
|
2778
|
+
await this.acquireNonceViaV15Delegate();
|
|
2779
|
+
} catch (e) {
|
|
2780
|
+
return Promise.reject(Error(`failed to acquire nonce: ${String(e)}`));
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
let requestBuilder = this.credentialOffer ? CredentialRequestClientBuilderV1_0_15.fromCredentialOffer({
|
|
4326
2785
|
credentialOffer: this.credentialOffer,
|
|
4327
2786
|
metadata: this.endpointMetadata
|
|
4328
|
-
}) :
|
|
2787
|
+
}) : CredentialRequestClientBuilderV1_0_15.fromCredentialIssuer({
|
|
4329
2788
|
credentialIssuer: this.getIssuer(),
|
|
4330
2789
|
credentialTypes,
|
|
4331
2790
|
metadata: this.endpointMetadata,
|
|
4332
2791
|
version: this.version()
|
|
4333
2792
|
});
|
|
2793
|
+
const issuerState = this.issuerSupportedFlowTypes().includes(AuthzFlowType3.AUTHORIZATION_CODE_FLOW) && this._state.authorizationCodeResponse && !this.accessTokenResponse?.c_nonce && this._state.credentialOffer?.issuerState ? this._state.credentialOffer.issuerState : void 0;
|
|
2794
|
+
requestBuilder.withIssuerState(issuerState);
|
|
4334
2795
|
requestBuilder.withTokenFromResponse(this.accessTokenResponse);
|
|
4335
2796
|
requestBuilder.withDeferredCredentialAwait(deferredCredentialAwait ?? false, deferredCredentialIntervalInMS);
|
|
2797
|
+
let subjectIssuance;
|
|
4336
2798
|
if (this.endpointMetadata?.credentialIssuerMetadata) {
|
|
4337
2799
|
const metadata = this.endpointMetadata.credentialIssuerMetadata;
|
|
4338
2800
|
const types = Array.isArray(credentialTypes) ? credentialTypes : [
|
|
@@ -4341,9 +2803,14 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4341
2803
|
if (metadata.credentials_supported && Array.isArray(metadata.credentials_supported)) {
|
|
4342
2804
|
let typeSupported = false;
|
|
4343
2805
|
metadata.credentials_supported.forEach((supportedCredential) => {
|
|
4344
|
-
const subTypes =
|
|
2806
|
+
const subTypes = getTypesFromCredentialSupported(supportedCredential);
|
|
4345
2807
|
if (subTypes.every((t, i) => types[i] === t) || types.length === 1 && (types[0] === supportedCredential.id || subTypes.includes(types[0]))) {
|
|
4346
2808
|
typeSupported = true;
|
|
2809
|
+
if (supportedCredential.credential_subject_issuance) {
|
|
2810
|
+
subjectIssuance = {
|
|
2811
|
+
credential_subject_issuance: supportedCredential.credential_subject_issuance
|
|
2812
|
+
};
|
|
2813
|
+
}
|
|
4347
2814
|
}
|
|
4348
2815
|
});
|
|
4349
2816
|
if (!typeSupported) {
|
|
@@ -4356,89 +2823,124 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4356
2823
|
}
|
|
4357
2824
|
}
|
|
4358
2825
|
}
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
accessTokenResponse: this.accessTokenResponse,
|
|
4362
|
-
callbacks: proofCallbacks,
|
|
4363
|
-
version: this.version()
|
|
4364
|
-
}).withIssuer(this.getIssuer()).withAlg(this.alg);
|
|
4365
|
-
if (this._state.jwk) {
|
|
4366
|
-
proofBuilder.withJWK(this._state.jwk);
|
|
4367
|
-
}
|
|
4368
|
-
if (this._state.kid) {
|
|
4369
|
-
proofBuilder.withKid(this._state.kid);
|
|
4370
|
-
}
|
|
4371
|
-
if (this.clientId) {
|
|
4372
|
-
proofBuilder.withClientId(this.clientId);
|
|
4373
|
-
}
|
|
4374
|
-
if (jti) {
|
|
4375
|
-
proofBuilder.withJti(jti);
|
|
2826
|
+
if (subjectIssuance) {
|
|
2827
|
+
requestBuilder.withSubjectIssuance(subjectIssuance);
|
|
4376
2828
|
}
|
|
4377
|
-
const
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
2829
|
+
const credentialRequestClient = requestBuilder.build();
|
|
2830
|
+
try {
|
|
2831
|
+
const proofBuilder = ProofOfPossessionBuilder.fromAccessTokenResponse({
|
|
2832
|
+
accessTokenResponse: this.accessTokenResponse,
|
|
2833
|
+
callbacks: proofCallbacks,
|
|
2834
|
+
version: this.version()
|
|
2835
|
+
}).withIssuer(this.getIssuer()).withAlg(this.alg);
|
|
2836
|
+
if (this._state.jwk) {
|
|
2837
|
+
proofBuilder.withJWK(this._state.jwk);
|
|
2838
|
+
}
|
|
2839
|
+
if (this._state.kid) {
|
|
2840
|
+
proofBuilder.withKid(this._state.kid);
|
|
2841
|
+
}
|
|
2842
|
+
if (this.clientId && (!this.credentialOffer || this.credentialOffer.supportedFlows.includes(AuthzFlowType3.AUTHORIZATION_CODE_FLOW) && !this.credentialOffer.preAuthorizedCode)) {
|
|
2843
|
+
proofBuilder.withClientId(this.clientId);
|
|
2844
|
+
}
|
|
2845
|
+
if (jti) {
|
|
2846
|
+
proofBuilder.withJti(jti);
|
|
2847
|
+
}
|
|
2848
|
+
if ("cachedCNonce" in this._state && this._state.cachedCNonce) {
|
|
2849
|
+
proofBuilder.withAccessTokenNonce(this._state.cachedCNonce);
|
|
2850
|
+
}
|
|
2851
|
+
const response = await credentialRequestClient.acquireCredentialsUsingProof({
|
|
2852
|
+
proofInput: proofBuilder,
|
|
2853
|
+
credentialTypes,
|
|
2854
|
+
context,
|
|
2855
|
+
format,
|
|
2856
|
+
subjectIssuance,
|
|
2857
|
+
createDPoPOpts
|
|
2858
|
+
});
|
|
2859
|
+
this._state.dpopResponseParams = response.params;
|
|
2860
|
+
if (response.errorBody) {
|
|
2861
|
+
logger8.debug(`Credential request error:\r
|
|
4387
2862
|
${JSON.stringify(response.errorBody)}`);
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
}
|
|
4393
|
-
return {
|
|
4394
|
-
...response.successBody,
|
|
4395
|
-
...this.dpopResponseParams && {
|
|
4396
|
-
params: this.dpopResponseParams
|
|
2863
|
+
throw Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed with status: ${response.origResponse.status}`);
|
|
2864
|
+
} else if (!response.successBody) {
|
|
2865
|
+
logger8.debug(`Credential request error. No success body`);
|
|
2866
|
+
throw Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed as there was no success response body`);
|
|
4397
2867
|
}
|
|
4398
|
-
|
|
2868
|
+
return {
|
|
2869
|
+
...response.successBody,
|
|
2870
|
+
...this.dpopResponseParams && {
|
|
2871
|
+
params: this.dpopResponseParams
|
|
2872
|
+
},
|
|
2873
|
+
access_token: response.access_token
|
|
2874
|
+
};
|
|
2875
|
+
} catch (e) {
|
|
2876
|
+
if (!this.shouldRetryWithFreshNonce(e)) {
|
|
2877
|
+
return Promise.reject(e instanceof Error ? e : Error(String(e)));
|
|
2878
|
+
}
|
|
2879
|
+
this._state.cachedCNonce = void 0;
|
|
2880
|
+
try {
|
|
2881
|
+
await this.acquireNonceViaV15Delegate();
|
|
2882
|
+
} catch (e2) {
|
|
2883
|
+
return Promise.reject(Error(`retry nonce fetch failed: ${String(e2)}`));
|
|
2884
|
+
}
|
|
2885
|
+
const proofBuilder2 = ProofOfPossessionBuilder.fromAccessTokenResponse({
|
|
2886
|
+
accessTokenResponse: this.accessTokenResponse,
|
|
2887
|
+
callbacks: proofCallbacks,
|
|
2888
|
+
version: this.version()
|
|
2889
|
+
}).withIssuer(this.getIssuer()).withAlg(this.alg);
|
|
2890
|
+
if (this._state.jwk) {
|
|
2891
|
+
proofBuilder2.withJWK(this._state.jwk);
|
|
2892
|
+
}
|
|
2893
|
+
if (this._state.kid) {
|
|
2894
|
+
proofBuilder2.withKid(this._state.kid);
|
|
2895
|
+
}
|
|
2896
|
+
if (this.clientId) {
|
|
2897
|
+
proofBuilder2.withClientId(this.clientId);
|
|
2898
|
+
}
|
|
2899
|
+
if (jti) {
|
|
2900
|
+
proofBuilder2.withJti(jti);
|
|
2901
|
+
}
|
|
2902
|
+
const response2 = await credentialRequestClient.acquireCredentialsUsingProof({
|
|
2903
|
+
proofInput: proofBuilder2,
|
|
2904
|
+
credentialTypes,
|
|
2905
|
+
context,
|
|
2906
|
+
format,
|
|
2907
|
+
subjectIssuance,
|
|
2908
|
+
createDPoPOpts
|
|
2909
|
+
});
|
|
2910
|
+
this._state.dpopResponseParams = response2.params;
|
|
2911
|
+
if (response2.errorBody) {
|
|
2912
|
+
logger8.debug(`Credential request error (after retry):\r
|
|
2913
|
+
${JSON.stringify(response2.errorBody)}`);
|
|
2914
|
+
return Promise.reject(Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed after retry with status: ${response2.origResponse.status}`));
|
|
2915
|
+
} else if (!response2.successBody) {
|
|
2916
|
+
logger8.debug(`Credential request error after retry. No success body`);
|
|
2917
|
+
return Promise.reject(Error(`Retrieving a credential from ${this._state.endpointMetadata?.credential_endpoint} for issuer ${this.getIssuer()} failed after retry as there was no success response body`));
|
|
2918
|
+
}
|
|
2919
|
+
return {
|
|
2920
|
+
...response2.successBody,
|
|
2921
|
+
...this.dpopResponseParams && {
|
|
2922
|
+
params: this.dpopResponseParams
|
|
2923
|
+
},
|
|
2924
|
+
access_token: response2.access_token
|
|
2925
|
+
};
|
|
2926
|
+
}
|
|
4399
2927
|
}
|
|
4400
2928
|
async exportState() {
|
|
4401
2929
|
return JSON.stringify(this._state);
|
|
4402
2930
|
}
|
|
4403
|
-
// FIXME: We really should convert <v11 to v12 objects first. Right now the logic doesn't map nicely and is brittle.
|
|
4404
|
-
// We should resolve IDs to objects first in case of strings.
|
|
4405
|
-
// When < v11 convert into a v12 object. When v12 object retain it.
|
|
4406
|
-
// Then match the object array on server metadata
|
|
4407
|
-
getCredentialsSupportedV11(restrictToInitiationTypes, format) {
|
|
4408
|
-
return getSupportedCredentials3({
|
|
4409
|
-
issuerMetadata: this.endpointMetadata.credentialIssuerMetadata,
|
|
4410
|
-
version: this.version(),
|
|
4411
|
-
format,
|
|
4412
|
-
types: restrictToInitiationTypes ? this.getCredentialOfferTypes() : void 0
|
|
4413
|
-
});
|
|
4414
|
-
}
|
|
4415
2931
|
getCredentialsSupported(format) {
|
|
4416
|
-
return
|
|
2932
|
+
return getSupportedCredentials2({
|
|
4417
2933
|
issuerMetadata: this.endpointMetadata.credentialIssuerMetadata,
|
|
4418
2934
|
version: this.version(),
|
|
4419
|
-
format
|
|
4420
|
-
types: void 0
|
|
2935
|
+
format
|
|
4421
2936
|
});
|
|
4422
2937
|
}
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
return [];
|
|
4426
|
-
} else if (this.credentialOffer.version < OpenId4VCIVersion16.VER_1_0_11) {
|
|
4427
|
-
const orig = this.credentialOffer.original_credential_offer;
|
|
4428
|
-
const types = typeof orig.credential_type === "string" ? [
|
|
4429
|
-
orig.credential_type
|
|
4430
|
-
] : orig.credential_type;
|
|
4431
|
-
const result = [];
|
|
4432
|
-
result[0] = types;
|
|
4433
|
-
return result;
|
|
4434
|
-
} else if (this.credentialOffer.version < OpenId4VCIVersion16.VER_1_0_13) {
|
|
4435
|
-
return this.credentialOffer.credential_offer.credentials.map((c) => getTypesFromObject2(c) ?? []);
|
|
4436
|
-
}
|
|
4437
|
-
throw Error(`This class only supports version 11 and lower! Version: ${this.version()}`);
|
|
2938
|
+
async sendNotification(credentialRequestOpts, request, accessToken) {
|
|
2939
|
+
return sendNotification(credentialRequestOpts, request, accessToken ?? this._state.accessToken ?? this._state.accessTokenResponse?.access_token);
|
|
4438
2940
|
}
|
|
4439
2941
|
issuerSupportedFlowTypes() {
|
|
4440
|
-
return this.credentialOffer?.supportedFlows ?? (this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ? [
|
|
4441
|
-
|
|
2942
|
+
return this.credentialOffer?.supportedFlows ?? (this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server ? [
|
|
2943
|
+
AuthzFlowType3.AUTHORIZATION_CODE_FLOW
|
|
4442
2944
|
] : []);
|
|
4443
2945
|
}
|
|
4444
2946
|
isFlowTypeSupported(flowType) {
|
|
@@ -4454,7 +2956,17 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4454
2956
|
return this._state.credentialOffer;
|
|
4455
2957
|
}
|
|
4456
2958
|
version() {
|
|
4457
|
-
|
|
2959
|
+
if (this.credentialOffer?.version && this.credentialOffer.version !== OpenId4VCIVersion9.VER_UNKNOWN) {
|
|
2960
|
+
return this.credentialOffer.version;
|
|
2961
|
+
}
|
|
2962
|
+
const metadata = this._state.endpointMetadata;
|
|
2963
|
+
if (metadata?.credentialIssuerMetadata) {
|
|
2964
|
+
const versions = determineVersionsFromIssuerMetadata(metadata.credentialIssuerMetadata);
|
|
2965
|
+
if (versions.length > 0 && !versions.includes(OpenId4VCIVersion9.VER_UNKNOWN)) {
|
|
2966
|
+
return versions[0];
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
return OpenId4VCIVersion9.VER_1_0_15;
|
|
4458
2970
|
}
|
|
4459
2971
|
get endpointMetadata() {
|
|
4460
2972
|
this.assertServerMetadata();
|
|
@@ -4496,7 +3008,10 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4496
3008
|
}
|
|
4497
3009
|
getAccessTokenEndpoint() {
|
|
4498
3010
|
this.assertIssuerData();
|
|
4499
|
-
|
|
3011
|
+
if (this.endpointMetadata) {
|
|
3012
|
+
return this.endpointMetadata.token_endpoint;
|
|
3013
|
+
}
|
|
3014
|
+
return AccessTokenClient.determineTokenURL({
|
|
4500
3015
|
issuerOpts: {
|
|
4501
3016
|
issuer: this.getIssuer()
|
|
4502
3017
|
}
|
|
@@ -4506,6 +3021,13 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4506
3021
|
this.assertIssuerData();
|
|
4507
3022
|
return this.endpointMetadata ? this.endpointMetadata.credential_endpoint : `${this.getIssuer()}/credential`;
|
|
4508
3023
|
}
|
|
3024
|
+
getAuthorizationChallengeEndpoint() {
|
|
3025
|
+
this.assertIssuerData();
|
|
3026
|
+
return this.endpointMetadata?.authorization_challenge_endpoint;
|
|
3027
|
+
}
|
|
3028
|
+
hasAuthorizationChallengeEndpoint() {
|
|
3029
|
+
return !!this.getAuthorizationChallengeEndpoint();
|
|
3030
|
+
}
|
|
4509
3031
|
hasDeferredCredentialEndpoint() {
|
|
4510
3032
|
return !!this.getAccessTokenEndpoint();
|
|
4511
3033
|
}
|
|
@@ -4517,13 +3039,6 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4517
3039
|
* Too bad we need a method like this, but EBSI is not exposing metadata
|
|
4518
3040
|
*/
|
|
4519
3041
|
isEBSI() {
|
|
4520
|
-
if (this.credentialOffer && this.credentialOffer?.credential_offer?.credentials?.find((cred) => (
|
|
4521
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4522
|
-
// @ts-ignore
|
|
4523
|
-
typeof cred !== "string" && "trust_framework" in cred && "name" in cred.trust_framework && cred.trust_framework.name.includes("ebsi")
|
|
4524
|
-
))) {
|
|
4525
|
-
return true;
|
|
4526
|
-
}
|
|
4527
3042
|
return this.clientId?.includes("ebsi") || this._state.kid?.includes("did:ebsi:") || this.getIssuer().includes("ebsi") || this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes("ebsi.eu") || this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes("ebsi.eu");
|
|
4528
3043
|
}
|
|
4529
3044
|
assertIssuerData() {
|
|
@@ -4544,13 +3059,20 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4544
3059
|
}
|
|
4545
3060
|
}
|
|
4546
3061
|
syncAuthorizationRequestOpts(opts) {
|
|
3062
|
+
const requestObjectOpts = {
|
|
3063
|
+
...this._state?.authorizationRequestOpts?.requestObjectOpts,
|
|
3064
|
+
...opts?.requestObjectOpts
|
|
3065
|
+
};
|
|
4547
3066
|
let authorizationRequestOpts = {
|
|
4548
3067
|
...this._state?.authorizationRequestOpts,
|
|
4549
|
-
...opts
|
|
3068
|
+
...opts,
|
|
3069
|
+
...requestObjectOpts && {
|
|
3070
|
+
requestObjectOpts
|
|
3071
|
+
}
|
|
4550
3072
|
};
|
|
4551
3073
|
if (!authorizationRequestOpts) {
|
|
4552
3074
|
authorizationRequestOpts = {
|
|
4553
|
-
redirectUri: `${
|
|
3075
|
+
redirectUri: `${DefaultURISchemes2.CREDENTIAL_OFFER}://`
|
|
4554
3076
|
};
|
|
4555
3077
|
}
|
|
4556
3078
|
const clientId = authorizationRequestOpts.clientId ?? this._state.clientId;
|
|
@@ -4561,7 +3083,7 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4561
3083
|
getAuthorizationCode = /* @__PURE__ */ __name((authorizationResponse, code) => {
|
|
4562
3084
|
if (authorizationResponse) {
|
|
4563
3085
|
this._state.authorizationCodeResponse = {
|
|
4564
|
-
...
|
|
3086
|
+
...toAuthorizationResponsePayload2(authorizationResponse)
|
|
4565
3087
|
};
|
|
4566
3088
|
} else if (code) {
|
|
4567
3089
|
this._state.authorizationCodeResponse = {
|
|
@@ -4570,28 +3092,68 @@ ${JSON.stringify(response.errorBody)}`);
|
|
|
4570
3092
|
}
|
|
4571
3093
|
return this._state.authorizationCodeResponse?.code ?? this._state.authorizationCodeResponse?.authorization_code;
|
|
4572
3094
|
}, "getAuthorizationCode");
|
|
3095
|
+
hasNonceEndpoint() {
|
|
3096
|
+
const endpoint = this._state.endpointMetadata?.credentialIssuerMetadata?.nonce_endpoint;
|
|
3097
|
+
return typeof endpoint === "string" && endpoint.length > 0;
|
|
3098
|
+
}
|
|
3099
|
+
async acquireNonceViaV15Delegate() {
|
|
3100
|
+
const state = this._state;
|
|
3101
|
+
let v15Client;
|
|
3102
|
+
try {
|
|
3103
|
+
v15Client = await OpenID4VCIClientV1_0_15.fromState({
|
|
3104
|
+
state
|
|
3105
|
+
});
|
|
3106
|
+
} catch (e) {
|
|
3107
|
+
return Promise.reject(Error(`failed to init v15 delegate for nonce: ${String(e)}`));
|
|
3108
|
+
}
|
|
3109
|
+
try {
|
|
3110
|
+
await v15Client.acquireNonce();
|
|
3111
|
+
} catch (e) {
|
|
3112
|
+
return Promise.reject(Error(`nonce request failed: ${String(e)}`));
|
|
3113
|
+
}
|
|
3114
|
+
state.cachedCNonce = v15Client.state.cachedCNonce;
|
|
3115
|
+
}
|
|
3116
|
+
shouldRetryWithFreshNonce(err) {
|
|
3117
|
+
if (!this.hasNonceEndpoint() && this.version() !== OpenId4VCIVersion9.VER_1_0_15) {
|
|
3118
|
+
return false;
|
|
3119
|
+
}
|
|
3120
|
+
const status = err?.response?.status ?? err?.status;
|
|
3121
|
+
const body = err?.response?.data ?? err?.data ?? void 0;
|
|
3122
|
+
const error = typeof body?.error === "string" ? body.error : void 0;
|
|
3123
|
+
const desc = typeof body?.error_description === "string" ? body.error_description : void 0;
|
|
3124
|
+
const text = [
|
|
3125
|
+
error,
|
|
3126
|
+
desc
|
|
3127
|
+
].filter(Boolean).join(" ").toLowerCase();
|
|
3128
|
+
if (status === 400 || status === 401 || status === 403) {
|
|
3129
|
+
if (text.includes("nonce") || text.includes("c_nonce")) {
|
|
3130
|
+
return true;
|
|
3131
|
+
}
|
|
3132
|
+
if (text.includes("proof") && (text.includes("invalid") || text.includes("expired"))) {
|
|
3133
|
+
return true;
|
|
3134
|
+
}
|
|
3135
|
+
if (error === "invalid_proof" || error === "invalid_request") {
|
|
3136
|
+
return true;
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
return false;
|
|
3140
|
+
}
|
|
4573
3141
|
};
|
|
4574
3142
|
|
|
4575
3143
|
// lib/index.ts
|
|
4576
3144
|
var LOG2 = VCI_LOGGERS2.get("sphereon:oid4vci:client");
|
|
4577
3145
|
export {
|
|
4578
3146
|
AccessTokenClient,
|
|
4579
|
-
AccessTokenClientV1_0_11,
|
|
4580
3147
|
CredentialOfferClient,
|
|
4581
|
-
|
|
4582
|
-
CredentialOfferClientV1_0_13,
|
|
3148
|
+
CredentialOfferClientV1_0_15,
|
|
4583
3149
|
CredentialRequestClient,
|
|
4584
3150
|
CredentialRequestClientBuilder,
|
|
4585
|
-
|
|
4586
|
-
CredentialRequestClientBuilderV1_0_13,
|
|
4587
|
-
CredentialRequestClientV1_0_11,
|
|
3151
|
+
CredentialRequestClientBuilderV1_0_15,
|
|
4588
3152
|
LOG2 as LOG,
|
|
4589
3153
|
MetadataClient,
|
|
4590
|
-
|
|
4591
|
-
MetadataClientV1_0_13,
|
|
3154
|
+
MetadataClientV1_0_15,
|
|
4592
3155
|
OpenID4VCIClient,
|
|
4593
|
-
|
|
4594
|
-
OpenID4VCIClientV1_0_13,
|
|
3156
|
+
OpenID4VCIClientV1_0_15,
|
|
4595
3157
|
ProofOfPossessionBuilder,
|
|
4596
3158
|
acquireAuthorizationChallengeAuthCode,
|
|
4597
3159
|
acquireAuthorizationChallengeAuthCodeUsingRequest,
|
|
@@ -4599,7 +3161,6 @@ export {
|
|
|
4599
3161
|
constructBaseResponse,
|
|
4600
3162
|
createAuthorizationChallengeRequest,
|
|
4601
3163
|
createAuthorizationRequestUrl,
|
|
4602
|
-
createAuthorizationRequestUrlV1_0_11,
|
|
4603
3164
|
createJwtBearerClientAssertion,
|
|
4604
3165
|
createSignedAuthRequestWhenNeeded,
|
|
4605
3166
|
generateMissingPKCEOpts,
|