@sphereon/oid4vci-client 0.12.1-next.2 → 0.12.1-next.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AccessTokenClient.d.ts.map +1 -1
- package/dist/AccessTokenClient.js +7 -5
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -1
- package/dist/AccessTokenClientV1_0_11.js +7 -5
- package/dist/AccessTokenClientV1_0_11.js.map +1 -1
- package/dist/CredentialRequestClient.d.ts +3 -2
- package/dist/CredentialRequestClient.d.ts.map +1 -1
- package/dist/CredentialRequestClient.js.map +1 -1
- package/dist/CredentialRequestClientBuilder.d.ts +7 -15
- package/dist/CredentialRequestClientBuilder.d.ts.map +1 -1
- package/dist/CredentialRequestClientBuilder.js +79 -55
- package/dist/CredentialRequestClientBuilder.js.map +1 -1
- package/dist/CredentialRequestClientBuilderV1_0_13.d.ts +51 -0
- package/dist/CredentialRequestClientBuilderV1_0_13.d.ts.map +1 -0
- package/dist/CredentialRequestClientBuilderV1_0_13.js +130 -0
- package/dist/CredentialRequestClientBuilderV1_0_13.js.map +1 -0
- package/dist/OpenID4VCIClient.d.ts +3 -1
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +31 -16
- package/dist/OpenID4VCIClient.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts +3 -2
- package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.js +26 -10
- package/dist/OpenID4VCIClientV1_0_11.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_13.d.ts +2 -1
- package/dist/OpenID4VCIClientV1_0_13.d.ts.map +1 -1
- package/dist/OpenID4VCIClientV1_0_13.js +26 -12
- package/dist/OpenID4VCIClientV1_0_13.js.map +1 -1
- package/dist/functions/AccessTokenUtil.d.ts +5 -0
- package/dist/functions/AccessTokenUtil.d.ts.map +1 -0
- package/dist/functions/AccessTokenUtil.js +55 -0
- package/dist/functions/AccessTokenUtil.js.map +1 -0
- package/dist/functions/index.d.ts +2 -0
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +2 -0
- package/dist/functions/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/lib/AccessTokenClient.ts +5 -4
- package/lib/AccessTokenClientV1_0_11.ts +6 -3
- package/lib/CredentialRequestClient.ts +3 -2
- package/lib/CredentialRequestClientBuilder.ts +98 -67
- package/lib/CredentialRequestClientBuilderV1_0_13.ts +173 -0
- package/lib/OpenID4VCIClient.ts +33 -6
- package/lib/OpenID4VCIClientV1_0_11.ts +32 -5
- package/lib/OpenID4VCIClientV1_0_13.ts +30 -5
- package/lib/__tests__/CredentialRequestClient.spec.ts +8 -13
- package/lib/__tests__/CredentialRequestClientBuilder.spec.ts +40 -2
- package/lib/__tests__/CredentialRequestClientV1_0_11.spec.ts +96 -0
- package/lib/__tests__/IT.spec.ts +148 -111
- package/lib/__tests__/MetadataMocks.ts +35 -0
- package/lib/__tests__/ProofOfPossessionBuilder.spec.ts +85 -0
- package/lib/__tests__/SdJwt.spec.ts +103 -0
- package/lib/functions/AccessTokenUtil.ts +45 -0
- package/lib/functions/index.ts +2 -0
- package/lib/index.ts +1 -0
- package/package.json +3 -3
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AccessTokenResponse,
|
|
3
|
+
CredentialIssuerMetadata,
|
|
3
4
|
CredentialIssuerMetadataV1_0_13,
|
|
4
|
-
CredentialOfferPayloadV1_0_13,
|
|
5
5
|
CredentialOfferRequestWithBaseUrl,
|
|
6
6
|
determineSpecVersionFromOffer,
|
|
7
7
|
EndpointMetadata,
|
|
8
8
|
ExperimentalSubjectIssuance,
|
|
9
|
-
getIssuerFromCredentialOfferPayload,
|
|
10
9
|
OID4VCICredentialFormat,
|
|
11
10
|
OpenId4VCIVersion,
|
|
12
11
|
UniformCredentialOfferRequest,
|
|
@@ -14,19 +13,21 @@ import {
|
|
|
14
13
|
import { CredentialFormat } from '@sphereon/ssi-types';
|
|
15
14
|
|
|
16
15
|
import { CredentialOfferClient } from './CredentialOfferClient';
|
|
17
|
-
import {
|
|
16
|
+
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
|
|
17
|
+
import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
|
|
18
|
+
|
|
19
|
+
type CredentialRequestClientBuilderVersionSpecific = CredentialRequestClientBuilderV1_0_11 | CredentialRequestClientBuilderV1_0_13;
|
|
20
|
+
|
|
21
|
+
function isV1_0_13(builder: CredentialRequestClientBuilderVersionSpecific): builder is CredentialRequestClientBuilderV1_0_13 {
|
|
22
|
+
return (builder as CredentialRequestClientBuilderV1_0_13).withCredentialIdentifier !== undefined;
|
|
23
|
+
}
|
|
18
24
|
|
|
19
25
|
export class CredentialRequestClientBuilder {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
credentialTypes?: string[] = [];
|
|
26
|
-
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
27
|
-
token?: string;
|
|
28
|
-
version?: OpenId4VCIVersion;
|
|
29
|
-
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
26
|
+
private _builder: CredentialRequestClientBuilderVersionSpecific;
|
|
27
|
+
|
|
28
|
+
private constructor(builder: CredentialRequestClientBuilderVersionSpecific) {
|
|
29
|
+
this._builder = builder;
|
|
30
|
+
}
|
|
30
31
|
|
|
31
32
|
public static fromCredentialIssuer({
|
|
32
33
|
credentialIssuer,
|
|
@@ -41,25 +42,40 @@ export class CredentialRequestClientBuilder {
|
|
|
41
42
|
credentialIdentifier?: string;
|
|
42
43
|
credentialTypes?: string | string[];
|
|
43
44
|
}): CredentialRequestClientBuilder {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
const specVersion = version ?? OpenId4VCIVersion.VER_1_0_13;
|
|
46
|
+
let builder;
|
|
47
|
+
|
|
48
|
+
if (specVersion >= OpenId4VCIVersion.VER_1_0_13) {
|
|
49
|
+
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
|
|
50
|
+
credentialIssuer,
|
|
51
|
+
metadata,
|
|
52
|
+
version,
|
|
53
|
+
credentialIdentifier,
|
|
54
|
+
credentialTypes,
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
if (!credentialTypes || credentialTypes.length === 0) {
|
|
58
|
+
throw new Error('CredentialTypes must be provided for v1_0_11');
|
|
59
|
+
}
|
|
60
|
+
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialIssuer({
|
|
61
|
+
credentialIssuer,
|
|
62
|
+
metadata,
|
|
63
|
+
version,
|
|
64
|
+
credentialTypes,
|
|
65
|
+
});
|
|
56
66
|
}
|
|
57
|
-
|
|
67
|
+
|
|
68
|
+
return new CredentialRequestClientBuilder(builder);
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilder> {
|
|
61
72
|
const offer = await CredentialOfferClient.fromURI(uri);
|
|
62
|
-
return CredentialRequestClientBuilder.fromCredentialOfferRequest({
|
|
73
|
+
return CredentialRequestClientBuilder.fromCredentialOfferRequest({
|
|
74
|
+
request: offer,
|
|
75
|
+
...offer,
|
|
76
|
+
metadata,
|
|
77
|
+
version: offer.version,
|
|
78
|
+
});
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
public static fromCredentialOfferRequest(opts: {
|
|
@@ -69,24 +85,17 @@ export class CredentialRequestClientBuilder {
|
|
|
69
85
|
version?: OpenId4VCIVersion;
|
|
70
86
|
metadata?: EndpointMetadata;
|
|
71
87
|
}): CredentialRequestClientBuilder {
|
|
72
|
-
const { request
|
|
88
|
+
const { request } = opts;
|
|
73
89
|
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
|
|
90
|
+
let builder;
|
|
91
|
+
|
|
74
92
|
if (version < OpenId4VCIVersion.VER_1_0_13) {
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
|
|
79
|
-
builder.withVersion(version);
|
|
80
|
-
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
81
|
-
if (metadata?.deferred_credential_endpoint) {
|
|
82
|
-
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
83
|
-
}
|
|
84
|
-
const ids: string[] = (request.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids;
|
|
85
|
-
// if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
|
|
86
|
-
if (ids.length && ids.length === 1) {
|
|
87
|
-
builder.withCredentialIdentifier(ids[0]);
|
|
93
|
+
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOfferRequest(opts);
|
|
94
|
+
} else {
|
|
95
|
+
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest(opts);
|
|
88
96
|
}
|
|
89
|
-
|
|
97
|
+
|
|
98
|
+
return new CredentialRequestClientBuilder(builder);
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
public static fromCredentialOffer({
|
|
@@ -96,78 +105,100 @@ export class CredentialRequestClientBuilder {
|
|
|
96
105
|
credentialOffer: CredentialOfferRequestWithBaseUrl;
|
|
97
106
|
metadata?: EndpointMetadata;
|
|
98
107
|
}): CredentialRequestClientBuilder {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
108
|
+
const version = determineSpecVersionFromOffer(credentialOffer.credential_offer);
|
|
109
|
+
let builder;
|
|
110
|
+
|
|
111
|
+
if (version < OpenId4VCIVersion.VER_1_0_13) {
|
|
112
|
+
builder = CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
|
|
113
|
+
credentialOffer,
|
|
114
|
+
metadata,
|
|
115
|
+
});
|
|
116
|
+
} else {
|
|
117
|
+
builder = CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
|
|
118
|
+
credentialOffer,
|
|
119
|
+
metadata,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return new CredentialRequestClientBuilder(builder);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public getVersion(): OpenId4VCIVersion | undefined {
|
|
127
|
+
return this._builder.version;
|
|
104
128
|
}
|
|
105
129
|
|
|
106
|
-
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
107
|
-
this.
|
|
130
|
+
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13): this {
|
|
131
|
+
if (isV1_0_13(this._builder)) {
|
|
132
|
+
this._builder.withCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadataV1_0_13);
|
|
133
|
+
} else {
|
|
134
|
+
this._builder.withCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadata);
|
|
135
|
+
}
|
|
108
136
|
return this;
|
|
109
137
|
}
|
|
110
138
|
|
|
111
139
|
public withCredentialEndpoint(credentialEndpoint: string): this {
|
|
112
|
-
this.credentialEndpoint
|
|
140
|
+
this._builder.withCredentialEndpoint(credentialEndpoint);
|
|
113
141
|
return this;
|
|
114
142
|
}
|
|
115
143
|
|
|
116
|
-
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
117
|
-
this.
|
|
144
|
+
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadata | CredentialIssuerMetadataV1_0_13): this {
|
|
145
|
+
if (isV1_0_13(this._builder)) {
|
|
146
|
+
this._builder.withDeferredCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadataV1_0_13);
|
|
147
|
+
} else {
|
|
148
|
+
this._builder.withDeferredCredentialEndpointFromMetadata(metadata as CredentialIssuerMetadata);
|
|
149
|
+
}
|
|
118
150
|
return this;
|
|
119
151
|
}
|
|
120
152
|
|
|
121
153
|
public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
|
|
122
|
-
this.deferredCredentialEndpoint
|
|
154
|
+
this._builder.withDeferredCredentialEndpoint(deferredCredentialEndpoint);
|
|
123
155
|
return this;
|
|
124
156
|
}
|
|
125
157
|
|
|
126
158
|
public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
|
|
127
|
-
this.deferredCredentialAwait
|
|
128
|
-
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
|
|
159
|
+
this._builder.withDeferredCredentialAwait(deferredCredentialAwait, deferredCredentialIntervalInMS);
|
|
129
160
|
return this;
|
|
130
161
|
}
|
|
131
162
|
|
|
132
163
|
public withCredentialIdentifier(credentialIdentifier: string): this {
|
|
133
|
-
this.
|
|
164
|
+
if (this._builder.version === undefined || this._builder.version < OpenId4VCIVersion.VER_1_0_13) {
|
|
165
|
+
throw new Error('Version of spec should be equal or higher than v1_0_13');
|
|
166
|
+
}
|
|
167
|
+
(this._builder as CredentialRequestClientBuilderV1_0_13).withCredentialIdentifier(credentialIdentifier);
|
|
134
168
|
return this;
|
|
135
169
|
}
|
|
136
170
|
|
|
137
171
|
public withCredentialType(credentialTypes: string | string[]): this {
|
|
138
|
-
this.
|
|
172
|
+
this._builder.withCredentialType(credentialTypes);
|
|
139
173
|
return this;
|
|
140
174
|
}
|
|
141
175
|
|
|
142
176
|
public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
|
|
143
|
-
this.format
|
|
177
|
+
this._builder.withFormat(format);
|
|
144
178
|
return this;
|
|
145
179
|
}
|
|
146
180
|
|
|
147
181
|
public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
|
|
148
|
-
this.subjectIssuance
|
|
182
|
+
this._builder.withSubjectIssuance(subjectIssuance);
|
|
149
183
|
return this;
|
|
150
184
|
}
|
|
151
185
|
|
|
152
186
|
public withToken(accessToken: string): this {
|
|
153
|
-
this.
|
|
187
|
+
this._builder.withToken(accessToken);
|
|
154
188
|
return this;
|
|
155
189
|
}
|
|
156
190
|
|
|
157
191
|
public withTokenFromResponse(response: AccessTokenResponse): this {
|
|
158
|
-
this.
|
|
192
|
+
this._builder.withTokenFromResponse(response);
|
|
159
193
|
return this;
|
|
160
194
|
}
|
|
161
195
|
|
|
162
196
|
public withVersion(version: OpenId4VCIVersion): this {
|
|
163
|
-
this.version
|
|
197
|
+
this._builder.withVersion(version);
|
|
164
198
|
return this;
|
|
165
199
|
}
|
|
166
200
|
|
|
167
|
-
public build()
|
|
168
|
-
|
|
169
|
-
this.withVersion(OpenId4VCIVersion.VER_1_0_11);
|
|
170
|
-
}
|
|
171
|
-
return new CredentialRequestClient(this);
|
|
201
|
+
public build() {
|
|
202
|
+
return this._builder.build();
|
|
172
203
|
}
|
|
173
204
|
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AccessTokenResponse,
|
|
3
|
+
CredentialIssuerMetadataV1_0_13,
|
|
4
|
+
CredentialOfferPayloadV1_0_13,
|
|
5
|
+
CredentialOfferRequestWithBaseUrl,
|
|
6
|
+
determineSpecVersionFromOffer,
|
|
7
|
+
EndpointMetadata,
|
|
8
|
+
ExperimentalSubjectIssuance,
|
|
9
|
+
getIssuerFromCredentialOfferPayload,
|
|
10
|
+
OID4VCICredentialFormat,
|
|
11
|
+
OpenId4VCIVersion,
|
|
12
|
+
UniformCredentialOfferRequest,
|
|
13
|
+
} from '@sphereon/oid4vci-common';
|
|
14
|
+
import { CredentialFormat } from '@sphereon/ssi-types';
|
|
15
|
+
|
|
16
|
+
import { CredentialOfferClient } from './CredentialOfferClient';
|
|
17
|
+
import { CredentialRequestClient } from './CredentialRequestClient';
|
|
18
|
+
|
|
19
|
+
export class CredentialRequestClientBuilderV1_0_13 {
|
|
20
|
+
credentialEndpoint?: string;
|
|
21
|
+
deferredCredentialEndpoint?: string;
|
|
22
|
+
deferredCredentialAwait = false;
|
|
23
|
+
deferredCredentialIntervalInMS = 5000;
|
|
24
|
+
credentialIdentifier?: string;
|
|
25
|
+
credentialTypes?: string[] = [];
|
|
26
|
+
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
27
|
+
token?: string;
|
|
28
|
+
version?: OpenId4VCIVersion;
|
|
29
|
+
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
30
|
+
|
|
31
|
+
public static fromCredentialIssuer({
|
|
32
|
+
credentialIssuer,
|
|
33
|
+
metadata,
|
|
34
|
+
version,
|
|
35
|
+
credentialIdentifier,
|
|
36
|
+
credentialTypes,
|
|
37
|
+
}: {
|
|
38
|
+
credentialIssuer: string;
|
|
39
|
+
metadata?: EndpointMetadata;
|
|
40
|
+
version?: OpenId4VCIVersion;
|
|
41
|
+
credentialIdentifier?: string;
|
|
42
|
+
credentialTypes?: string | string[];
|
|
43
|
+
}): CredentialRequestClientBuilderV1_0_13 {
|
|
44
|
+
const issuer = credentialIssuer;
|
|
45
|
+
const builder = new CredentialRequestClientBuilderV1_0_13();
|
|
46
|
+
builder.withVersion(version ?? OpenId4VCIVersion.VER_1_0_13);
|
|
47
|
+
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
48
|
+
if (metadata?.deferred_credential_endpoint) {
|
|
49
|
+
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
50
|
+
}
|
|
51
|
+
if (credentialIdentifier) {
|
|
52
|
+
builder.withCredentialIdentifier(credentialIdentifier);
|
|
53
|
+
}
|
|
54
|
+
if (credentialTypes) {
|
|
55
|
+
builder.withCredentialType(credentialTypes);
|
|
56
|
+
}
|
|
57
|
+
return builder;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static async fromURI({ uri, metadata }: { uri: string; metadata?: EndpointMetadata }): Promise<CredentialRequestClientBuilderV1_0_13> {
|
|
61
|
+
const offer = await CredentialOfferClient.fromURI(uri);
|
|
62
|
+
return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({ request: offer, ...offer, metadata, version: offer.version });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public static fromCredentialOfferRequest(opts: {
|
|
66
|
+
request: UniformCredentialOfferRequest;
|
|
67
|
+
scheme?: string;
|
|
68
|
+
baseUrl?: string;
|
|
69
|
+
version?: OpenId4VCIVersion;
|
|
70
|
+
metadata?: EndpointMetadata;
|
|
71
|
+
}): CredentialRequestClientBuilderV1_0_13 {
|
|
72
|
+
const { request, metadata } = opts;
|
|
73
|
+
const version = opts.version ?? request.version ?? determineSpecVersionFromOffer(request.original_credential_offer);
|
|
74
|
+
if (version < OpenId4VCIVersion.VER_1_0_13) {
|
|
75
|
+
throw new Error('Versions below v1.0.13 (draft 13) are not supported.');
|
|
76
|
+
}
|
|
77
|
+
const builder = new CredentialRequestClientBuilderV1_0_13();
|
|
78
|
+
const issuer = getIssuerFromCredentialOfferPayload(request.credential_offer) ?? (metadata?.issuer as string);
|
|
79
|
+
builder.withVersion(version);
|
|
80
|
+
builder.withCredentialEndpoint(metadata?.credential_endpoint ?? (issuer.endsWith('/') ? `${issuer}credential` : `${issuer}/credential`));
|
|
81
|
+
if (metadata?.deferred_credential_endpoint) {
|
|
82
|
+
builder.withDeferredCredentialEndpoint(metadata.deferred_credential_endpoint);
|
|
83
|
+
}
|
|
84
|
+
const ids: string[] = (request.credential_offer as CredentialOfferPayloadV1_0_13).credential_configuration_ids;
|
|
85
|
+
// if there's only one in the offer, we pre-select it. if not, you should provide the credentialType
|
|
86
|
+
if (ids.length && ids.length === 1) {
|
|
87
|
+
builder.withCredentialIdentifier(ids[0]);
|
|
88
|
+
}
|
|
89
|
+
return builder;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public static fromCredentialOffer({
|
|
93
|
+
credentialOffer,
|
|
94
|
+
metadata,
|
|
95
|
+
}: {
|
|
96
|
+
credentialOffer: CredentialOfferRequestWithBaseUrl;
|
|
97
|
+
metadata?: EndpointMetadata;
|
|
98
|
+
}): CredentialRequestClientBuilderV1_0_13 {
|
|
99
|
+
return CredentialRequestClientBuilderV1_0_13.fromCredentialOfferRequest({
|
|
100
|
+
request: credentialOffer,
|
|
101
|
+
metadata,
|
|
102
|
+
version: credentialOffer.version,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public withCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
107
|
+
this.credentialEndpoint = metadata.credential_endpoint;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public withCredentialEndpoint(credentialEndpoint: string): this {
|
|
112
|
+
this.credentialEndpoint = credentialEndpoint;
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public withDeferredCredentialEndpointFromMetadata(metadata: CredentialIssuerMetadataV1_0_13): this {
|
|
117
|
+
this.deferredCredentialEndpoint = metadata.deferred_credential_endpoint;
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public withDeferredCredentialEndpoint(deferredCredentialEndpoint: string): this {
|
|
122
|
+
this.deferredCredentialEndpoint = deferredCredentialEndpoint;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public withDeferredCredentialAwait(deferredCredentialAwait: boolean, deferredCredentialIntervalInMS?: number): this {
|
|
127
|
+
this.deferredCredentialAwait = deferredCredentialAwait;
|
|
128
|
+
this.deferredCredentialIntervalInMS = deferredCredentialIntervalInMS ?? 5000;
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public withCredentialIdentifier(credentialIdentifier: string): this {
|
|
133
|
+
this.credentialIdentifier = credentialIdentifier;
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public withCredentialType(credentialTypes: string | string[]): this {
|
|
138
|
+
this.credentialTypes = Array.isArray(credentialTypes) ? credentialTypes : [credentialTypes];
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public withFormat(format: CredentialFormat | OID4VCICredentialFormat): this {
|
|
143
|
+
this.format = format;
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public withSubjectIssuance(subjectIssuance: ExperimentalSubjectIssuance): this {
|
|
148
|
+
this.subjectIssuance = subjectIssuance;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public withToken(accessToken: string): this {
|
|
153
|
+
this.token = accessToken;
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public withTokenFromResponse(response: AccessTokenResponse): this {
|
|
158
|
+
this.token = response.access_token;
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public withVersion(version: OpenId4VCIVersion): this {
|
|
163
|
+
this.version = version;
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public build(): CredentialRequestClient {
|
|
168
|
+
if (!this.version) {
|
|
169
|
+
this.withVersion(OpenId4VCIVersion.VER_1_0_11);
|
|
170
|
+
}
|
|
171
|
+
return new CredentialRequestClient(this);
|
|
172
|
+
}
|
|
173
|
+
}
|
package/lib/OpenID4VCIClient.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Alg,
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationResponse,
|
|
6
|
+
AuthorizationServerOpts,
|
|
6
7
|
AuthzFlowType,
|
|
7
8
|
CodeChallengeMethod,
|
|
8
9
|
CredentialConfigurationSupported,
|
|
@@ -41,8 +42,8 @@ import { createAuthorizationRequestUrl } from './AuthorizationCodeClient';
|
|
|
41
42
|
import { createAuthorizationRequestUrlV1_0_11 } from './AuthorizationCodeClientV1_0_11';
|
|
42
43
|
import { CredentialOfferClient } from './CredentialOfferClient';
|
|
43
44
|
import { CredentialRequestOpts } from './CredentialRequestClient';
|
|
44
|
-
import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder';
|
|
45
45
|
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
|
|
46
|
+
import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
|
|
46
47
|
import { MetadataClient } from './MetadataClient';
|
|
47
48
|
import { OpenID4VCIClientStateV1_0_11 } from './OpenID4VCIClientV1_0_11';
|
|
48
49
|
import { OpenID4VCIClientStateV1_0_13 } from './OpenID4VCIClientV1_0_13';
|
|
@@ -273,8 +274,10 @@ export class OpenID4VCIClient {
|
|
|
273
274
|
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
274
275
|
code?: string; // Directly pass in a code from an auth response
|
|
275
276
|
redirectUri?: string;
|
|
277
|
+
additionalRequestParams?: Record<string, any>;
|
|
278
|
+
asOpts?: AuthorizationServerOpts;
|
|
276
279
|
}): Promise<AccessTokenResponse> {
|
|
277
|
-
const { pin, clientId } = opts ?? {};
|
|
280
|
+
const { pin, clientId = this._state.clientId ?? this._state.authorizationRequestOpts?.clientId } = opts ?? {};
|
|
278
281
|
let { redirectUri } = opts ?? {};
|
|
279
282
|
if (opts?.authorizationResponse) {
|
|
280
283
|
this._state.authorizationCodeResponse = { ...toAuthorizationResponsePayload(opts.authorizationResponse) };
|
|
@@ -288,6 +291,26 @@ export class OpenID4VCIClient {
|
|
|
288
291
|
}
|
|
289
292
|
this.assertIssuerData();
|
|
290
293
|
|
|
294
|
+
const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
|
|
295
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
296
|
+
const clientAssertionType =
|
|
297
|
+
asOpts.clientOpts?.clientAssertionType ??
|
|
298
|
+
(kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
|
|
299
|
+
? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
300
|
+
: undefined);
|
|
301
|
+
if (this.isEBSI() || (clientId && kid)) {
|
|
302
|
+
if (!clientId) {
|
|
303
|
+
throw Error(`Client id expected for EBSI`);
|
|
304
|
+
}
|
|
305
|
+
asOpts.clientOpts = {
|
|
306
|
+
...asOpts.clientOpts,
|
|
307
|
+
clientId,
|
|
308
|
+
...(kid && { kid }),
|
|
309
|
+
...(clientAssertionType && { clientAssertionType }),
|
|
310
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
291
314
|
if (clientId) {
|
|
292
315
|
this._state.clientId = clientId;
|
|
293
316
|
}
|
|
@@ -311,7 +334,8 @@ export class OpenID4VCIClient {
|
|
|
311
334
|
...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
|
|
312
335
|
code,
|
|
313
336
|
redirectUri,
|
|
314
|
-
asOpts
|
|
337
|
+
asOpts,
|
|
338
|
+
...(opts?.additionalRequestParams && { additionalParams: opts.additionalRequestParams }),
|
|
315
339
|
});
|
|
316
340
|
|
|
317
341
|
if (response.errorBody) {
|
|
@@ -368,7 +392,7 @@ export class OpenID4VCIClient {
|
|
|
368
392
|
if (jwk) this._state.jwk = jwk;
|
|
369
393
|
if (kid) this._state.kid = kid;
|
|
370
394
|
|
|
371
|
-
let requestBuilder:
|
|
395
|
+
let requestBuilder: CredentialRequestClientBuilderV1_0_13 | CredentialRequestClientBuilderV1_0_11;
|
|
372
396
|
if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
|
|
373
397
|
requestBuilder = this.credentialOffer
|
|
374
398
|
? CredentialRequestClientBuilderV1_0_11.fromCredentialOffer({
|
|
@@ -383,11 +407,11 @@ export class OpenID4VCIClient {
|
|
|
383
407
|
});
|
|
384
408
|
} else {
|
|
385
409
|
requestBuilder = this.credentialOffer
|
|
386
|
-
?
|
|
410
|
+
? CredentialRequestClientBuilderV1_0_13.fromCredentialOffer({
|
|
387
411
|
credentialOffer: this.credentialOffer,
|
|
388
412
|
metadata: this.endpointMetadata,
|
|
389
413
|
})
|
|
390
|
-
:
|
|
414
|
+
: CredentialRequestClientBuilderV1_0_13.fromCredentialIssuer({
|
|
391
415
|
credentialIssuer: this.getIssuer(),
|
|
392
416
|
credentialTypes,
|
|
393
417
|
metadata: this.endpointMetadata,
|
|
@@ -646,6 +670,9 @@ export class OpenID4VCIClient {
|
|
|
646
670
|
}
|
|
647
671
|
// this.assertIssuerData();
|
|
648
672
|
return (
|
|
673
|
+
this.clientId?.includes('ebsi') ||
|
|
674
|
+
this._state.kid?.includes('did:ebsi:') ||
|
|
675
|
+
this.getIssuer().includes('ebsi') ||
|
|
649
676
|
this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ||
|
|
650
677
|
this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes('ebsi.eu')
|
|
651
678
|
);
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Alg,
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationResponse,
|
|
6
|
+
AuthorizationServerOpts,
|
|
6
7
|
AuthzFlowType,
|
|
7
8
|
CodeChallengeMethod,
|
|
8
9
|
CredentialConfigurationSupported,
|
|
@@ -259,6 +260,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
259
260
|
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
260
261
|
code?: string; // Directly pass in a code from an auth response
|
|
261
262
|
redirectUri?: string;
|
|
263
|
+
asOpts?: AuthorizationServerOpts;
|
|
262
264
|
}): Promise<AccessTokenResponse> {
|
|
263
265
|
const { pin, clientId } = opts ?? {};
|
|
264
266
|
let { redirectUri } = opts ?? {};
|
|
@@ -288,6 +290,25 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
288
290
|
if (this._state.authorizationRequestOpts?.redirectUri && !redirectUri) {
|
|
289
291
|
redirectUri = this._state.authorizationRequestOpts.redirectUri;
|
|
290
292
|
}
|
|
293
|
+
const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
|
|
294
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
295
|
+
const clientAssertionType =
|
|
296
|
+
asOpts.clientOpts?.clientAssertionType ??
|
|
297
|
+
(kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
|
|
298
|
+
? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
299
|
+
: undefined);
|
|
300
|
+
if (this.isEBSI() || (clientId && kid)) {
|
|
301
|
+
if (!clientId) {
|
|
302
|
+
throw Error(`Client id expected for EBSI`);
|
|
303
|
+
}
|
|
304
|
+
asOpts.clientOpts = {
|
|
305
|
+
...asOpts.clientOpts,
|
|
306
|
+
clientId,
|
|
307
|
+
...(kid && { kid }),
|
|
308
|
+
...(clientAssertionType && { clientAssertionType }),
|
|
309
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
291
312
|
|
|
292
313
|
const response = await accessTokenClient.acquireAccessToken({
|
|
293
314
|
credentialOffer: this.credentialOffer,
|
|
@@ -297,7 +318,7 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
297
318
|
...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
|
|
298
319
|
code,
|
|
299
320
|
redirectUri,
|
|
300
|
-
asOpts
|
|
321
|
+
asOpts,
|
|
301
322
|
});
|
|
302
323
|
|
|
303
324
|
if (response.errorBody) {
|
|
@@ -584,8 +605,8 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
584
605
|
*/
|
|
585
606
|
public isEBSI() {
|
|
586
607
|
if (
|
|
587
|
-
|
|
588
|
-
(this.credentialOffer?.credential_offer as CredentialOfferPayloadV1_0_11)
|
|
608
|
+
this.credentialOffer &&
|
|
609
|
+
(this.credentialOffer?.credential_offer as CredentialOfferPayloadV1_0_11)?.credentials?.find(
|
|
589
610
|
(cred) =>
|
|
590
611
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
591
612
|
// @ts-ignore
|
|
@@ -594,8 +615,14 @@ export class OpenID4VCIClientV1_0_11 {
|
|
|
594
615
|
) {
|
|
595
616
|
return true;
|
|
596
617
|
}
|
|
597
|
-
this.assertIssuerData();
|
|
598
|
-
return
|
|
618
|
+
// this.assertIssuerData();
|
|
619
|
+
return (
|
|
620
|
+
this.clientId?.includes('ebsi') ||
|
|
621
|
+
this._state.kid?.includes('did:ebsi:') ||
|
|
622
|
+
this.getIssuer().includes('ebsi') ||
|
|
623
|
+
this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ||
|
|
624
|
+
this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes('ebsi.eu')
|
|
625
|
+
);
|
|
599
626
|
}
|
|
600
627
|
|
|
601
628
|
private assertIssuerData(): void {
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Alg,
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationResponse,
|
|
6
|
+
AuthorizationServerOpts,
|
|
6
7
|
AuthzFlowType,
|
|
7
8
|
CodeChallengeMethod,
|
|
8
9
|
CredentialConfigurationSupportedV1_0_13,
|
|
@@ -36,8 +37,7 @@ import { CredentialRequestOpts } from './CredentialRequestClient';
|
|
|
36
37
|
import { CredentialRequestClientBuilder } from './CredentialRequestClientBuilder';
|
|
37
38
|
import { MetadataClientV1_0_13 } from './MetadataClientV1_0_13';
|
|
38
39
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
39
|
-
import { generateMissingPKCEOpts } from './functions';
|
|
40
|
-
import { sendNotification } from './functions';
|
|
40
|
+
import { generateMissingPKCEOpts, sendNotification } from './functions';
|
|
41
41
|
|
|
42
42
|
const debug = Debug('sphereon:oid4vci');
|
|
43
43
|
|
|
@@ -265,6 +265,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
265
265
|
authorizationResponse?: string | AuthorizationResponse; // Pass in an auth response, either as URI/redirect, or object
|
|
266
266
|
code?: string; // Directly pass in a code from an auth response
|
|
267
267
|
redirectUri?: string;
|
|
268
|
+
asOpts?: AuthorizationServerOpts;
|
|
268
269
|
}): Promise<AccessTokenResponse> {
|
|
269
270
|
const { pin, clientId } = opts ?? {};
|
|
270
271
|
let { redirectUri } = opts ?? {};
|
|
@@ -279,6 +280,25 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
279
280
|
this._state.pkce.codeVerifier = opts.codeVerifier;
|
|
280
281
|
}
|
|
281
282
|
this.assertIssuerData();
|
|
283
|
+
const asOpts: AuthorizationServerOpts = { ...opts?.asOpts };
|
|
284
|
+
const kid = asOpts.clientOpts?.kid ?? this._state.kid ?? this._state.authorizationRequestOpts?.requestObjectOpts?.kid;
|
|
285
|
+
const clientAssertionType =
|
|
286
|
+
asOpts.clientOpts?.clientAssertionType ??
|
|
287
|
+
(kid && clientId && typeof asOpts.clientOpts?.signCallbacks === 'function'
|
|
288
|
+
? 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
289
|
+
: undefined);
|
|
290
|
+
if (this.isEBSI() || (clientId && kid)) {
|
|
291
|
+
if (!clientId) {
|
|
292
|
+
throw Error(`Client id expected for EBSI`);
|
|
293
|
+
}
|
|
294
|
+
asOpts.clientOpts = {
|
|
295
|
+
...asOpts.clientOpts,
|
|
296
|
+
clientId,
|
|
297
|
+
...(kid && { kid }),
|
|
298
|
+
...(clientAssertionType && { clientAssertionType }),
|
|
299
|
+
signCallbacks: asOpts.clientOpts?.signCallbacks ?? this._state.authorizationRequestOpts?.requestObjectOpts?.signCallbacks,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
282
302
|
|
|
283
303
|
if (clientId) {
|
|
284
304
|
this._state.clientId = clientId;
|
|
@@ -302,7 +322,7 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
302
322
|
...(!this._state.pkce.disabled && { codeVerifier: this._state.pkce.codeVerifier }),
|
|
303
323
|
code,
|
|
304
324
|
redirectUri,
|
|
305
|
-
asOpts
|
|
325
|
+
asOpts,
|
|
306
326
|
});
|
|
307
327
|
|
|
308
328
|
if (response.errorBody) {
|
|
@@ -636,8 +656,13 @@ export class OpenID4VCIClientV1_0_13 {
|
|
|
636
656
|
}
|
|
637
657
|
}
|
|
638
658
|
|
|
639
|
-
|
|
640
|
-
|
|
659
|
+
return (
|
|
660
|
+
this.clientId?.includes('ebsi') ||
|
|
661
|
+
this._state.kid?.includes('did:ebsi:') ||
|
|
662
|
+
this.getIssuer().includes('ebsi') ||
|
|
663
|
+
this.endpointMetadata.credentialIssuerMetadata?.authorization_endpoint?.includes('ebsi.eu') ||
|
|
664
|
+
this.endpointMetadata.credentialIssuerMetadata?.authorization_server?.includes('ebsi.eu')
|
|
665
|
+
);
|
|
641
666
|
}
|
|
642
667
|
|
|
643
668
|
private assertIssuerData(): void {
|