@sphereon/oid4vci-client 0.12.0 → 0.12.1-next.19
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.js +1 -1
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AccessTokenClientV1_0_11.js +1 -1
- package/dist/AccessTokenClientV1_0_11.js.map +1 -1
- package/dist/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/AuthorizationCodeClient.js +4 -1
- package/dist/AuthorizationCodeClient.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 +1 -0
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +5 -5
- package/dist/OpenID4VCIClient.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 +1 -1
- package/lib/AccessTokenClientV1_0_11.ts +1 -1
- package/lib/AuthorizationCodeClient.ts +7 -4
- package/lib/CredentialRequestClient.ts +3 -2
- package/lib/CredentialRequestClientBuilder.ts +98 -67
- package/lib/CredentialRequestClientBuilderV1_0_13.ts +173 -0
- package/lib/OpenID4VCIClient.ts +6 -4
- 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/index.ts +1 -0
- package/package.json +3 -3
|
@@ -12,8 +12,15 @@ const jwt: Jwt = {
|
|
|
12
12
|
payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL, iat: Date.now() / 1000 },
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const jwt_withoutDid: Jwt = {
|
|
16
|
+
header: { alg: Alg.ES256, kid: 'ebfeb1f712ebc6f1c276e12ec21/keys/1', typ: 'jwt' },
|
|
17
|
+
payload: { iss: 'sphereon:wallet', nonce: 'tZignsnFbp', jti: 'tZignsnFbp223', aud: IDENTIPROOF_ISSUER_URL, iat: Date.now() / 1000 },
|
|
18
|
+
};
|
|
19
|
+
|
|
15
20
|
const kid = 'did:example:ebfeb1f712ebc6f1c276e12ec21/keys/1';
|
|
16
21
|
|
|
22
|
+
const kid_withoutDid = 'ebfeb1f712ebc6f1c276e12ec21/keys/1';
|
|
23
|
+
|
|
17
24
|
let keypair: KeyPair;
|
|
18
25
|
|
|
19
26
|
async function proofOfPossessionCallbackFunction(args: Jwt, kid?: string): Promise<string> {
|
|
@@ -52,6 +59,16 @@ describe('ProofOfPossession Builder ', () => {
|
|
|
52
59
|
).rejects.toThrow(Error(PROOF_CANT_BE_CONSTRUCTED));
|
|
53
60
|
});
|
|
54
61
|
|
|
62
|
+
it('should fail without supplied proof or callbacks and with kid without did', async function () {
|
|
63
|
+
await expect(
|
|
64
|
+
ProofOfPossessionBuilder.fromProof(undefined as never, OpenId4VCIVersion.VER_1_0_13)
|
|
65
|
+
.withIssuer(IDENTIPROOF_ISSUER_URL)
|
|
66
|
+
.withClientId('sphereon:wallet')
|
|
67
|
+
.withKid(kid_withoutDid)
|
|
68
|
+
.build(),
|
|
69
|
+
).rejects.toThrow(Error(PROOF_CANT_BE_CONSTRUCTED));
|
|
70
|
+
});
|
|
71
|
+
|
|
55
72
|
it('should fail wit undefined jwt supplied', async function () {
|
|
56
73
|
await expect(() =>
|
|
57
74
|
ProofOfPossessionBuilder.fromJwt({ jwt, callbacks: { signCallback: proofOfPossessionCallbackFunction }, version: OpenId4VCIVersion.VER_1_0_08 })
|
|
@@ -63,6 +80,21 @@ describe('ProofOfPossession Builder ', () => {
|
|
|
63
80
|
).toThrow(Error(NO_JWT_PROVIDED));
|
|
64
81
|
});
|
|
65
82
|
|
|
83
|
+
it('should fail with undefined jwt supplied and kid without did', async function () {
|
|
84
|
+
await expect(() =>
|
|
85
|
+
ProofOfPossessionBuilder.fromJwt({
|
|
86
|
+
jwt: jwt_withoutDid,
|
|
87
|
+
callbacks: { signCallback: proofOfPossessionCallbackFunction },
|
|
88
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
89
|
+
})
|
|
90
|
+
.withJwt(undefined as never)
|
|
91
|
+
.withIssuer(IDENTIPROOF_ISSUER_URL)
|
|
92
|
+
.withClientId('sphereon:wallet')
|
|
93
|
+
.withKid(kid_withoutDid)
|
|
94
|
+
.build(),
|
|
95
|
+
).toThrow(Error(NO_JWT_PROVIDED));
|
|
96
|
+
});
|
|
97
|
+
|
|
66
98
|
it('should build a proof with all required params present', async function () {
|
|
67
99
|
const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
|
|
68
100
|
jwt,
|
|
@@ -78,6 +110,21 @@ describe('ProofOfPossession Builder ', () => {
|
|
|
78
110
|
expect(proof).toBeDefined();
|
|
79
111
|
});
|
|
80
112
|
|
|
113
|
+
it('should build a proof with all required params present without did', async function () {
|
|
114
|
+
const proof: ProofOfPossession = await ProofOfPossessionBuilder.fromJwt({
|
|
115
|
+
jwt: jwt_withoutDid,
|
|
116
|
+
callbacks: {
|
|
117
|
+
signCallback: proofOfPossessionCallbackFunction,
|
|
118
|
+
},
|
|
119
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
120
|
+
})
|
|
121
|
+
.withIssuer(IDENTIPROOF_ISSUER_URL)
|
|
122
|
+
.withKid(kid_withoutDid)
|
|
123
|
+
.withClientId('sphereon:wallet')
|
|
124
|
+
.build();
|
|
125
|
+
expect(proof).toBeDefined();
|
|
126
|
+
});
|
|
127
|
+
|
|
81
128
|
it('should fail creating a proof of possession with simple verification', async () => {
|
|
82
129
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
83
130
|
async function proofOfPossessionCallbackFunction(_args: Jwt, _kid?: string): Promise<string> {
|
|
@@ -93,6 +140,25 @@ describe('ProofOfPossession Builder ', () => {
|
|
|
93
140
|
).rejects.toThrow(Error(JWS_NOT_VALID));
|
|
94
141
|
});
|
|
95
142
|
|
|
143
|
+
it('should fail creating a proof of possession with simple verification and without did', async () => {
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
145
|
+
async function proofOfPossessionCallbackFunction(_args: Jwt, _kid?: string): Promise<string> {
|
|
146
|
+
throw new Error(JWS_NOT_VALID);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
await expect(
|
|
150
|
+
ProofOfPossessionBuilder.fromJwt({
|
|
151
|
+
jwt: jwt_withoutDid,
|
|
152
|
+
callbacks: { signCallback: proofOfPossessionCallbackFunction },
|
|
153
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
154
|
+
})
|
|
155
|
+
.withIssuer(IDENTIPROOF_ISSUER_URL)
|
|
156
|
+
.withClientId('sphereon:wallet')
|
|
157
|
+
.withKid(kid_withoutDid)
|
|
158
|
+
.build(),
|
|
159
|
+
).rejects.toThrow(Error(JWS_NOT_VALID));
|
|
160
|
+
});
|
|
161
|
+
|
|
96
162
|
it('should fail creating a proof of possession without verify callback', async () => {
|
|
97
163
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
98
164
|
async function proofOfPossessionCallbackFunction(_args: Jwt, _kid?: string): Promise<string> {
|
|
@@ -107,4 +173,23 @@ describe('ProofOfPossession Builder ', () => {
|
|
|
107
173
|
.build(),
|
|
108
174
|
).rejects.toThrow(Error(JWS_NOT_VALID));
|
|
109
175
|
});
|
|
176
|
+
|
|
177
|
+
it('should fail creating a proof of possession without verify callback and without did', async () => {
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
179
|
+
async function proofOfPossessionCallbackFunction(_args: Jwt, _kid?: string): Promise<string> {
|
|
180
|
+
throw new Error(JWS_NOT_VALID);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await expect(
|
|
184
|
+
ProofOfPossessionBuilder.fromJwt({
|
|
185
|
+
jwt: jwt_withoutDid,
|
|
186
|
+
callbacks: { signCallback: proofOfPossessionCallbackFunction },
|
|
187
|
+
version: OpenId4VCIVersion.VER_1_0_08,
|
|
188
|
+
})
|
|
189
|
+
.withIssuer(IDENTIPROOF_ISSUER_URL)
|
|
190
|
+
.withClientId('sphereon:wallet')
|
|
191
|
+
.withKid(kid_withoutDid)
|
|
192
|
+
.build(),
|
|
193
|
+
).rejects.toThrow(Error(JWS_NOT_VALID));
|
|
194
|
+
});
|
|
110
195
|
});
|
|
@@ -166,4 +166,107 @@ describe('sd-jwt vc', () => {
|
|
|
166
166
|
},
|
|
167
167
|
UNIT_TEST_TIMEOUT,
|
|
168
168
|
);
|
|
169
|
+
|
|
170
|
+
it(
|
|
171
|
+
'succeed with a full flow without did',
|
|
172
|
+
async () => {
|
|
173
|
+
const offerUri = await vcIssuer.createCredentialOfferURI({
|
|
174
|
+
grants: {
|
|
175
|
+
'urn:ietf:params:oauth:grant-type:pre-authorized_code': {
|
|
176
|
+
tx_code: {
|
|
177
|
+
input_mode: 'text',
|
|
178
|
+
length: 3,
|
|
179
|
+
},
|
|
180
|
+
'pre-authorized_code': '123',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
credential_configuration_ids: ['SdJwtCredential'],
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
nock(vcIssuer.issuerMetadata.credential_issuer).get('/.well-known/openid-credential-issuer').reply(200, JSON.stringify(issuerMetadata));
|
|
187
|
+
nock(vcIssuer.issuerMetadata.credential_issuer).get('/.well-known/openid-configuration').reply(404);
|
|
188
|
+
nock(vcIssuer.issuerMetadata.credential_issuer).get('/.well-known/oauth-authorization-server').reply(404);
|
|
189
|
+
|
|
190
|
+
expect(offerUri.uri).toEqual(
|
|
191
|
+
'openid-credential-offer://?credential_offer=%7B%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22123%22%2C%22tx_code%22%3A%7B%22input_mode%22%3A%22text%22%2C%22length%22%3A3%7D%7D%7D%2C%22credential_configuration_ids%22%3A%5B%22SdJwtCredential%22%5D%2C%22credential_issuer%22%3A%22https%3A%2F%2Fexample.com%22%7D',
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const client = await OpenID4VCIClientV1_0_13.fromURI({
|
|
195
|
+
uri: offerUri.uri,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expect(client.credentialOffer?.credential_offer).toEqual({
|
|
199
|
+
credential_issuer: 'https://example.com',
|
|
200
|
+
credential_configuration_ids: ['SdJwtCredential'],
|
|
201
|
+
grants: {
|
|
202
|
+
'urn:ietf:params:oauth:grant-type:pre-authorized_code': {
|
|
203
|
+
'pre-authorized_code': '123',
|
|
204
|
+
tx_code: {
|
|
205
|
+
input_mode: 'text',
|
|
206
|
+
length: 3,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const supported = client.getCredentialsSupported('vc+sd-jwt');
|
|
213
|
+
expect(supported).toEqual({ SdJwtCredentialId: { format: 'vc+sd-jwt', id: 'SdJwtCredentialId', vct: 'SdJwtCredentialId' } });
|
|
214
|
+
|
|
215
|
+
const offered = supported['SdJwtCredentialId'] as CredentialSupportedSdJwtVc;
|
|
216
|
+
|
|
217
|
+
nock(issuerMetadata.token_endpoint as string)
|
|
218
|
+
.post('/')
|
|
219
|
+
.reply(200, async (_, body: string) => {
|
|
220
|
+
const parsedBody = Object.fromEntries(body.split('&').map((x) => x.split('=')));
|
|
221
|
+
return createAccessTokenResponse(parsedBody as AccessTokenRequest, {
|
|
222
|
+
credentialOfferSessions: vcIssuer.credentialOfferSessions,
|
|
223
|
+
accessTokenIssuer: 'https://issuer.example.com',
|
|
224
|
+
cNonces: vcIssuer.cNonces,
|
|
225
|
+
cNonce: 'a-c-nonce',
|
|
226
|
+
accessTokenSignerCallback: async () => 'ey.val.ue',
|
|
227
|
+
tokenExpiresIn: 500,
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
await client.acquireAccessToken({ pin: '123' });
|
|
232
|
+
nock(issuerMetadata.credential_endpoint as string)
|
|
233
|
+
.post('/')
|
|
234
|
+
.reply(200, async (_, body) =>
|
|
235
|
+
vcIssuer.issueCredential({
|
|
236
|
+
credentialRequest: { ...(body as CredentialRequestV1_0_13), credential_identifier: offered.vct },
|
|
237
|
+
credential: {
|
|
238
|
+
vct: 'Hello',
|
|
239
|
+
iss: 'example.com',
|
|
240
|
+
iat: 123,
|
|
241
|
+
// Defines what can be disclosed (optional)
|
|
242
|
+
__disclosureFrame: {
|
|
243
|
+
name: true,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
newCNonce: 'new-c-nonce',
|
|
247
|
+
}),
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const credentials = await client.acquireCredentials({
|
|
251
|
+
credentialIdentifier: offered.vct,
|
|
252
|
+
// format: 'vc+sd-jwt',
|
|
253
|
+
alg,
|
|
254
|
+
jwk,
|
|
255
|
+
proofCallbacks: {
|
|
256
|
+
// When using sd-jwt for real, this jwt should include a jwk
|
|
257
|
+
signCallback: async () => 'ey.ja.ja',
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
expect(credentials).toEqual({
|
|
262
|
+
notification_id: expect.any(String),
|
|
263
|
+
access_token: 'ey.val.ue',
|
|
264
|
+
c_nonce: 'new-c-nonce',
|
|
265
|
+
c_nonce_expires_in: 300,
|
|
266
|
+
credential: 'sd-jwt',
|
|
267
|
+
// format: 'vc+sd-jwt',
|
|
268
|
+
});
|
|
269
|
+
},
|
|
270
|
+
UNIT_TEST_TIMEOUT,
|
|
271
|
+
);
|
|
169
272
|
});
|
package/lib/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from './CredentialOfferClientV1_0_11';
|
|
|
13
13
|
export * from './CredentialOfferClientV1_0_13';
|
|
14
14
|
export * from './CredentialRequestClientV1_0_11';
|
|
15
15
|
export * from './CredentialRequestClientBuilder';
|
|
16
|
+
export * from './CredentialRequestClientBuilderV1_0_13';
|
|
16
17
|
export * from './CredentialRequestClientBuilderV1_0_11';
|
|
17
18
|
export * from './functions';
|
|
18
19
|
export * from './MetadataClient';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/oid4vci-client",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1-next.19+e6034f5",
|
|
4
4
|
"description": "OpenID for Verifiable Credential Issuance (OpenID4VCI) client",
|
|
5
5
|
"source": "lib/index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"build": "tsc"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@sphereon/oid4vci-common": "0.12.
|
|
18
|
+
"@sphereon/oid4vci-common": "0.12.1-next.19+e6034f5",
|
|
19
19
|
"@sphereon/ssi-types": "0.25.1-unstable.87",
|
|
20
20
|
"cross-fetch": "^3.1.8",
|
|
21
21
|
"debug": "^4.3.4"
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"OIDC4VCI",
|
|
70
70
|
"OID4VCI"
|
|
71
71
|
],
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "e6034f5abd580dd657ac22ceaff9c513e43cc348"
|
|
73
73
|
}
|