@sphereon/oid4vci-client 0.10.3 → 0.10.4-next.119
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/README.md +24 -5
- package/dist/AccessTokenClient.d.ts +5 -5
- package/dist/AccessTokenClient.d.ts.map +1 -1
- package/dist/AccessTokenClient.js +51 -37
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AccessTokenClientV1_0_11.d.ts +29 -0
- package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -0
- package/dist/AccessTokenClientV1_0_11.js +209 -0
- package/dist/AccessTokenClientV1_0_11.js.map +1 -0
- package/dist/AuthorizationCodeClient.d.ts +9 -4
- package/dist/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/AuthorizationCodeClient.js +102 -18
- package/dist/AuthorizationCodeClient.js.map +1 -1
- package/dist/AuthorizationCodeClientV1_0_11.d.ts +9 -0
- package/dist/AuthorizationCodeClientV1_0_11.d.ts.map +1 -0
- package/dist/AuthorizationCodeClientV1_0_11.js +134 -0
- package/dist/AuthorizationCodeClientV1_0_11.js.map +1 -0
- package/dist/CredentialOfferClient.d.ts.map +1 -1
- package/dist/CredentialOfferClient.js +18 -13
- package/dist/CredentialOfferClient.js.map +1 -1
- package/dist/CredentialOfferClientV1_0_11.d.ts +10 -0
- package/dist/CredentialOfferClientV1_0_11.d.ts.map +1 -0
- package/dist/CredentialOfferClientV1_0_11.js +101 -0
- package/dist/CredentialOfferClientV1_0_11.js.map +1 -0
- package/dist/CredentialOfferClientV1_0_13.d.ts +10 -0
- package/dist/CredentialOfferClientV1_0_13.d.ts.map +1 -0
- package/dist/CredentialOfferClientV1_0_13.js +94 -0
- package/dist/CredentialOfferClientV1_0_13.js.map +1 -0
- package/dist/CredentialRequestClient.d.ts +20 -7
- package/dist/CredentialRequestClient.d.ts.map +1 -1
- package/dist/CredentialRequestClient.js +46 -30
- package/dist/CredentialRequestClient.js.map +1 -1
- package/dist/CredentialRequestClientBuilder.d.ts +11 -6
- package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
- package/dist/CredentialRequestClientBuilder.js +22 -9
- package/dist/CredentialRequestClientBuilder.js.map +1 -1
- package/dist/CredentialRequestClientBuilderV1_0_11.d.ts +48 -0
- package/dist/CredentialRequestClientBuilderV1_0_11.d.ts.map +1 -0
- package/dist/CredentialRequestClientBuilderV1_0_11.js +121 -0
- package/dist/CredentialRequestClientBuilderV1_0_11.js.map +1 -0
- package/dist/CredentialRequestClientV1_0_11.d.ts +50 -0
- package/dist/CredentialRequestClientV1_0_11.d.ts.map +1 -0
- package/dist/CredentialRequestClientV1_0_11.js +151 -0
- package/dist/CredentialRequestClientV1_0_11.js.map +1 -0
- package/dist/MetadataClient.d.ts +5 -15
- package/dist/MetadataClient.d.ts.map +1 -1
- package/dist/MetadataClient.js +41 -44
- package/dist/MetadataClient.js.map +1 -1
- package/dist/MetadataClientV1_0_11.d.ts +31 -0
- package/dist/MetadataClientV1_0_11.d.ts.map +1 -0
- package/dist/MetadataClientV1_0_11.js +182 -0
- package/dist/MetadataClientV1_0_11.js.map +1 -0
- package/dist/MetadataClientV1_0_13.d.ts +31 -0
- package/dist/MetadataClientV1_0_13.d.ts.map +1 -0
- package/dist/MetadataClientV1_0_13.js +181 -0
- package/dist/MetadataClientV1_0_13.js.map +1 -0
- package/dist/OpenID4VCIClient.d.ts +14 -19
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +111 -61
- package/dist/OpenID4VCIClient.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts +108 -0
- package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -0
- package/dist/OpenID4VCIClientV1_0_11.js +449 -0
- package/dist/OpenID4VCIClientV1_0_11.js.map +1 -0
- package/dist/OpenID4VCIClientV1_0_13.d.ts +112 -0
- package/dist/OpenID4VCIClientV1_0_13.d.ts.map +1 -0
- package/dist/OpenID4VCIClientV1_0_13.js +478 -0
- package/dist/OpenID4VCIClientV1_0_13.js.map +1 -0
- package/dist/ProofOfPossessionBuilder.d.ts +14 -3
- package/dist/ProofOfPossessionBuilder.d.ts.map +1 -1
- package/dist/ProofOfPossessionBuilder.js +20 -21
- package/dist/ProofOfPossessionBuilder.js.map +1 -1
- package/dist/functions/OpenIDUtils.d.ts +12 -0
- package/dist/functions/OpenIDUtils.d.ts.map +1 -0
- package/dist/functions/OpenIDUtils.js +37 -0
- package/dist/functions/OpenIDUtils.js.map +1 -0
- package/dist/functions/index.d.ts +2 -3
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +2 -3
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/notifications.d.ts +4 -0
- package/dist/functions/notifications.d.ts.map +1 -0
- package/dist/functions/notifications.js +39 -0
- package/dist/functions/notifications.js.map +1 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/lib/AccessTokenClient.ts +59 -34
- package/lib/AccessTokenClientV1_0_11.ts +250 -0
- package/lib/AuthorizationCodeClient.ts +131 -28
- package/lib/AuthorizationCodeClientV1_0_11.ts +170 -0
- package/lib/CredentialOfferClient.ts +21 -8
- package/lib/CredentialOfferClientV1_0_11.ts +112 -0
- package/lib/CredentialOfferClientV1_0_13.ts +103 -0
- package/lib/CredentialRequestClient.ts +65 -26
- package/lib/CredentialRequestClientBuilder.ts +34 -16
- package/lib/CredentialRequestClientBuilderV1_0_11.ts +163 -0
- package/lib/CredentialRequestClientV1_0_11.ts +197 -0
- package/lib/MetadataClient.ts +64 -49
- package/lib/MetadataClientV1_0_11.ts +189 -0
- package/lib/MetadataClientV1_0_13.ts +188 -0
- package/lib/OpenID4VCIClient.ts +132 -68
- package/lib/OpenID4VCIClientV1_0_11.ts +635 -0
- package/lib/OpenID4VCIClientV1_0_13.ts +677 -0
- package/lib/ProofOfPossessionBuilder.ts +41 -11
- package/lib/__tests__/AccessTokenClient.spec.ts +40 -12
- package/lib/__tests__/AuthorizationDetailsBuilder.spec.ts +0 -12
- package/lib/__tests__/CredentialRequestClient.spec.ts +87 -50
- package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +18 -12
- package/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +317 -0
- package/lib/__tests__/EBSIE2E.spec.test.ts +2 -2
- package/lib/__tests__/HttpUtils.spec.ts +1 -1
- package/lib/__tests__/IT.spec.ts +264 -14
- package/lib/__tests__/IssuanceInitiation.spec.ts +59 -4
- package/lib/__tests__/IssuanceInitiationV1_0_11.spec.ts +62 -0
- package/lib/__tests__/MattrE2E.spec.test.ts +2 -2
- package/lib/__tests__/MetadataClient.spec.ts +53 -3
- package/lib/__tests__/MetadataMocks.ts +42 -2
- package/lib/__tests__/OpenID4VCIClient.spec.ts +58 -2
- package/lib/__tests__/{OpenID4VCIClientPAR.spec.ts → OpenID4VCIClientPARV1_0_11.spec.ts} +5 -5
- package/lib/__tests__/OpenID4VCIClientV1_0_11.spec.ts +226 -0
- package/lib/__tests__/OpenID4VCIClientV1_0_13.spec.ts +204 -0
- package/lib/__tests__/ProofOfPossessionBuilder.spec.ts +1 -1
- package/lib/__tests__/SdJwt.spec.ts +36 -30
- package/lib/__tests__/SphereonE2E.spec.test.ts +10 -7
- package/lib/__tests__/data/VciDataFixtures.ts +712 -27
- package/lib/functions/OpenIDUtils.ts +25 -0
- package/lib/functions/index.ts +2 -3
- package/lib/functions/notifications.ts +32 -0
- package/lib/index.ts +16 -1
- package/lib/types/index.ts +6 -0
- package/package.json +4 -4
- package/dist/functions/ProofUtil.d.ts +0 -30
- package/dist/functions/ProofUtil.d.ts.map +0 -1
- package/dist/functions/ProofUtil.js +0 -106
- package/dist/functions/ProofUtil.js.map +0 -1
- package/lib/functions/ProofUtil.ts +0 -128
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
convertJsonToURI,
|
|
3
|
+
convertURIToJsonObject,
|
|
2
4
|
CredentialOffer,
|
|
3
5
|
CredentialOfferPayload,
|
|
4
6
|
CredentialOfferPayloadV1_0_09,
|
|
5
7
|
CredentialOfferRequestWithBaseUrl,
|
|
6
8
|
CredentialOfferV1_0_11,
|
|
9
|
+
CredentialOfferV1_0_13,
|
|
7
10
|
determineSpecVersionFromURI,
|
|
8
11
|
getClientIdFromCredentialOfferPayload,
|
|
9
12
|
OpenId4VCIVersion,
|
|
@@ -11,7 +14,7 @@ import {
|
|
|
11
14
|
} from '@sphereon/oid4vci-common';
|
|
12
15
|
import Debug from 'debug';
|
|
13
16
|
|
|
14
|
-
import {
|
|
17
|
+
import { LOG } from './types';
|
|
15
18
|
|
|
16
19
|
const debug = Debug('sphereon:oid4vci:offer');
|
|
17
20
|
|
|
@@ -25,21 +28,24 @@ export class CredentialOfferClient {
|
|
|
25
28
|
const scheme = uri.split('://')[0];
|
|
26
29
|
const baseUrl = uri.split('?')[0];
|
|
27
30
|
const version = determineSpecVersionFromURI(uri);
|
|
31
|
+
LOG.log(`Offer URL determined to be of version ${version}`);
|
|
28
32
|
let credentialOffer: CredentialOffer;
|
|
29
33
|
let credentialOfferPayload: CredentialOfferPayload;
|
|
34
|
+
// credential offer was introduced in draft 9 and credential_offer_uri in draft 11
|
|
30
35
|
if (version < OpenId4VCIVersion.VER_1_0_11) {
|
|
31
36
|
credentialOfferPayload = convertURIToJsonObject(uri, {
|
|
32
37
|
arrayTypeProperties: ['credential_type'],
|
|
33
|
-
requiredProperties: uri.includes('
|
|
38
|
+
requiredProperties: uri.includes('credential_offer=') ? ['credential_offer'] : ['issuer', 'credential_type'],
|
|
34
39
|
}) as CredentialOfferPayloadV1_0_09;
|
|
35
40
|
credentialOffer = {
|
|
36
41
|
credential_offer: credentialOfferPayload,
|
|
37
42
|
};
|
|
38
43
|
} else {
|
|
39
44
|
credentialOffer = convertURIToJsonObject(uri, {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
// It must have the '=' sign after credential_offer otherwise the uri will get split at openid_credential_offer
|
|
46
|
+
arrayTypeProperties: uri.includes('credential_offer_uri=') ? ['credential_offer_uri='] : ['credential_offer='],
|
|
47
|
+
requiredProperties: uri.includes('credential_offer_uri=') ? ['credential_offer_uri='] : ['credential_offer='],
|
|
48
|
+
}) as CredentialOfferV1_0_11 | CredentialOfferV1_0_13;
|
|
43
49
|
if (credentialOffer?.credential_offer_uri === undefined && !credentialOffer?.credential_offer) {
|
|
44
50
|
throw Error('Either a credential_offer or credential_offer_uri should be present in ' + uri);
|
|
45
51
|
}
|
|
@@ -55,13 +61,20 @@ export class CredentialOfferClient {
|
|
|
55
61
|
return {
|
|
56
62
|
scheme,
|
|
57
63
|
baseUrl,
|
|
58
|
-
clientId,
|
|
64
|
+
...(clientId && { clientId }),
|
|
59
65
|
...request,
|
|
60
66
|
...(grants?.authorization_code?.issuer_state && { issuerState: grants.authorization_code.issuer_state }),
|
|
61
67
|
...(grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.['pre-authorized_code'] && {
|
|
62
68
|
preAuthorizedCode: grants['urn:ietf:params:oauth:grant-type:pre-authorized_code']['pre-authorized_code'],
|
|
63
69
|
}),
|
|
64
|
-
userPinRequired:
|
|
70
|
+
userPinRequired:
|
|
71
|
+
request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.user_pin_required ??
|
|
72
|
+
!!request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code ??
|
|
73
|
+
false,
|
|
74
|
+
...(request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code &&
|
|
75
|
+
{
|
|
76
|
+
// txCode: request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code,
|
|
77
|
+
}),
|
|
65
78
|
};
|
|
66
79
|
}
|
|
67
80
|
|
|
@@ -101,7 +114,7 @@ export class CredentialOfferClient {
|
|
|
101
114
|
arrayTypeProperties: isUri ? [] : ['credential_type'],
|
|
102
115
|
uriTypeProperties: isUri
|
|
103
116
|
? ['credential_offer_uri']
|
|
104
|
-
: version >= OpenId4VCIVersion.
|
|
117
|
+
: version >= OpenId4VCIVersion.VER_1_0_13
|
|
105
118
|
? ['credential_issuer', 'credential_type']
|
|
106
119
|
: ['issuer', 'credential_type'],
|
|
107
120
|
param,
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
convertJsonToURI,
|
|
3
|
+
convertURIToJsonObject,
|
|
4
|
+
CredentialOffer,
|
|
5
|
+
CredentialOfferPayload,
|
|
6
|
+
CredentialOfferPayloadV1_0_09,
|
|
7
|
+
CredentialOfferRequestWithBaseUrl,
|
|
8
|
+
CredentialOfferRequestWithBaseUrlV1_0_11,
|
|
9
|
+
CredentialOfferV1_0_11,
|
|
10
|
+
determineSpecVersionFromURI,
|
|
11
|
+
getClientIdFromCredentialOfferPayload,
|
|
12
|
+
OpenId4VCIVersion,
|
|
13
|
+
toUniformCredentialOfferRequest,
|
|
14
|
+
} from '@sphereon/oid4vci-common';
|
|
15
|
+
import Debug from 'debug';
|
|
16
|
+
|
|
17
|
+
const debug = Debug('sphereon:oid4vci:offer');
|
|
18
|
+
|
|
19
|
+
export class CredentialOfferClientV1_0_11 {
|
|
20
|
+
public static async fromURI(uri: string, opts?: { resolve?: boolean }): Promise<CredentialOfferRequestWithBaseUrlV1_0_11> {
|
|
21
|
+
debug(`Credential Offer URI: ${uri}`);
|
|
22
|
+
if (!uri.includes('?') || !uri.includes('://')) {
|
|
23
|
+
debug(`Invalid Credential Offer URI: ${uri}`);
|
|
24
|
+
throw Error(`Invalid Credential Offer Request`);
|
|
25
|
+
}
|
|
26
|
+
const scheme = uri.split('://')[0];
|
|
27
|
+
const baseUrl = uri.split('?')[0];
|
|
28
|
+
const version = determineSpecVersionFromURI(uri);
|
|
29
|
+
let credentialOffer: CredentialOffer;
|
|
30
|
+
let credentialOfferPayload: CredentialOfferPayload;
|
|
31
|
+
if (version < OpenId4VCIVersion.VER_1_0_11) {
|
|
32
|
+
credentialOfferPayload = convertURIToJsonObject(uri, {
|
|
33
|
+
arrayTypeProperties: ['credential_type'],
|
|
34
|
+
requiredProperties: uri.includes('credential_offer_uri=') ? ['credential_offer_uri='] : ['issuer', 'credential_type='],
|
|
35
|
+
}) as CredentialOfferPayloadV1_0_09;
|
|
36
|
+
credentialOffer = {
|
|
37
|
+
credential_offer: credentialOfferPayload,
|
|
38
|
+
};
|
|
39
|
+
} else {
|
|
40
|
+
credentialOffer = convertURIToJsonObject(uri, {
|
|
41
|
+
arrayTypeProperties: ['credentials'],
|
|
42
|
+
requiredProperties: uri.includes('credential_offer_uri=') ? ['credential_offer_uri='] : ['credential_offer='],
|
|
43
|
+
}) as CredentialOfferV1_0_11;
|
|
44
|
+
if (credentialOffer?.credential_offer_uri === undefined && !credentialOffer?.credential_offer) {
|
|
45
|
+
throw Error('Either a credential_offer or credential_offer_uri should be present in ' + uri);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const request = await toUniformCredentialOfferRequest(credentialOffer, {
|
|
50
|
+
...opts,
|
|
51
|
+
version,
|
|
52
|
+
});
|
|
53
|
+
const clientId = getClientIdFromCredentialOfferPayload(request.credential_offer);
|
|
54
|
+
const grants = request.credential_offer?.grants;
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
scheme,
|
|
58
|
+
baseUrl,
|
|
59
|
+
...(clientId && { clientId }),
|
|
60
|
+
...request,
|
|
61
|
+
...(grants?.authorization_code?.issuer_state && { issuerState: grants.authorization_code.issuer_state }),
|
|
62
|
+
...(grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.['pre-authorized_code'] && {
|
|
63
|
+
preAuthorizedCode: grants['urn:ietf:params:oauth:grant-type:pre-authorized_code']['pre-authorized_code'],
|
|
64
|
+
}),
|
|
65
|
+
userPinRequired: !!request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.user_pin_required ?? false,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public static toURI(
|
|
70
|
+
requestWithBaseUrl: CredentialOfferRequestWithBaseUrl,
|
|
71
|
+
opts?: {
|
|
72
|
+
version?: OpenId4VCIVersion;
|
|
73
|
+
},
|
|
74
|
+
): string {
|
|
75
|
+
debug(`Credential Offer Request with base URL: ${JSON.stringify(requestWithBaseUrl)}`);
|
|
76
|
+
const version = opts?.version ?? requestWithBaseUrl.version;
|
|
77
|
+
let baseUrl = requestWithBaseUrl.baseUrl.includes(requestWithBaseUrl.scheme)
|
|
78
|
+
? requestWithBaseUrl.baseUrl
|
|
79
|
+
: `${requestWithBaseUrl.scheme.replace('://', '')}://${requestWithBaseUrl.baseUrl}`;
|
|
80
|
+
let param: string | undefined;
|
|
81
|
+
|
|
82
|
+
const isUri = requestWithBaseUrl.credential_offer_uri !== undefined;
|
|
83
|
+
|
|
84
|
+
if (version.valueOf() >= OpenId4VCIVersion.VER_1_0_11.valueOf()) {
|
|
85
|
+
// v11 changed from encoding every param to a encoded json object with a credential_offer param key
|
|
86
|
+
if (!baseUrl.includes('?')) {
|
|
87
|
+
param = isUri ? 'credential_offer_uri' : 'credential_offer';
|
|
88
|
+
} else {
|
|
89
|
+
const split = baseUrl.split('?');
|
|
90
|
+
if (split.length > 1 && split[1] !== '') {
|
|
91
|
+
if (baseUrl.endsWith('&')) {
|
|
92
|
+
param = isUri ? 'credential_offer_uri' : 'credential_offer';
|
|
93
|
+
} else if (!baseUrl.endsWith('=')) {
|
|
94
|
+
baseUrl += `&`;
|
|
95
|
+
param = isUri ? 'credential_offer_uri' : 'credential_offer';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return convertJsonToURI(requestWithBaseUrl.credential_offer_uri ?? requestWithBaseUrl.original_credential_offer, {
|
|
101
|
+
baseUrl,
|
|
102
|
+
arrayTypeProperties: isUri ? [] : ['credential_type'],
|
|
103
|
+
uriTypeProperties: isUri
|
|
104
|
+
? ['credential_offer_uri']
|
|
105
|
+
: version >= OpenId4VCIVersion.VER_1_0_11
|
|
106
|
+
? ['credential_issuer', 'credential_type']
|
|
107
|
+
: ['issuer', 'credential_type'],
|
|
108
|
+
param,
|
|
109
|
+
version,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
convertJsonToURI,
|
|
3
|
+
convertURIToJsonObject,
|
|
4
|
+
CredentialOfferRequestWithBaseUrl,
|
|
5
|
+
CredentialOfferV1_0_13,
|
|
6
|
+
determineSpecVersionFromURI,
|
|
7
|
+
getClientIdFromCredentialOfferPayload,
|
|
8
|
+
OpenId4VCIVersion,
|
|
9
|
+
toUniformCredentialOfferRequest,
|
|
10
|
+
} from '@sphereon/oid4vci-common';
|
|
11
|
+
import Debug from 'debug';
|
|
12
|
+
|
|
13
|
+
const debug = Debug('sphereon:oid4vci:offer');
|
|
14
|
+
|
|
15
|
+
export class CredentialOfferClientV1_0_13 {
|
|
16
|
+
public static async fromURI(uri: string, opts?: { resolve?: boolean }): Promise<CredentialOfferRequestWithBaseUrl> {
|
|
17
|
+
debug(`Credential Offer URI: ${uri}`);
|
|
18
|
+
if (!uri.includes('?') || !uri.includes('://')) {
|
|
19
|
+
debug(`Invalid Credential Offer URI: ${uri}`);
|
|
20
|
+
throw Error(`Invalid Credential Offer Request`);
|
|
21
|
+
}
|
|
22
|
+
const scheme = uri.split('://')[0];
|
|
23
|
+
const baseUrl = uri.split('?')[0];
|
|
24
|
+
const version = determineSpecVersionFromURI(uri);
|
|
25
|
+
const credentialOffer = convertURIToJsonObject(uri, {
|
|
26
|
+
// It must have the '=' sign after credential_offer otherwise the uri will get split at openid_credential_offer
|
|
27
|
+
arrayTypeProperties: uri.includes('credential_offer_uri=')
|
|
28
|
+
? ['credential_configuration_ids', 'credential_offer_uri=']
|
|
29
|
+
: ['credential_configuration_ids', 'credential_offer='],
|
|
30
|
+
requiredProperties: uri.includes('credential_offer_uri=') ? ['credential_offer_uri='] : ['credential_offer='],
|
|
31
|
+
}) as CredentialOfferV1_0_13;
|
|
32
|
+
if (credentialOffer?.credential_offer_uri === undefined && !credentialOffer?.credential_offer) {
|
|
33
|
+
throw Error('Either a credential_offer or credential_offer_uri should be present in ' + uri);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const request = await toUniformCredentialOfferRequest(credentialOffer, {
|
|
37
|
+
...opts,
|
|
38
|
+
version,
|
|
39
|
+
});
|
|
40
|
+
const clientId = getClientIdFromCredentialOfferPayload(request.credential_offer);
|
|
41
|
+
const grants = request.credential_offer?.grants;
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
scheme,
|
|
45
|
+
baseUrl,
|
|
46
|
+
...(clientId && { clientId }),
|
|
47
|
+
...request,
|
|
48
|
+
...(grants?.authorization_code?.issuer_state && { issuerState: grants.authorization_code.issuer_state }),
|
|
49
|
+
...(grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.['pre-authorized_code'] && {
|
|
50
|
+
preAuthorizedCode: grants['urn:ietf:params:oauth:grant-type:pre-authorized_code']['pre-authorized_code'],
|
|
51
|
+
}),
|
|
52
|
+
userPinRequired: !!request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code ?? false,
|
|
53
|
+
...(request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code &&
|
|
54
|
+
{
|
|
55
|
+
// txCode: request.credential_offer?.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.tx_code,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static toURI(
|
|
61
|
+
requestWithBaseUrl: CredentialOfferRequestWithBaseUrl,
|
|
62
|
+
opts?: {
|
|
63
|
+
version?: OpenId4VCIVersion;
|
|
64
|
+
},
|
|
65
|
+
): string {
|
|
66
|
+
debug(`Credential Offer Request with base URL: ${JSON.stringify(requestWithBaseUrl)}`);
|
|
67
|
+
const version = opts?.version ?? requestWithBaseUrl.version;
|
|
68
|
+
let baseUrl = requestWithBaseUrl.baseUrl.includes(requestWithBaseUrl.scheme)
|
|
69
|
+
? requestWithBaseUrl.baseUrl
|
|
70
|
+
: `${requestWithBaseUrl.scheme.replace('://', '')}://${requestWithBaseUrl.baseUrl}`;
|
|
71
|
+
let param: string | undefined;
|
|
72
|
+
|
|
73
|
+
const isUri = requestWithBaseUrl.credential_offer_uri !== undefined;
|
|
74
|
+
|
|
75
|
+
if (version.valueOf() >= OpenId4VCIVersion.VER_1_0_11.valueOf()) {
|
|
76
|
+
// v11 changed from encoding every param to a encoded json object with a credential_offer param key
|
|
77
|
+
if (!baseUrl.includes('?')) {
|
|
78
|
+
param = isUri ? 'credential_offer_uri' : 'credential_offer';
|
|
79
|
+
} else {
|
|
80
|
+
const split = baseUrl.split('?');
|
|
81
|
+
if (split.length > 1 && split[1] !== '') {
|
|
82
|
+
if (baseUrl.endsWith('&')) {
|
|
83
|
+
param = isUri ? 'credential_offer_uri' : 'credential_offer';
|
|
84
|
+
} else if (!baseUrl.endsWith('=')) {
|
|
85
|
+
baseUrl += `&`;
|
|
86
|
+
param = isUri ? 'credential_offer_uri' : 'credential_offer';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return convertJsonToURI(requestWithBaseUrl.credential_offer_uri ?? requestWithBaseUrl.original_credential_offer, {
|
|
92
|
+
baseUrl,
|
|
93
|
+
arrayTypeProperties: isUri ? [] : ['credential_type'],
|
|
94
|
+
uriTypeProperties: isUri
|
|
95
|
+
? ['credential_offer_uri']
|
|
96
|
+
: version >= OpenId4VCIVersion.VER_1_0_13
|
|
97
|
+
? ['credential_issuer', 'credential_type']
|
|
98
|
+
: ['issuer', 'credential_type'],
|
|
99
|
+
param,
|
|
100
|
+
version,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
acquireDeferredCredential,
|
|
3
|
+
CredentialRequestV1_0_13,
|
|
3
4
|
CredentialResponse,
|
|
4
5
|
getCredentialRequestForVersion,
|
|
5
6
|
getUniformFormat,
|
|
6
7
|
isDeferredCredentialResponse,
|
|
8
|
+
isValidURL,
|
|
9
|
+
JsonLdIssuerCredentialDefinition,
|
|
7
10
|
OID4VCICredentialFormat,
|
|
8
11
|
OpenId4VCIVersion,
|
|
9
12
|
OpenIDResponse,
|
|
13
|
+
post,
|
|
10
14
|
ProofOfPossession,
|
|
11
15
|
UniformCredentialRequest,
|
|
12
16
|
URL_NOT_VALID,
|
|
13
17
|
} from '@sphereon/oid4vci-common';
|
|
18
|
+
import { ExperimentalSubjectIssuance } from '@sphereon/oid4vci-common/dist/experimental/holder-vci';
|
|
14
19
|
import { CredentialFormat } from '@sphereon/ssi-types';
|
|
15
20
|
import Debug from 'debug';
|
|
16
21
|
|
|
17
22
|
import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder';
|
|
18
23
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
19
|
-
import { isValidURL, post } from './functions';
|
|
20
24
|
|
|
21
25
|
const debug = Debug('sphereon:oid4vci:credential');
|
|
22
26
|
|
|
@@ -24,12 +28,15 @@ export interface CredentialRequestOpts {
|
|
|
24
28
|
deferredCredentialAwait?: boolean;
|
|
25
29
|
deferredCredentialIntervalInMS?: number;
|
|
26
30
|
credentialEndpoint: string;
|
|
31
|
+
notificationEndpoint?: string;
|
|
27
32
|
deferredCredentialEndpoint?: string;
|
|
28
|
-
credentialTypes
|
|
33
|
+
credentialTypes?: string[];
|
|
34
|
+
credentialIdentifier?: string;
|
|
29
35
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
30
36
|
proof: ProofOfPossession;
|
|
31
37
|
token: string;
|
|
32
38
|
version: OpenId4VCIVersion;
|
|
39
|
+
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
export async function buildProof<DIDDoc>(
|
|
@@ -41,7 +48,7 @@ export async function buildProof<DIDDoc>(
|
|
|
41
48
|
) {
|
|
42
49
|
if ('proof_type' in proofInput) {
|
|
43
50
|
if (opts.cNonce) {
|
|
44
|
-
throw Error(`Cnonce param is only supported when using a Proof of
|
|
51
|
+
throw Error(`Cnonce param is only supported when using a Proof of possession builder`);
|
|
45
52
|
}
|
|
46
53
|
return await ProofOfPossessionBuilder.fromProof(proofInput as ProofOfPossession, opts.version).build();
|
|
47
54
|
}
|
|
@@ -77,18 +84,33 @@ export class CredentialRequestClient {
|
|
|
77
84
|
|
|
78
85
|
public async acquireCredentialsUsingProof<DIDDoc>(opts: {
|
|
79
86
|
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
|
|
87
|
+
credentialIdentifier?: string;
|
|
80
88
|
credentialTypes?: string | string[];
|
|
81
89
|
context?: string[];
|
|
82
90
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
92
|
+
}): Promise<OpenIDResponse<CredentialResponse> & { access_token: string }> {
|
|
93
|
+
const { credentialIdentifier, credentialTypes, proofInput, format, context, subjectIssuance } = opts;
|
|
94
|
+
|
|
95
|
+
const request = await this.createCredentialRequest({
|
|
96
|
+
proofInput,
|
|
97
|
+
credentialTypes,
|
|
98
|
+
context,
|
|
99
|
+
format,
|
|
100
|
+
version: this.version(),
|
|
101
|
+
credentialIdentifier,
|
|
102
|
+
subjectIssuance,
|
|
103
|
+
});
|
|
87
104
|
return await this.acquireCredentialsUsingRequest(request);
|
|
88
105
|
}
|
|
89
106
|
|
|
90
|
-
public async acquireCredentialsUsingRequest(
|
|
91
|
-
|
|
107
|
+
public async acquireCredentialsUsingRequest(
|
|
108
|
+
uniformRequest: UniformCredentialRequest,
|
|
109
|
+
): Promise<OpenIDResponse<CredentialResponse> & { access_token: string }> {
|
|
110
|
+
if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
|
|
111
|
+
throw new Error('Versions below v1.0.13 (draft 13) are not supported by the V13 credential request client.');
|
|
112
|
+
}
|
|
113
|
+
const request: CredentialRequestV1_0_13 = getCredentialRequestForVersion(uniformRequest, this.version()) as CredentialRequestV1_0_13;
|
|
92
114
|
const credentialEndpoint: string = this.credentialRequestOpts.credentialEndpoint;
|
|
93
115
|
if (!isValidURL(credentialEndpoint)) {
|
|
94
116
|
debug(`Invalid credential endpoint: ${credentialEndpoint}`);
|
|
@@ -97,12 +119,20 @@ export class CredentialRequestClient {
|
|
|
97
119
|
debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
|
|
98
120
|
debug(`request\n: ${JSON.stringify(request, null, 2)}`);
|
|
99
121
|
const requestToken: string = this.credentialRequestOpts.token;
|
|
100
|
-
let response
|
|
122
|
+
let response = (await post(credentialEndpoint, JSON.stringify(request), { bearerToken: requestToken })) as OpenIDResponse<CredentialResponse> & {
|
|
123
|
+
access_token: string;
|
|
124
|
+
};
|
|
101
125
|
this._isDeferred = isDeferredCredentialResponse(response);
|
|
102
126
|
if (this.isDeferred() && this.credentialRequestOpts.deferredCredentialAwait && response.successBody) {
|
|
103
127
|
response = await this.acquireDeferredCredential(response.successBody, { bearerToken: this.credentialRequestOpts.token });
|
|
104
128
|
}
|
|
129
|
+
response.access_token = requestToken;
|
|
105
130
|
|
|
131
|
+
if ((uniformRequest.credential_subject_issuance && response.successBody) || response.successBody?.credential_subject_issuance) {
|
|
132
|
+
if (JSON.stringify(uniformRequest.credential_subject_issuance) !== JSON.stringify(response.successBody?.credential_subject_issuance)) {
|
|
133
|
+
throw Error('Subject signing was requested, but issuer did not provide the options in its response');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
106
136
|
debug(`Credential endpoint ${credentialEndpoint} response:\r\n${JSON.stringify(response, null, 2)}`);
|
|
107
137
|
return response;
|
|
108
138
|
}
|
|
@@ -112,7 +142,7 @@ export class CredentialRequestClient {
|
|
|
112
142
|
opts?: {
|
|
113
143
|
bearerToken?: string;
|
|
114
144
|
},
|
|
115
|
-
): Promise<OpenIDResponse<CredentialResponse
|
|
145
|
+
): Promise<OpenIDResponse<CredentialResponse> & { access_token: string }> {
|
|
116
146
|
const transactionId = response.transaction_id;
|
|
117
147
|
const bearerToken = response.acceptance_token ?? opts?.bearerToken;
|
|
118
148
|
const deferredCredentialEndpoint = this.getDeferredCredentialEndpoint();
|
|
@@ -133,12 +163,24 @@ export class CredentialRequestClient {
|
|
|
133
163
|
|
|
134
164
|
public async createCredentialRequest<DIDDoc>(opts: {
|
|
135
165
|
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
|
|
166
|
+
credentialIdentifier?: string;
|
|
136
167
|
credentialTypes?: string | string[];
|
|
137
168
|
context?: string[];
|
|
138
169
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
170
|
+
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
139
171
|
version: OpenId4VCIVersion;
|
|
140
|
-
}): Promise<
|
|
141
|
-
const { proofInput } = opts;
|
|
172
|
+
}): Promise<CredentialRequestV1_0_13> {
|
|
173
|
+
const { proofInput, credentialIdentifier: credential_identifier } = opts;
|
|
174
|
+
const proof = await buildProof(proofInput, opts);
|
|
175
|
+
if (credential_identifier) {
|
|
176
|
+
if (opts.format || opts.credentialTypes || opts.context) {
|
|
177
|
+
throw Error(`You cannot mix credential_identifier with format, credential types and/or context`);
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
credential_identifier,
|
|
181
|
+
proof,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
142
184
|
const formatSelection = opts.format ?? this.credentialRequestOpts.format;
|
|
143
185
|
|
|
144
186
|
if (!formatSelection) {
|
|
@@ -149,15 +191,13 @@ export class CredentialRequestClient {
|
|
|
149
191
|
opts?.credentialTypes && (typeof opts.credentialTypes === 'string' || opts.credentialTypes.length > 0)
|
|
150
192
|
? opts.credentialTypes
|
|
151
193
|
: this.credentialRequestOpts.credentialTypes;
|
|
194
|
+
if (!typesSelection) {
|
|
195
|
+
throw Error(`Credential type(s) need to be provided`);
|
|
196
|
+
}
|
|
152
197
|
const types = Array.isArray(typesSelection) ? typesSelection : [typesSelection];
|
|
153
198
|
if (types.length === 0) {
|
|
154
199
|
throw Error(`Credential type(s) need to be provided`);
|
|
155
200
|
}
|
|
156
|
-
// FIXME: this is mixing up the type (as id) from v8/v9 and the types (from the vc.type) from v11
|
|
157
|
-
else if (!this.isV11OrHigher() && types.length !== 1) {
|
|
158
|
-
throw Error('Only a single credential type is supported for V8/V9');
|
|
159
|
-
}
|
|
160
|
-
const proof = await buildProof(proofInput, opts);
|
|
161
201
|
|
|
162
202
|
// TODO: we should move format specific logic
|
|
163
203
|
if (format === 'jwt_vc_json' || format === 'jwt_vc') {
|
|
@@ -165,6 +205,7 @@ export class CredentialRequestClient {
|
|
|
165
205
|
types,
|
|
166
206
|
format,
|
|
167
207
|
proof,
|
|
208
|
+
...opts.subjectIssuance,
|
|
168
209
|
};
|
|
169
210
|
} else if (format === 'jwt_vc_json-ld' || format === 'ldp_vc') {
|
|
170
211
|
if (this.version() >= OpenId4VCIVersion.VER_1_0_12 && !opts.context) {
|
|
@@ -174,6 +215,7 @@ export class CredentialRequestClient {
|
|
|
174
215
|
return {
|
|
175
216
|
format,
|
|
176
217
|
proof,
|
|
218
|
+
...opts.subjectIssuance,
|
|
177
219
|
|
|
178
220
|
// Ignored because v11 does not have the context value, but it is required in v12
|
|
179
221
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -181,28 +223,25 @@ export class CredentialRequestClient {
|
|
|
181
223
|
credential_definition: {
|
|
182
224
|
types,
|
|
183
225
|
...(opts.context && { '@context': opts.context }),
|
|
184
|
-
},
|
|
226
|
+
} as JsonLdIssuerCredentialDefinition,
|
|
185
227
|
};
|
|
186
228
|
} else if (format === 'vc+sd-jwt') {
|
|
187
229
|
if (types.length > 1) {
|
|
188
230
|
throw Error(`Only a single credential type is supported for ${format}`);
|
|
189
231
|
}
|
|
190
|
-
|
|
232
|
+
// fixme: this isn't up to the CredentialRequest that we see in the version v1_0_13
|
|
191
233
|
return {
|
|
192
234
|
format,
|
|
193
235
|
proof,
|
|
194
236
|
vct: types[0],
|
|
195
|
-
|
|
237
|
+
...opts.subjectIssuance,
|
|
238
|
+
} as CredentialRequestV1_0_13;
|
|
196
239
|
}
|
|
197
240
|
|
|
198
241
|
throw new Error(`Unsupported format: ${format}`);
|
|
199
242
|
}
|
|
200
243
|
|
|
201
244
|
private version(): OpenId4VCIVersion {
|
|
202
|
-
return this.credentialRequestOpts?.version ?? OpenId4VCIVersion.
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
private isV11OrHigher(): boolean {
|
|
206
|
-
return this.version() >= OpenId4VCIVersion.VER_1_0_11;
|
|
245
|
+
return this.credentialRequestOpts?.version ?? OpenId4VCIVersion.VER_1_0_13;
|
|
207
246
|
}
|
|
208
247
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AccessTokenResponse,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
CredentialIssuerMetadataV1_0_13,
|
|
4
|
+
CredentialOfferPayloadV1_0_13,
|
|
5
5
|
CredentialOfferRequestWithBaseUrl,
|
|
6
6
|
determineSpecVersionFromOffer,
|
|
7
7
|
EndpointMetadata,
|
|
8
|
+
ExperimentalSubjectIssuance,
|
|
8
9
|
getIssuerFromCredentialOfferPayload,
|
|
9
|
-
getTypesFromOffer,
|
|
10
10
|
OID4VCICredentialFormat,
|
|
11
11
|
OpenId4VCIVersion,
|
|
12
12
|
UniformCredentialOfferRequest,
|
|
@@ -21,21 +21,25 @@ export class CredentialRequestClientBuilder {
|
|
|
21
21
|
deferredCredentialEndpoint?: string;
|
|
22
22
|
deferredCredentialAwait = false;
|
|
23
23
|
deferredCredentialIntervalInMS = 5000;
|
|
24
|
-
|
|
24
|
+
credentialIdentifier?: string;
|
|
25
|
+
credentialTypes?: string[] = [];
|
|
25
26
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
26
27
|
token?: string;
|
|
27
28
|
version?: OpenId4VCIVersion;
|
|
29
|
+
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
28
30
|
|
|
29
31
|
public static fromCredentialIssuer({
|
|
30
32
|
credentialIssuer,
|
|
31
33
|
metadata,
|
|
32
34
|
version,
|
|
35
|
+
credentialIdentifier,
|
|
33
36
|
credentialTypes,
|
|
34
37
|
}: {
|
|
35
38
|
credentialIssuer: string;
|
|
36
39
|
metadata?: EndpointMetadata;
|
|
37
40
|
version?: OpenId4VCIVersion;
|
|
38
|
-
|
|
41
|
+
credentialIdentifier?: string;
|
|
42
|
+
credentialTypes?: string | string[];
|
|
39
43
|
}): CredentialRequestClientBuilder {
|
|
40
44
|
const issuer = credentialIssuer;
|
|
41
45
|
const builder = new CredentialRequestClientBuilder();
|
|
@@ -44,7 +48,12 @@ export class CredentialRequestClientBuilder {
|
|
|
44
48
|
if (metadata?.deferred_credential_endpoint) {
|
|
45
49
|
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
46
50
|
}
|
|
47
|
-
|
|
51
|
+
if (credentialIdentifier) {
|
|
52
|
+
builder.withCredentialIdentifier(credentialIdentifier);
|
|
53
|
+
}
|
|
54
|
+
if (credentialTypes) {
|
|
55
|
+
builder.withCredentialType(credentialTypes);
|
|
56
|
+
}
|
|
48
57
|
return builder;
|
|
49
58
|
}
|
|
50
59
|
|
|
@@ -62,6 +71,9 @@ export class CredentialRequestClientBuilder {
|
|
|
62
71
|
}): CredentialRequestClientBuilder {
|
|
63
72
|
const { request, metadata } = opts;
|
|
64
73
|
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
|
|
74
|
+
if (version < OpenId4VCIVersion.VER_1_0_13) {
|
|
75
|
+
throw new Error('Versions below v1.0.13 (draft 13) are not supported.');
|
|
76
|
+
}
|
|
65
77
|
const builder = new CredentialRequestClientBuilder();
|
|
66
78
|
const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
|
|
67
79
|
builder.withVersion(version);
|
|
@@ -69,15 +81,11 @@ export class CredentialRequestClientBuilder {
|
|
|
69
81
|
if (metadata?.deferred_credential_endpoint) {
|
|
70
82
|
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
71
83
|
}
|
|
72
|
-
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
builder.
|
|
76
|
-
} else {
|
|
77
|
-
// todo: look whether this is correct
|
|
78
|
-
builder.withCredentialType(getTypesFromOffer(request.credential_offer));
|
|
84
|
+
const ids: string[] = (request.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids;
|
|
85
|
+
// if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
|
|
86
|
+
if (ids.length && ids.length === 1) {
|
|
87
|
+
builder.withCredentialIdentifier(ids[0]);
|
|
79
88
|
}
|
|
80
|
-
|
|
81
89
|
return builder;
|
|
82
90
|
}
|
|
83
91
|
|
|
@@ -95,7 +103,7 @@ export class CredentialRequestClientBuilder {
|
|
|
95
103
|
});
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
public withCredentialEndpointFromMetadata(metadata:
|
|
106
|
+
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
99
107
|
this.credentialEndpoint = metadata.credential_endpoint;
|
|
100
108
|
return this;
|
|
101
109
|
}
|
|
@@ -105,7 +113,7 @@ export class CredentialRequestClientBuilder {
|
|
|
105
113
|
return this;
|
|
106
114
|
}
|
|
107
115
|
|
|
108
|
-
public withDeferredCredentialEndpointFromMetadata(metadata:
|
|
116
|
+
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
109
117
|
this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
|
|
110
118
|
return this;
|
|
111
119
|
}
|
|
@@ -121,6 +129,11 @@ export class CredentialRequestClientBuilder {
|
|
|
121
129
|
return this;
|
|
122
130
|
}
|
|
123
131
|
|
|
132
|
+
public withCredentialIdentifier(credentialIdentifier: string): this {
|
|
133
|
+
this.credentialIdentifier = credentialIdentifier;
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
|
|
124
137
|
public withCredentialType(credentialTypes: string | string[]): this {
|
|
125
138
|
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
|
|
126
139
|
return this;
|
|
@@ -131,6 +144,11 @@ export class CredentialRequestClientBuilder {
|
|
|
131
144
|
return this;
|
|
132
145
|
}
|
|
133
146
|
|
|
147
|
+
public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
|
|
148
|
+
this.subjectIssuance = subjectIssuance;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
|
|
134
152
|
public withToken(accessToken: string): this {
|
|
135
153
|
this.token = accessToken;
|
|
136
154
|
return this;
|