@sphereon/oid4vci-client 0.8.2-next.6 → 0.8.2-next.88
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 +9 -8
- package/dist/AccessTokenClient.d.ts +0 -1
- package/dist/AccessTokenClient.d.ts.map +1 -1
- package/dist/AccessTokenClient.js +11 -18
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AuthorizationCodeClient.d.ts +9 -0
- package/dist/AuthorizationCodeClient.d.ts.map +1 -0
- package/dist/AuthorizationCodeClient.js +132 -0
- package/dist/AuthorizationCodeClient.js.map +1 -0
- package/dist/AuthorizationDetailsBuilder.d.ts.map +1 -1
- package/dist/AuthorizationDetailsBuilder.js.map +1 -1
- package/dist/CredentialOfferClient.d.ts.map +1 -1
- package/dist/CredentialOfferClient.js +3 -1
- package/dist/CredentialOfferClient.js.map +1 -1
- package/dist/CredentialRequestClient.d.ts +15 -0
- package/dist/CredentialRequestClient.d.ts.map +1 -1
- package/dist/CredentialRequestClient.js +91 -43
- package/dist/CredentialRequestClient.js.map +1 -1
- package/dist/CredentialRequestClientBuilder.d.ts +19 -7
- package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
- package/dist/CredentialRequestClientBuilder.js +31 -1
- package/dist/CredentialRequestClientBuilder.js.map +1 -1
- package/dist/MetadataClient.d.ts.map +1 -1
- package/dist/MetadataClient.js +12 -1
- package/dist/MetadataClient.js.map +1 -1
- package/dist/OpenID4VCIClient.d.ts +62 -27
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +255 -176
- package/dist/OpenID4VCIClient.js.map +1 -1
- package/dist/ProofOfPossessionBuilder.d.ts +3 -1
- package/dist/ProofOfPossessionBuilder.d.ts.map +1 -1
- package/dist/ProofOfPossessionBuilder.js +5 -0
- package/dist/ProofOfPossessionBuilder.js.map +1 -1
- package/dist/functions/AuthorizationUtil.d.ts +3 -0
- package/dist/functions/AuthorizationUtil.d.ts.map +1 -0
- package/dist/functions/AuthorizationUtil.js +22 -0
- package/dist/functions/AuthorizationUtil.js.map +1 -0
- package/dist/functions/ProofUtil.d.ts +2 -1
- package/dist/functions/ProofUtil.d.ts.map +1 -1
- package/dist/functions/ProofUtil.js +6 -4
- package/dist/functions/ProofUtil.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/lib/AccessTokenClient.ts +16 -20
- package/lib/AuthorizationCodeClient.ts +163 -0
- package/lib/AuthorizationDetailsBuilder.ts +2 -2
- package/lib/CredentialOfferClient.ts +4 -1
- package/lib/CredentialRequestClient.ts +116 -45
- package/lib/CredentialRequestClientBuilder.ts +53 -8
- package/lib/MetadataClient.ts +13 -1
- package/lib/OpenID4VCIClient.ts +348 -216
- package/lib/ProofOfPossessionBuilder.ts +8 -0
- package/lib/__tests__/AccessTokenClient.spec.ts +2 -0
- package/lib/__tests__/CredentialRequestClient.spec.ts +28 -8
- package/lib/__tests__/EBSIE2E.spec.test.ts +145 -0
- package/lib/__tests__/MetadataClient.spec.ts +4 -1
- package/lib/__tests__/OpenID4VCIClient.spec.ts +117 -76
- package/lib/__tests__/OpenID4VCIClientPAR.spec.ts +59 -49
- package/lib/__tests__/SdJwt.spec.ts +163 -0
- package/lib/__tests__/SphereonE2E.spec.test.ts +2 -2
- package/lib/__tests__/data/VciDataFixtures.ts +14 -13
- package/lib/functions/AuthorizationUtil.ts +18 -0
- package/lib/functions/ProofUtil.ts +18 -4
- package/lib/index.ts +1 -0
- package/lib/types/index.ts +0 -0
- package/package.json +8 -6
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
acquireDeferredCredential,
|
|
3
3
|
CredentialResponse,
|
|
4
|
+
getCredentialRequestForVersion,
|
|
5
|
+
getUniformFormat,
|
|
6
|
+
isDeferredCredentialResponse,
|
|
4
7
|
OID4VCICredentialFormat,
|
|
5
8
|
OpenId4VCIVersion,
|
|
6
9
|
OpenIDResponse,
|
|
@@ -18,7 +21,10 @@ import { isValidURL, post } from './functions';
|
|
|
18
21
|
const debug = Debug('sphereon:oid4vci:credential');
|
|
19
22
|
|
|
20
23
|
export interface CredentialRequestOpts {
|
|
24
|
+
deferredCredentialAwait?: boolean;
|
|
25
|
+
deferredCredentialIntervalInMS?: number;
|
|
21
26
|
credentialEndpoint: string;
|
|
27
|
+
deferredCredentialEndpoint?: string;
|
|
22
28
|
credentialTypes: string[];
|
|
23
29
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
24
30
|
proof: ProofOfPossession;
|
|
@@ -26,17 +32,45 @@ export interface CredentialRequestOpts {
|
|
|
26
32
|
version: OpenId4VCIVersion;
|
|
27
33
|
}
|
|
28
34
|
|
|
35
|
+
export async function buildProof<DIDDoc>(
|
|
36
|
+
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession,
|
|
37
|
+
opts: {
|
|
38
|
+
version: OpenId4VCIVersion;
|
|
39
|
+
cNonce?: string;
|
|
40
|
+
},
|
|
41
|
+
) {
|
|
42
|
+
if ('proof_type' in proofInput) {
|
|
43
|
+
if (opts.cNonce) {
|
|
44
|
+
throw Error(`Cnonce param is only supported when using a Proof of Posession builder`);
|
|
45
|
+
}
|
|
46
|
+
return await ProofOfPossessionBuilder.fromProof(proofInput as ProofOfPossession, opts.version).build();
|
|
47
|
+
}
|
|
48
|
+
if (opts.cNonce) {
|
|
49
|
+
proofInput.withAccessTokenNonce(opts.cNonce);
|
|
50
|
+
}
|
|
51
|
+
return await proofInput.build();
|
|
52
|
+
}
|
|
53
|
+
|
|
29
54
|
export class CredentialRequestClient {
|
|
30
55
|
private readonly _credentialRequestOpts: Partial<CredentialRequestOpts>;
|
|
56
|
+
private _isDeferred = false;
|
|
31
57
|
|
|
32
58
|
get credentialRequestOpts(): CredentialRequestOpts {
|
|
33
59
|
return this._credentialRequestOpts as CredentialRequestOpts;
|
|
34
60
|
}
|
|
35
61
|
|
|
62
|
+
public isDeferred(): boolean {
|
|
63
|
+
return this._isDeferred;
|
|
64
|
+
}
|
|
65
|
+
|
|
36
66
|
public getCredentialEndpoint(): string {
|
|
37
67
|
return this.credentialRequestOpts.credentialEndpoint;
|
|
38
68
|
}
|
|
39
69
|
|
|
70
|
+
public getDeferredCredentialEndpoint(): string | undefined {
|
|
71
|
+
return this.credentialRequestOpts.deferredCredentialEndpoint;
|
|
72
|
+
}
|
|
73
|
+
|
|
40
74
|
public constructor(builder: CredentialRequestClientBuilder) {
|
|
41
75
|
this._credentialRequestOpts = { ...builder };
|
|
42
76
|
}
|
|
@@ -44,68 +78,73 @@ export class CredentialRequestClient {
|
|
|
44
78
|
public async acquireCredentialsUsingProof<DIDDoc>(opts: {
|
|
45
79
|
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
|
|
46
80
|
credentialTypes?: string | string[];
|
|
81
|
+
context?: string[];
|
|
47
82
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
48
83
|
}): Promise<OpenIDResponse<CredentialResponse>> {
|
|
49
|
-
const { credentialTypes, proofInput, format } = opts;
|
|
84
|
+
const { credentialTypes, proofInput, format, context } = opts;
|
|
50
85
|
|
|
51
|
-
const request = await this.createCredentialRequest({ proofInput, credentialTypes, format, version: this.version() });
|
|
86
|
+
const request = await this.createCredentialRequest({ proofInput, credentialTypes, context, format, version: this.version() });
|
|
52
87
|
return await this.acquireCredentialsUsingRequest(request);
|
|
53
88
|
}
|
|
54
89
|
|
|
55
90
|
public async acquireCredentialsUsingRequest(uniformRequest: UniformCredentialRequest): Promise<OpenIDResponse<CredentialResponse>> {
|
|
56
|
-
|
|
57
|
-
if (!this.isV11OrHigher()) {
|
|
58
|
-
let format: string = uniformRequest.format;
|
|
59
|
-
if (format === 'jwt_vc_json') {
|
|
60
|
-
format = 'jwt_vc';
|
|
61
|
-
} else if (format === 'jwt_vc_json-ld') {
|
|
62
|
-
format = 'ldp_vc';
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
request = {
|
|
66
|
-
format,
|
|
67
|
-
proof: uniformRequest.proof,
|
|
68
|
-
type:
|
|
69
|
-
'types' in uniformRequest
|
|
70
|
-
? uniformRequest.types.filter((t) => t !== 'VerifiableCredential')[0]
|
|
71
|
-
: uniformRequest.credential_definition.types[0],
|
|
72
|
-
} as CredentialRequestV1_0_08;
|
|
73
|
-
}
|
|
91
|
+
const request = getCredentialRequestForVersion(uniformRequest, this.version());
|
|
74
92
|
const credentialEndpoint: string = this.credentialRequestOpts.credentialEndpoint;
|
|
75
93
|
if (!isValidURL(credentialEndpoint)) {
|
|
76
94
|
debug(`Invalid credential endpoint: ${credentialEndpoint}`);
|
|
77
95
|
throw new Error(URL_NOT_VALID);
|
|
78
96
|
}
|
|
79
97
|
debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
|
|
98
|
+
debug(`request\n: ${JSON.stringify(request, null, 2)}`);
|
|
80
99
|
const requestToken: string = this.credentialRequestOpts.token;
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
let response: OpenIDResponse<CredentialResponse> = await post(credentialEndpoint, JSON.stringify(request), { bearerToken: requestToken });
|
|
101
|
+
this._isDeferred = isDeferredCredentialResponse(response);
|
|
102
|
+
if (this.isDeferred() && this.credentialRequestOpts.deferredCredentialAwait && response.successBody) {
|
|
103
|
+
response = await this.acquireDeferredCredential(response.successBody, { bearerToken: this.credentialRequestOpts.token });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
debug(`Credential endpoint ${credentialEndpoint} response:\r\n${JSON.stringify(response, null, 2)}`);
|
|
83
107
|
return response;
|
|
84
108
|
}
|
|
85
109
|
|
|
110
|
+
public async acquireDeferredCredential(
|
|
111
|
+
response: Pick<CredentialResponse, 'transaction_id' | 'acceptance_token' | 'c_nonce'>,
|
|
112
|
+
opts?: {
|
|
113
|
+
bearerToken?: string;
|
|
114
|
+
},
|
|
115
|
+
): Promise<OpenIDResponse<CredentialResponse>> {
|
|
116
|
+
const transactionId = response.transaction_id;
|
|
117
|
+
const bearerToken = response.acceptance_token ?? opts?.bearerToken;
|
|
118
|
+
const deferredCredentialEndpoint = this.getDeferredCredentialEndpoint();
|
|
119
|
+
if (!deferredCredentialEndpoint) {
|
|
120
|
+
throw Error(`No deferred credential endpoint supplied.`);
|
|
121
|
+
} else if (!bearerToken) {
|
|
122
|
+
throw Error(`No bearer token present and refresh for defered endpoint not supported yet`);
|
|
123
|
+
// todo updated bearer token with new c_nonce
|
|
124
|
+
}
|
|
125
|
+
return await acquireDeferredCredential({
|
|
126
|
+
bearerToken,
|
|
127
|
+
transactionId,
|
|
128
|
+
deferredCredentialEndpoint,
|
|
129
|
+
deferredCredentialAwait: this.credentialRequestOpts.deferredCredentialAwait,
|
|
130
|
+
deferredCredentialIntervalInMS: this.credentialRequestOpts.deferredCredentialIntervalInMS,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
86
134
|
public async createCredentialRequest<DIDDoc>(opts: {
|
|
87
135
|
proofInput: ProofOfPossessionBuilder<DIDDoc> | ProofOfPossession;
|
|
88
136
|
credentialTypes?: string | string[];
|
|
137
|
+
context?: string[];
|
|
89
138
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
90
139
|
version: OpenId4VCIVersion;
|
|
91
140
|
}): Promise<UniformCredentialRequest> {
|
|
92
141
|
const { proofInput } = opts;
|
|
93
142
|
const formatSelection = opts.format ?? this.credentialRequestOpts.format;
|
|
94
143
|
|
|
95
|
-
|
|
96
|
-
if (opts.version < OpenId4VCIVersion.VER_1_0_11) {
|
|
97
|
-
if (formatSelection === 'jwt_vc' || formatSelection === 'jwt') {
|
|
98
|
-
format = 'jwt_vc_json';
|
|
99
|
-
} else if (formatSelection === 'ldp_vc' || formatSelection === 'ldp') {
|
|
100
|
-
format = 'jwt_vc_json-ld';
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!format) {
|
|
144
|
+
if (!formatSelection) {
|
|
105
145
|
throw Error(`Format of credential to be issued is missing`);
|
|
106
|
-
} else if (format !== 'jwt_vc_json-ld' && format !== 'jwt_vc_json' && format !== 'ldp_vc') {
|
|
107
|
-
throw Error(`Invalid format of credential to be issued: ${format}`);
|
|
108
146
|
}
|
|
147
|
+
const format = getUniformFormat(formatSelection);
|
|
109
148
|
const typesSelection =
|
|
110
149
|
opts?.credentialTypes && (typeof opts.credentialTypes === 'string' || opts.credentialTypes.length > 0)
|
|
111
150
|
? opts.credentialTypes
|
|
@@ -113,24 +152,56 @@ export class CredentialRequestClient {
|
|
|
113
152
|
const types = Array.isArray(typesSelection) ? typesSelection : [typesSelection];
|
|
114
153
|
if (types.length === 0) {
|
|
115
154
|
throw Error(`Credential type(s) need to be provided`);
|
|
116
|
-
}
|
|
155
|
+
}
|
|
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) {
|
|
117
158
|
throw Error('Only a single credential type is supported for V8/V9');
|
|
118
159
|
}
|
|
160
|
+
const proof = await buildProof(proofInput, opts);
|
|
161
|
+
|
|
162
|
+
// TODO: we should move format specific logic
|
|
163
|
+
if (format === 'jwt_vc_json' || format === 'jwt_vc') {
|
|
164
|
+
return {
|
|
165
|
+
types,
|
|
166
|
+
format,
|
|
167
|
+
proof,
|
|
168
|
+
};
|
|
169
|
+
} else if (format === 'jwt_vc_json-ld' || format === 'ldp_vc') {
|
|
170
|
+
if (this.version() >= OpenId4VCIVersion.VER_1_0_12 && !opts.context) {
|
|
171
|
+
throw Error('No @context value present, but it is required');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
format,
|
|
176
|
+
proof,
|
|
177
|
+
|
|
178
|
+
// Ignored because v11 does not have the context value, but it is required in v12
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
credential_definition: {
|
|
182
|
+
types,
|
|
183
|
+
...(opts.context && { '@context': opts.context }),
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
} else if (format === 'vc+sd-jwt') {
|
|
187
|
+
if (types.length > 1) {
|
|
188
|
+
throw Error(`Only a single credential type is supported for ${format}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
format,
|
|
193
|
+
proof,
|
|
194
|
+
vct: types[0],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
119
197
|
|
|
120
|
-
|
|
121
|
-
'proof_type' in proofInput
|
|
122
|
-
? await ProofOfPossessionBuilder.fromProof(proofInput as ProofOfPossession, opts.version).build()
|
|
123
|
-
: await proofInput.build();
|
|
124
|
-
return {
|
|
125
|
-
types,
|
|
126
|
-
format,
|
|
127
|
-
proof,
|
|
128
|
-
} as UniformCredentialRequest;
|
|
198
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
129
199
|
}
|
|
130
200
|
|
|
131
201
|
private version(): OpenId4VCIVersion {
|
|
132
202
|
return this.credentialRequestOpts?.version ?? OpenId4VCIVersion.VER_1_0_11;
|
|
133
203
|
}
|
|
204
|
+
|
|
134
205
|
private isV11OrHigher(): boolean {
|
|
135
206
|
return this.version() >= OpenId4VCIVersion.VER_1_0_11;
|
|
136
207
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
determineSpecVersionFromOffer,
|
|
7
7
|
EndpointMetadata,
|
|
8
8
|
getIssuerFromCredentialOfferPayload,
|
|
9
|
+
getTypesFromOffer,
|
|
9
10
|
OID4VCICredentialFormat,
|
|
10
11
|
OpenId4VCIVersion,
|
|
11
12
|
UniformCredentialOfferRequest,
|
|
@@ -17,11 +18,36 @@ import { CredentialRequestClient } from './CredentialRequestClient';
|
|
|
17
18
|
|
|
18
19
|
export class CredentialRequestClientBuilder {
|
|
19
20
|
credentialEndpoint?: string;
|
|
21
|
+
deferredCredentialEndpoint?: string;
|
|
22
|
+
deferredCredentialAwait = false;
|
|
23
|
+
deferredCredentialIntervalInMS = 5000;
|
|
20
24
|
credentialTypes: string[] = [];
|
|
21
25
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
22
26
|
token?: string;
|
|
23
27
|
version?: OpenId4VCIVersion;
|
|
24
28
|
|
|
29
|
+
public static fromCredentialIssuer({
|
|
30
|
+
credentialIssuer,
|
|
31
|
+
metadata,
|
|
32
|
+
version,
|
|
33
|
+
credentialTypes,
|
|
34
|
+
}: {
|
|
35
|
+
credentialIssuer: string;
|
|
36
|
+
metadata?: EndpointMetadata;
|
|
37
|
+
version?: OpenId4VCIVersion;
|
|
38
|
+
credentialTypes: string | string[];
|
|
39
|
+
}): CredentialRequestClientBuilder {
|
|
40
|
+
const issuer = credentialIssuer;
|
|
41
|
+
const builder = new CredentialRequestClientBuilder();
|
|
42
|
+
builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_11);
|
|
43
|
+
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
44
|
+
if (metadata?.deferred_credential_endpoint) {
|
|
45
|
+
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
46
|
+
}
|
|
47
|
+
builder.withCredentialType(credentialTypes);
|
|
48
|
+
return builder;
|
|
49
|
+
}
|
|
50
|
+
|
|
25
51
|
public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilder> {
|
|
26
52
|
const offer = await CredentialOfferClient.fromURI(uri);
|
|
27
53
|
return CredentialRequestClientBuilder.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
|
|
@@ -40,13 +66,16 @@ export class CredentialRequestClientBuilder {
|
|
|
40
66
|
const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
|
|
41
67
|
builder.withVersion(version);
|
|
42
68
|
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
69
|
+
if (metadata?.deferred_credential_endpoint) {
|
|
70
|
+
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
71
|
+
}
|
|
43
72
|
|
|
44
73
|
if (version <= OpenId4VCIVersion.VER_1_0_08) {
|
|
45
74
|
//todo: This basically sets all types available during initiation. Probably the user only wants a subset. So do we want to do this?
|
|
46
75
|
builder.withCredentialType((request.original_credential_offer as CredentialOfferPayloadV1_0_08).credential_type);
|
|
47
76
|
} else {
|
|
48
77
|
// todo: look whether this is correct
|
|
49
|
-
builder.withCredentialType(request.credential_offer
|
|
78
|
+
builder.withCredentialType(getTypesFromOffer(request.credential_offer));
|
|
50
79
|
}
|
|
51
80
|
|
|
52
81
|
return builder;
|
|
@@ -66,37 +95,53 @@ export class CredentialRequestClientBuilder {
|
|
|
66
95
|
});
|
|
67
96
|
}
|
|
68
97
|
|
|
69
|
-
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata):
|
|
98
|
+
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
|
|
70
99
|
this.credentialEndpoint = metadata.credential_endpoint;
|
|
71
100
|
return this;
|
|
72
101
|
}
|
|
73
102
|
|
|
74
|
-
public withCredentialEndpoint(credentialEndpoint: string):
|
|
103
|
+
public withCredentialEndpoint(credentialEndpoint: string): this {
|
|
75
104
|
this.credentialEndpoint = credentialEndpoint;
|
|
76
105
|
return this;
|
|
77
106
|
}
|
|
78
107
|
|
|
79
|
-
public
|
|
108
|
+
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata): this {
|
|
109
|
+
this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
|
|
114
|
+
this.deferredCredentialEndpoint = deferredCredentialEndpoint;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
|
|
119
|
+
this.deferredCredentialAwait = deferredCredentialAwait;
|
|
120
|
+
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public withCredentialType(credentialTypes: string | string[]): this {
|
|
80
125
|
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
|
|
81
126
|
return this;
|
|
82
127
|
}
|
|
83
128
|
|
|
84
|
-
public withFormat(format: CredentialFormat | OID4VCICredentialFormat):
|
|
129
|
+
public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
|
|
85
130
|
this.format = format;
|
|
86
131
|
return this;
|
|
87
132
|
}
|
|
88
133
|
|
|
89
|
-
public withToken(accessToken: string):
|
|
134
|
+
public withToken(accessToken: string): this {
|
|
90
135
|
this.token = accessToken;
|
|
91
136
|
return this;
|
|
92
137
|
}
|
|
93
138
|
|
|
94
|
-
public withTokenFromResponse(response: AccessTokenResponse):
|
|
139
|
+
public withTokenFromResponse(response: AccessTokenResponse): this {
|
|
95
140
|
this.token = response.access_token;
|
|
96
141
|
return this;
|
|
97
142
|
}
|
|
98
143
|
|
|
99
|
-
public withVersion(version: OpenId4VCIVersion):
|
|
144
|
+
public withVersion(version: OpenId4VCIVersion): this {
|
|
100
145
|
this.version = version;
|
|
101
146
|
return this;
|
|
102
147
|
}
|
package/lib/MetadataClient.ts
CHANGED
|
@@ -45,6 +45,7 @@ export class MetadataClient {
|
|
|
45
45
|
public static async retrieveAllMetadata(issuer: string, opts?: { errorOnNotFound: boolean }): Promise<EndpointMetadataResult> {
|
|
46
46
|
let token_endpoint: string | undefined;
|
|
47
47
|
let credential_endpoint: string | undefined;
|
|
48
|
+
let deferred_credential_endpoint: string | undefined;
|
|
48
49
|
let authorization_endpoint: string | undefined;
|
|
49
50
|
let authorizationServerType: AuthorizationServerType = 'OID4VCI';
|
|
50
51
|
let authorization_server: string = issuer;
|
|
@@ -53,6 +54,7 @@ export class MetadataClient {
|
|
|
53
54
|
if (credentialIssuerMetadata) {
|
|
54
55
|
debug(`Issuer ${issuer} OID4VCI well-known server metadata\r\n${JSON.stringify(credentialIssuerMetadata)}`);
|
|
55
56
|
credential_endpoint = credentialIssuerMetadata.credential_endpoint;
|
|
57
|
+
deferred_credential_endpoint = credentialIssuerMetadata.deferred_credential_endpoint;
|
|
56
58
|
if (credentialIssuerMetadata.token_endpoint) {
|
|
57
59
|
token_endpoint = credentialIssuerMetadata.token_endpoint;
|
|
58
60
|
}
|
|
@@ -111,12 +113,21 @@ export class MetadataClient {
|
|
|
111
113
|
if (authMetadata.credential_endpoint) {
|
|
112
114
|
if (credential_endpoint && authMetadata.credential_endpoint !== credential_endpoint) {
|
|
113
115
|
debug(
|
|
114
|
-
`Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.
|
|
116
|
+
`Credential issuer has a different credential_endpoint (${credential_endpoint}) from the Authorization Server (${authMetadata.credential_endpoint}). Will use the issuer value`,
|
|
115
117
|
);
|
|
116
118
|
} else {
|
|
117
119
|
credential_endpoint = authMetadata.credential_endpoint;
|
|
118
120
|
}
|
|
119
121
|
}
|
|
122
|
+
if (authMetadata.deferred_credential_endpoint) {
|
|
123
|
+
if (deferred_credential_endpoint && authMetadata.deferred_credential_endpoint !== deferred_credential_endpoint) {
|
|
124
|
+
debug(
|
|
125
|
+
`Credential issuer has a different deferred_credential_endpoint (${deferred_credential_endpoint}) from the Authorization Server (${authMetadata.deferred_credential_endpoint}). Will use the issuer value`,
|
|
126
|
+
);
|
|
127
|
+
} else {
|
|
128
|
+
deferred_credential_endpoint = authMetadata.deferred_credential_endpoint;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
if (!authorization_endpoint) {
|
|
@@ -148,6 +159,7 @@ export class MetadataClient {
|
|
|
148
159
|
issuer,
|
|
149
160
|
token_endpoint,
|
|
150
161
|
credential_endpoint,
|
|
162
|
+
deferred_credential_endpoint,
|
|
151
163
|
authorization_server,
|
|
152
164
|
authorization_endpoint,
|
|
153
165
|
authorizationServerType,
|