@sphereon/oid4vci-client 0.15.2-unstable.8 → 0.16.0
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 +7 -5
- package/dist/AccessTokenClient.d.ts.map +1 -1
- package/dist/AccessTokenClient.js +25 -5
- package/dist/AccessTokenClient.js.map +1 -1
- package/dist/AccessTokenClientV1_0_11.d.ts +7 -5
- package/dist/AccessTokenClientV1_0_11.d.ts.map +1 -1
- package/dist/AccessTokenClientV1_0_11.js +25 -5
- package/dist/AccessTokenClientV1_0_11.js.map +1 -1
- package/dist/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/AuthorizationCodeClient.js.map +1 -1
- package/dist/AuthorizationCodeClientV1_0_11.js +1 -1
- package/dist/AuthorizationCodeClientV1_0_11.js.map +1 -1
- package/dist/CredentialRequestClient.d.ts +5 -3
- package/dist/CredentialRequestClient.d.ts.map +1 -1
- package/dist/CredentialRequestClient.js +22 -4
- package/dist/CredentialRequestClient.js.map +1 -1
- package/dist/CredentialRequestClientV1_0_11.d.ts +5 -3
- package/dist/CredentialRequestClientV1_0_11.d.ts.map +1 -1
- package/dist/CredentialRequestClientV1_0_11.js +22 -4
- package/dist/CredentialRequestClientV1_0_11.js.map +1 -1
- package/dist/MetadataClientV1_0_13.d.ts.map +1 -1
- package/dist/MetadataClientV1_0_13.js +0 -5
- package/dist/MetadataClientV1_0_13.js.map +1 -1
- package/dist/OpenID4VCIClient.d.ts +2 -2
- package/dist/OpenID4VCIClient.d.ts.map +1 -1
- package/dist/OpenID4VCIClient.js +0 -12
- package/dist/OpenID4VCIClient.js.map +1 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts +2 -1
- package/dist/OpenID4VCIClientV1_0_11.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/ProofOfPossessionBuilder.d.ts +2 -1
- package/dist/ProofOfPossessionBuilder.d.ts.map +1 -1
- package/dist/ProofOfPossessionBuilder.js.map +1 -1
- package/dist/functions/AccessTokenUtil.d.ts.map +1 -1
- package/dist/functions/AccessTokenUtil.js +2 -2
- package/dist/functions/AccessTokenUtil.js.map +1 -1
- package/dist/functions/dpopUtil.d.ts +10 -0
- package/dist/functions/dpopUtil.d.ts.map +1 -0
- package/dist/functions/dpopUtil.js +30 -0
- package/dist/functions/dpopUtil.js.map +1 -0
- package/dist/functions/notifications.d.ts.map +1 -1
- package/dist/functions/notifications.js +3 -3
- package/dist/functions/notifications.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/lib/AccessTokenClient.ts +43 -7
- package/lib/AccessTokenClientV1_0_11.ts +43 -7
- package/lib/AuthorizationCodeClient.ts +1 -2
- package/lib/AuthorizationCodeClientV1_0_11.ts +1 -1
- package/lib/CredentialRequestClient.ts +38 -5
- package/lib/CredentialRequestClientV1_0_11.ts +38 -5
- package/lib/MetadataClientV1_0_13.ts +0 -6
- package/lib/OpenID4VCIClient.ts +4 -15
- package/lib/OpenID4VCIClientV1_0_11.ts +1 -1
- package/lib/OpenID4VCIClientV1_0_13.ts +1 -1
- package/lib/ProofOfPossessionBuilder.ts +1 -1
- package/lib/__tests__/AccessTokenClient.spec.ts +4 -11
- package/lib/__tests__/SphereonE2E.spec.test.ts +3 -3
- package/lib/functions/AccessTokenUtil.ts +2 -2
- package/lib/functions/dpopUtil.ts +35 -0
- package/lib/functions/notifications.ts +2 -4
- package/lib/index.ts +0 -1
- package/package.json +4 -3
- package/dist/IssuerSessionClient.d.ts +0 -3
- package/dist/IssuerSessionClient.d.ts.map +0 -1
- package/dist/IssuerSessionClient.js +0 -28
- package/dist/IssuerSessionClient.js.map +0 -1
- package/lib/IssuerSessionClient.ts +0 -17
- package/lib/__tests__/IssuerSessionClient.spec.ts +0 -64
|
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.createJwtBearerClientAssertion = void 0;
|
|
13
|
+
const oid4vc_common_1 = require("@sphereon/oid4vc-common");
|
|
13
14
|
const oid4vci_common_1 = require("@sphereon/oid4vci-common");
|
|
14
|
-
const uuid_1 = require("uuid");
|
|
15
15
|
const ProofOfPossessionBuilder_1 = require("../ProofOfPossessionBuilder");
|
|
16
16
|
const createJwtBearerClientAssertion = (request, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
17
|
var _a, _b;
|
|
@@ -44,7 +44,7 @@ const createJwtBearerClientAssertion = (request, opts) => __awaiter(void 0, void
|
|
|
44
44
|
iss: clientId,
|
|
45
45
|
sub: clientId,
|
|
46
46
|
aud: credentialIssuer,
|
|
47
|
-
jti: (0,
|
|
47
|
+
jti: (0, oid4vc_common_1.uuidv4)(),
|
|
48
48
|
exp: Date.now() / 1000 + 60,
|
|
49
49
|
iat: Date.now() / 1000 - 60,
|
|
50
50
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessTokenUtil.js","sourceRoot":"","sources":["../../lib/functions/AccessTokenUtil.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAA8G;
|
|
1
|
+
{"version":3,"file":"AccessTokenUtil.js","sourceRoot":"","sources":["../../lib/functions/AccessTokenUtil.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2DAAiD;AACjD,6DAA8G;AAE9G,0EAAuE;AAEhE,MAAM,8BAA8B,GAAG,CAC5C,OAAoC,EACpC,IAEC,EACc,EAAE;;IACjB,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAC1C,IAAI,CAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,UAAU,0CAAE,mBAAmB,MAAK,wDAAwD,EAAE,CAAC;QACzG,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;QAC/E,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;QAChC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC,CAAC;QACrG,CAAC;aAAM,IAAI,CAAC,GAAG,EAAE,CAAC;YAChB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC,CAAC;QAC9F,CAAC;aAAM,IAAI,OAAO,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,YAAY,CAAA,KAAK,UAAU,EAAE,CAAC;YAC7D,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC,CAAC;QACxG,CAAC;aAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7B,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2EAA2E,CAAC,CAAC,CAAC;QAC5G,CAAC;QACD,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,GAAG,GAAQ;YACf,MAAM,EAAE;gBACN,GAAG,EAAE,KAAK;gBACV,GAAG;gBACH,GAAG,EAAE,GAAG,aAAH,GAAG,cAAH,GAAG,GAAI,OAAO;aACpB;YACD,OAAO,EAAE;gBACP,GAAG,EAAE,QAAQ;gBACb,GAAG,EAAE,QAAQ;gBACb,GAAG,EAAE,gBAAgB;gBACrB,GAAG,EAAE,IAAA,sBAAM,GAAE;gBACb,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE;gBAC3B,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE;aAC5B;SACF,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,mDAAwB,CAAC,OAAO,CAAC;YACjD,GAAG;YACH,SAAS,EAAE,aAAa;YACxB,OAAO,EAAE,MAAA,IAAI,CAAC,OAAO,mCAAI,kCAAiB,CAAC,UAAU;YACrD,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,qBAAqB,GAAG,wDAAwD,CAAC;QACzF,OAAO,CAAC,gBAAgB,GAAG,GAAG,CAAC,GAAG,CAAC;IACrC,CAAC;AACH,CAAC,CAAA,CAAC;AA9CW,QAAA,8BAA8B,kCA8CzC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { OpenIDResponse } from 'oid4vci-common';
|
|
2
|
+
export type RetryRequestWithDPoPNonce = {
|
|
3
|
+
ok: true;
|
|
4
|
+
dpopNonce: string;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
};
|
|
8
|
+
export declare function shouldRetryTokenRequestWithDPoPNonce(response: OpenIDResponse<unknown, unknown>): RetryRequestWithDPoPNonce;
|
|
9
|
+
export declare function shouldRetryResourceRequestWithDPoPNonce(response: OpenIDResponse<unknown, unknown>): RetryRequestWithDPoPNonce;
|
|
10
|
+
//# sourceMappingURL=dpopUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpopUtil.d.ts","sourceRoot":"","sources":["../../lib/functions/dpopUtil.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,yBAAyB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAExF,wBAAgB,oCAAoC,CAAC,QAAQ,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,yBAAyB,CAW1H;AAED,wBAAgB,uCAAuC,CAAC,QAAQ,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,yBAAyB,CAgB7H"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shouldRetryTokenRequestWithDPoPNonce = shouldRetryTokenRequestWithDPoPNonce;
|
|
4
|
+
exports.shouldRetryResourceRequestWithDPoPNonce = shouldRetryResourceRequestWithDPoPNonce;
|
|
5
|
+
const oid4vc_common_1 = require("@sphereon/oid4vc-common");
|
|
6
|
+
function shouldRetryTokenRequestWithDPoPNonce(response) {
|
|
7
|
+
if (!response.errorBody || response.errorBody.error !== oid4vc_common_1.dpopTokenRequestNonceError) {
|
|
8
|
+
return { ok: false };
|
|
9
|
+
}
|
|
10
|
+
const dPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
11
|
+
if (!dPoPNonce) {
|
|
12
|
+
throw new Error('Missing required DPoP-Nonce header.');
|
|
13
|
+
}
|
|
14
|
+
return { ok: true, dpopNonce: dPoPNonce };
|
|
15
|
+
}
|
|
16
|
+
function shouldRetryResourceRequestWithDPoPNonce(response) {
|
|
17
|
+
if (!response.errorBody || response.origResponse.status !== 401) {
|
|
18
|
+
return { ok: false };
|
|
19
|
+
}
|
|
20
|
+
const wwwAuthenticateHeader = response.origResponse.headers.get('WWW-Authenticate');
|
|
21
|
+
if (!(wwwAuthenticateHeader === null || wwwAuthenticateHeader === void 0 ? void 0 : wwwAuthenticateHeader.includes(oid4vc_common_1.dpopTokenRequestNonceError))) {
|
|
22
|
+
return { ok: false };
|
|
23
|
+
}
|
|
24
|
+
const dPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
25
|
+
if (!dPoPNonce) {
|
|
26
|
+
throw new Error('Missing required DPoP-Nonce header.');
|
|
27
|
+
}
|
|
28
|
+
return { ok: true, dpopNonce: dPoPNonce };
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=dpopUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpopUtil.js","sourceRoot":"","sources":["../../lib/functions/dpopUtil.ts"],"names":[],"mappings":";;AAKA,oFAWC;AAED,0FAgBC;AAlCD,2DAAqE;AAKrE,SAAgB,oCAAoC,CAAC,QAA0C;IAC7F,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,KAAK,0CAA0B,EAAE,CAAC;QACnF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAClE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAC5C,CAAC;AAED,SAAgB,uCAAuC,CAAC,QAA0C;IAChG,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAChE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,qBAAqB,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACpF,IAAI,CAAC,CAAA,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,QAAQ,CAAC,0CAA0B,CAAC,CAAA,EAAE,CAAC;QACjE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAClE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../lib/functions/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,mBAAmB,EAAE,kBAAkB,EAAQ,MAAM,0BAA0B,CAAC;AAEpH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,wBAAsB,gBAAgB,CACpC,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,CAAC,EACrD,OAAO,EAAE,mBAAmB,EAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../lib/functions/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,mBAAmB,EAAE,kBAAkB,EAAQ,MAAM,0BAA0B,CAAC;AAEpH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,wBAAsB,gBAAgB,CACpC,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,CAAC,EACrD,OAAO,EAAE,mBAAmB,EAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAoB7B"}
|
|
@@ -14,7 +14,7 @@ const oid4vci_common_1 = require("@sphereon/oid4vci-common");
|
|
|
14
14
|
const types_1 = require("../types");
|
|
15
15
|
function sendNotification(credentialRequestOpts, request, accessToken) {
|
|
16
16
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
-
var _a
|
|
17
|
+
var _a;
|
|
18
18
|
types_1.LOG.info(`Sending status notification event '${request.event}' for id ${request.notification_id}`);
|
|
19
19
|
if (!credentialRequestOpts.notificationEndpoint) {
|
|
20
20
|
throw Error(`Cannot send notification when no notification endpoint is provided`);
|
|
@@ -24,10 +24,10 @@ function sendNotification(credentialRequestOpts, request, accessToken) {
|
|
|
24
24
|
const error = ((_a = response.errorBody) === null || _a === void 0 ? void 0 : _a.error) !== undefined;
|
|
25
25
|
const result = {
|
|
26
26
|
error,
|
|
27
|
-
response: error ?
|
|
27
|
+
response: error ? response.errorBody : undefined,
|
|
28
28
|
};
|
|
29
29
|
if (error) {
|
|
30
|
-
types_1.LOG.warning(`Notification endpoint returned an error for event '${request.event}' and id ${request.notification_id}: ${
|
|
30
|
+
types_1.LOG.warning(`Notification endpoint returned an error for event '${request.event}' and id ${request.notification_id}: ${response.errorBody}`);
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
types_1.LOG.debug(`Notification endpoint returned success for event '${request.event}' and id ${request.notification_id}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../lib/functions/notifications.ts"],"names":[],"mappings":";;;;;;;;;;;AAKA,
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../lib/functions/notifications.ts"],"names":[],"mappings":";;;;;;;;;;;AAKA,4CAwBC;AA7BD,6DAAoH;AAGpH,oCAA+B;AAE/B,SAAsB,gBAAgB,CACpC,qBAAqD,EACrD,OAA4B,EAC5B,WAAoB;;;QAEpB,WAAG,CAAC,IAAI,CAAC,sCAAsC,OAAO,CAAC,KAAK,YAAY,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;QACnG,IAAI,CAAC,qBAAqB,CAAC,oBAAoB,EAAE,CAAC;YAChD,MAAM,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,aAAX,WAAW,cAAX,WAAW,GAAI,qBAAqB,CAAC,KAAK,CAAC;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAI,EAA4B,qBAAqB,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,oBACrH,CAAC,KAAK,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EACpC,CAAC;QACH,MAAM,KAAK,GAAG,CAAA,MAAA,QAAQ,CAAC,SAAS,0CAAE,KAAK,MAAK,SAAS,CAAC;QACtD,MAAM,MAAM,GAAG;YACb,KAAK;YACL,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;SACjD,CAAC;QACF,IAAI,KAAK,EAAE,CAAC;YACV,WAAG,CAAC,OAAO,CAAC,sDAAsD,OAAO,CAAC,KAAK,YAAY,OAAO,CAAC,eAAe,KAAK,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/I,CAAC;aAAM,CAAC;YACN,WAAG,CAAC,KAAK,CAAC,qDAAqD,OAAO,CAAC,KAAK,YAAY,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;QACrH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,5 @@ export * from './MetadataClientV1_0_11';
|
|
|
19
19
|
export * from './OpenID4VCIClient';
|
|
20
20
|
export * from './OpenID4VCIClientV1_0_13';
|
|
21
21
|
export * from './OpenID4VCIClientV1_0_11';
|
|
22
|
-
export * from './IssuerSessionClient';
|
|
23
22
|
export * from './ProofOfPossessionBuilder';
|
|
24
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,eAAO,MAAM,GAAG,EAAE,aAAa,CAAC,MAAM,CAA8C,CAAC;AAErF,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,eAAO,MAAM,GAAG,EAAE,aAAa,CAAC,MAAM,CAA8C,CAAC;AAErF,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,5 @@ __exportStar(require("./MetadataClientV1_0_11"), exports);
|
|
|
36
36
|
__exportStar(require("./OpenID4VCIClient"), exports);
|
|
37
37
|
__exportStar(require("./OpenID4VCIClientV1_0_13"), exports);
|
|
38
38
|
__exportStar(require("./OpenID4VCIClientV1_0_11"), exports);
|
|
39
|
-
__exportStar(require("./IssuerSessionClient"), exports);
|
|
40
39
|
__exportStar(require("./ProofOfPossessionBuilder"), exports);
|
|
41
40
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAAuD;AAG1C,QAAA,GAAG,GAA0B,4BAAW,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAErF,sDAAoC;AACpC,6DAA2C;AAC3C,4DAA0C;AAC1C,mEAAiD;AACjD,4DAA0C;AAC1C,0DAAwC;AACxC,iEAA+C;AAC/C,iEAA+C;AAC/C,mEAAiD;AACjD,mEAAiD;AACjD,0EAAwD;AACxD,0EAAwD;AACxD,8CAA4B;AAC5B,mDAAiC;AACjC,0DAAwC;AACxC,0DAAwC;AACxC,qDAAmC;AACnC,4DAA0C;AAC1C,4DAA0C;AAC1C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAAuD;AAG1C,QAAA,GAAG,GAA0B,4BAAW,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAErF,sDAAoC;AACpC,6DAA2C;AAC3C,4DAA0C;AAC1C,mEAAiD;AACjD,4DAA0C;AAC1C,0DAAwC;AACxC,iEAA+C;AAC/C,iEAA+C;AAC/C,mEAAiD;AACjD,mEAAiD;AACjD,0EAAwD;AACxD,0EAAwD;AACxD,8CAA4B;AAC5B,mDAAiC;AACjC,0DAAwC;AACxC,0DAAwC;AACxC,qDAAmC;AACnC,4DAA0C;AAC1C,4DAA0C;AAC1C,6DAA2C"}
|
package/lib/AccessTokenClient.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
2
3
|
AccessTokenRequest,
|
|
3
4
|
AccessTokenRequestOpts,
|
|
@@ -6,6 +7,7 @@ import {
|
|
|
6
7
|
AuthorizationServerOpts,
|
|
7
8
|
AuthzFlowType,
|
|
8
9
|
convertJsonToURI,
|
|
10
|
+
DPoPResponseParams,
|
|
9
11
|
EndpointMetadata,
|
|
10
12
|
formPost,
|
|
11
13
|
getIssuerFromCredentialOfferPayload,
|
|
@@ -24,11 +26,12 @@ import { ObjectUtils } from '@sphereon/ssi-types';
|
|
|
24
26
|
|
|
25
27
|
import { MetadataClientV1_0_13 } from './MetadataClientV1_0_13';
|
|
26
28
|
import { createJwtBearerClientAssertion } from './functions';
|
|
29
|
+
import { shouldRetryTokenRequestWithDPoPNonce } from './functions/dpopUtil';
|
|
27
30
|
import { LOG } from './types';
|
|
28
31
|
|
|
29
32
|
export class AccessTokenClient {
|
|
30
|
-
public async acquireAccessToken(opts: AccessTokenRequestOpts): Promise<OpenIDResponse<AccessTokenResponse>> {
|
|
31
|
-
const { asOpts, pin, codeVerifier, code, redirectUri, metadata } = opts;
|
|
33
|
+
public async acquireAccessToken(opts: AccessTokenRequestOpts): Promise<OpenIDResponse<AccessTokenResponse, DPoPResponseParams>> {
|
|
34
|
+
const { asOpts, pin, codeVerifier, code, redirectUri, metadata, createDPoPOpts } = opts;
|
|
32
35
|
|
|
33
36
|
const credentialOffer = opts.credentialOffer ? await assertedUniformCredentialOffer(opts.credentialOffer) : undefined;
|
|
34
37
|
const pinMetadata: TxCodeAndPinRequired | undefined = credentialOffer && this.getPinMetadata(credentialOffer.credential_offer);
|
|
@@ -59,6 +62,7 @@ export class AccessTokenClient {
|
|
|
59
62
|
metadata,
|
|
60
63
|
asOpts,
|
|
61
64
|
issuerOpts,
|
|
65
|
+
createDPoPOpts: createDPoPOpts,
|
|
62
66
|
});
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -68,13 +72,15 @@ export class AccessTokenClient {
|
|
|
68
72
|
metadata,
|
|
69
73
|
asOpts,
|
|
70
74
|
issuerOpts,
|
|
75
|
+
createDPoPOpts,
|
|
71
76
|
}: {
|
|
72
77
|
accessTokenRequest: AccessTokenRequest;
|
|
73
78
|
pinMetadata?: TxCodeAndPinRequired;
|
|
74
79
|
metadata?: EndpointMetadata;
|
|
75
80
|
asOpts?: AuthorizationServerOpts;
|
|
76
81
|
issuerOpts?: IssuerOpts;
|
|
77
|
-
|
|
82
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
83
|
+
}): Promise<OpenIDResponse<AccessTokenResponse, DPoPResponseParams>> {
|
|
78
84
|
this.validate(accessTokenRequest, pinMetadata);
|
|
79
85
|
|
|
80
86
|
const requestTokenURL = AccessTokenClient.determineTokenURL({
|
|
@@ -87,10 +93,34 @@ export class AccessTokenClient {
|
|
|
87
93
|
: undefined,
|
|
88
94
|
});
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
const useDpop = createDPoPOpts?.dPoPSigningAlgValuesSupported && createDPoPOpts.dPoPSigningAlgValuesSupported.length > 0;
|
|
97
|
+
let dPoP = useDpop ? await createDPoP(getCreateDPoPOptions(createDPoPOpts, requestTokenURL)) : undefined;
|
|
98
|
+
|
|
99
|
+
let response = await this.sendAuthCode(requestTokenURL, accessTokenRequest, dPoP ? { headers: { dpop: dPoP } } : undefined);
|
|
100
|
+
|
|
101
|
+
let nextDPoPNonce = createDPoPOpts?.jwtPayloadProps.nonce;
|
|
102
|
+
const retryWithNonce = shouldRetryTokenRequestWithDPoPNonce(response);
|
|
103
|
+
if (retryWithNonce.ok && createDPoPOpts) {
|
|
104
|
+
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
105
|
+
|
|
106
|
+
dPoP = await createDPoP(getCreateDPoPOptions(createDPoPOpts, requestTokenURL));
|
|
107
|
+
response = await this.sendAuthCode(requestTokenURL, accessTokenRequest, dPoP ? { headers: { dpop: dPoP } } : undefined);
|
|
108
|
+
const successDPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
109
|
+
|
|
110
|
+
nextDPoPNonce = successDPoPNonce ?? retryWithNonce.dpopNonce;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (response.successBody && createDPoPOpts && response.successBody.token_type !== 'DPoP') {
|
|
114
|
+
throw new Error('Invalid token type returned. Expected DPoP. Received: ' + response.successBody.token_type);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
...response,
|
|
119
|
+
params: { ...(nextDPoPNonce && { dpop: { dpopNonce: nextDPoPNonce } }) },
|
|
120
|
+
};
|
|
91
121
|
}
|
|
92
122
|
|
|
93
|
-
public async createAccessTokenRequest(opts: AccessTokenRequestOpts): Promise<AccessTokenRequest> {
|
|
123
|
+
public async createAccessTokenRequest(opts: Omit<AccessTokenRequestOpts, 'createDPoPOpts'>): Promise<AccessTokenRequest> {
|
|
94
124
|
const { asOpts, pin, codeVerifier, code, redirectUri } = opts;
|
|
95
125
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
96
126
|
// @ts-ignore
|
|
@@ -222,8 +252,14 @@ export class AccessTokenClient {
|
|
|
222
252
|
}
|
|
223
253
|
}
|
|
224
254
|
|
|
225
|
-
private async sendAuthCode(
|
|
226
|
-
|
|
255
|
+
private async sendAuthCode(
|
|
256
|
+
requestTokenURL: string,
|
|
257
|
+
accessTokenRequest: AccessTokenRequest,
|
|
258
|
+
opts?: { headers?: Record<string, string> },
|
|
259
|
+
): Promise<OpenIDResponse<AccessTokenResponse, DPoPResponseParams>> {
|
|
260
|
+
return await formPost(requestTokenURL, convertJsonToURI(accessTokenRequest, { mode: JsonURIMode.X_FORM_WWW_URLENCODED }), {
|
|
261
|
+
customHeaders: opts?.headers ? opts.headers : undefined,
|
|
262
|
+
});
|
|
227
263
|
}
|
|
228
264
|
|
|
229
265
|
public static determineTokenURL({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
2
3
|
AccessTokenRequest,
|
|
3
4
|
AccessTokenRequestOpts,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
convertJsonToURI,
|
|
9
10
|
CredentialOfferV1_0_11,
|
|
10
11
|
CredentialOfferV1_0_13,
|
|
12
|
+
DPoPResponseParams,
|
|
11
13
|
EndpointMetadata,
|
|
12
14
|
formPost,
|
|
13
15
|
getIssuerFromCredentialOfferPayload,
|
|
@@ -27,12 +29,13 @@ import Debug from 'debug';
|
|
|
27
29
|
|
|
28
30
|
import { MetadataClientV1_0_13 } from './MetadataClientV1_0_13';
|
|
29
31
|
import { createJwtBearerClientAssertion } from './functions';
|
|
32
|
+
import { shouldRetryTokenRequestWithDPoPNonce } from './functions/dpopUtil';
|
|
30
33
|
|
|
31
34
|
const debug = Debug('sphereon:oid4vci:token');
|
|
32
35
|
|
|
33
36
|
export class AccessTokenClientV1_0_11 {
|
|
34
|
-
public async acquireAccessToken(opts: AccessTokenRequestOpts): Promise<OpenIDResponse<AccessTokenResponse>> {
|
|
35
|
-
const { asOpts, pin, codeVerifier, code, redirectUri, metadata } = opts;
|
|
37
|
+
public async acquireAccessToken(opts: AccessTokenRequestOpts): Promise<OpenIDResponse<AccessTokenResponse, DPoPResponseParams>> {
|
|
38
|
+
const { asOpts, pin, codeVerifier, code, redirectUri, metadata, createDPoPOpts } = opts;
|
|
36
39
|
|
|
37
40
|
const credentialOffer = opts.credentialOffer ? await assertedUniformCredentialOffer(opts.credentialOffer) : undefined;
|
|
38
41
|
const isPinRequired = credentialOffer && this.isPinRequiredValue(credentialOffer.credential_offer);
|
|
@@ -63,6 +66,7 @@ export class AccessTokenClientV1_0_11 {
|
|
|
63
66
|
metadata,
|
|
64
67
|
asOpts,
|
|
65
68
|
issuerOpts,
|
|
69
|
+
createDPoPOpts,
|
|
66
70
|
});
|
|
67
71
|
}
|
|
68
72
|
|
|
@@ -71,6 +75,7 @@ export class AccessTokenClientV1_0_11 {
|
|
|
71
75
|
isPinRequired,
|
|
72
76
|
metadata,
|
|
73
77
|
asOpts,
|
|
78
|
+
createDPoPOpts,
|
|
74
79
|
issuerOpts,
|
|
75
80
|
}: {
|
|
76
81
|
accessTokenRequest: AccessTokenRequest;
|
|
@@ -78,7 +83,8 @@ export class AccessTokenClientV1_0_11 {
|
|
|
78
83
|
metadata?: EndpointMetadata;
|
|
79
84
|
asOpts?: AuthorizationServerOpts;
|
|
80
85
|
issuerOpts?: IssuerOpts;
|
|
81
|
-
|
|
86
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
87
|
+
}): Promise<OpenIDResponse<AccessTokenResponse, DPoPResponseParams>> {
|
|
82
88
|
this.validate(accessTokenRequest, isPinRequired);
|
|
83
89
|
|
|
84
90
|
const requestTokenURL = AccessTokenClientV1_0_11.determineTokenURL({
|
|
@@ -91,10 +97,34 @@ export class AccessTokenClientV1_0_11 {
|
|
|
91
97
|
: undefined,
|
|
92
98
|
});
|
|
93
99
|
|
|
94
|
-
|
|
100
|
+
const useDpop = createDPoPOpts?.dPoPSigningAlgValuesSupported && createDPoPOpts.dPoPSigningAlgValuesSupported.length > 0;
|
|
101
|
+
let dPoP = useDpop ? await createDPoP(getCreateDPoPOptions(createDPoPOpts, requestTokenURL)) : undefined;
|
|
102
|
+
|
|
103
|
+
let response = await this.sendAuthCode(requestTokenURL, accessTokenRequest, dPoP ? { headers: { dpop: dPoP } } : undefined);
|
|
104
|
+
|
|
105
|
+
let nextDPoPNonce = createDPoPOpts?.jwtPayloadProps.nonce;
|
|
106
|
+
const retryWithNonce = shouldRetryTokenRequestWithDPoPNonce(response);
|
|
107
|
+
if (retryWithNonce.ok && createDPoPOpts) {
|
|
108
|
+
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
109
|
+
|
|
110
|
+
dPoP = await createDPoP(getCreateDPoPOptions(createDPoPOpts, requestTokenURL));
|
|
111
|
+
response = await this.sendAuthCode(requestTokenURL, accessTokenRequest, dPoP ? { headers: { dpop: dPoP } } : undefined);
|
|
112
|
+
const successDPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
113
|
+
|
|
114
|
+
nextDPoPNonce = successDPoPNonce ?? retryWithNonce.dpopNonce;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (response.successBody && createDPoPOpts && response.successBody.token_type !== 'DPoP') {
|
|
118
|
+
throw new Error('Invalid token type returned. Expected DPoP. Received: ' + response.successBody.token_type);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
...response,
|
|
123
|
+
params: { ...(nextDPoPNonce && { dpop: { dpopNonce: nextDPoPNonce } }) },
|
|
124
|
+
};
|
|
95
125
|
}
|
|
96
126
|
|
|
97
|
-
public async createAccessTokenRequest(opts: AccessTokenRequestOpts): Promise<AccessTokenRequest> {
|
|
127
|
+
public async createAccessTokenRequest(opts: Omit<AccessTokenRequestOpts, 'createDPoPOpts'>): Promise<AccessTokenRequest> {
|
|
98
128
|
const { asOpts, pin, codeVerifier, code, redirectUri } = opts;
|
|
99
129
|
const credentialOfferRequest = opts.credentialOffer
|
|
100
130
|
? await toUniformCredentialOfferRequest(opts.credentialOffer as CredentialOfferV1_0_11 | CredentialOfferV1_0_13)
|
|
@@ -204,8 +234,14 @@ export class AccessTokenClientV1_0_11 {
|
|
|
204
234
|
}
|
|
205
235
|
}
|
|
206
236
|
|
|
207
|
-
private async sendAuthCode(
|
|
208
|
-
|
|
237
|
+
private async sendAuthCode(
|
|
238
|
+
requestTokenURL: string,
|
|
239
|
+
accessTokenRequest: AccessTokenRequest,
|
|
240
|
+
opts?: { headers?: Record<string, string> },
|
|
241
|
+
): Promise<OpenIDResponse<AccessTokenResponse>> {
|
|
242
|
+
return await formPost(requestTokenURL, convertJsonToURI(accessTokenRequest, { mode: JsonURIMode.X_FORM_WWW_URLENCODED }), {
|
|
243
|
+
customHeaders: opts?.headers ? opts.headers : undefined,
|
|
244
|
+
});
|
|
209
245
|
}
|
|
210
246
|
|
|
211
247
|
public static determineTokenURL({
|
|
@@ -114,7 +114,7 @@ export const createAuthorizationRequestUrl = async ({
|
|
|
114
114
|
const client_id = clientId ?? authorizationRequest.clientId;
|
|
115
115
|
|
|
116
116
|
// Authorization server metadata takes precedence
|
|
117
|
-
const authorizationMetadata = endpointMetadata.authorizationServerMetadata ?? endpointMetadata.credentialIssuerMetadata
|
|
117
|
+
const authorizationMetadata = endpointMetadata.authorizationServerMetadata ?? endpointMetadata.credentialIssuerMetadata;
|
|
118
118
|
|
|
119
119
|
let { authorizationDetails } = authorizationRequest;
|
|
120
120
|
const parMode = authorizationMetadata?.require_pushed_authorization_requests
|
|
@@ -182,7 +182,6 @@ export const createAuthorizationRequestUrl = async ({
|
|
|
182
182
|
}
|
|
183
183
|
const parEndpoint = authorizationMetadata?.pushed_authorization_request_endpoint;
|
|
184
184
|
|
|
185
|
-
|
|
186
185
|
let queryObj: Record<string, any> | PushedAuthorizationResponse = {
|
|
187
186
|
response_type: ResponseType.AUTH_CODE,
|
|
188
187
|
...(!pkce.disabled && {
|
|
@@ -40,7 +40,7 @@ export const createAuthorizationRequestUrlV1_0_11 = async ({
|
|
|
40
40
|
|
|
41
41
|
const parMode = endpointMetadata?.credentialIssuerMetadata?.require_pushed_authorization_requests
|
|
42
42
|
? PARMode.REQUIRE
|
|
43
|
-
: authorizationRequest.parMode ?? PARMode.AUTO;
|
|
43
|
+
: (authorizationRequest.parMode ?? PARMode.AUTO);
|
|
44
44
|
// Scope and authorization_details can be used in the same authorization request
|
|
45
45
|
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-rar-23#name-relationship-to-scope-param
|
|
46
46
|
if (!scope && !authorizationDetails) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
2
3
|
acquireDeferredCredential,
|
|
3
4
|
CredentialRequestV1_0_13,
|
|
4
5
|
CredentialResponse,
|
|
6
|
+
DPoPResponseParams,
|
|
5
7
|
getCredentialRequestForVersion,
|
|
6
8
|
getUniformFormat,
|
|
7
9
|
isDeferredCredentialResponse,
|
|
@@ -21,6 +23,7 @@ import Debug from 'debug';
|
|
|
21
23
|
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
|
|
22
24
|
import { CredentialRequestClientBuilderV1_0_13 } from './CredentialRequestClientBuilderV1_0_13';
|
|
23
25
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
26
|
+
import { shouldRetryResourceRequestWithDPoPNonce } from './functions/dpopUtil';
|
|
24
27
|
|
|
25
28
|
const debug = Debug('sphereon:oid4vci:credential');
|
|
26
29
|
|
|
@@ -89,7 +92,8 @@ export class CredentialRequestClient {
|
|
|
89
92
|
context?: string[];
|
|
90
93
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
91
94
|
subjectIssuance?: ExperimentalSubjectIssuance;
|
|
92
|
-
|
|
95
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
96
|
+
}): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
|
|
93
97
|
const { credentialIdentifier, credentialTypes, proofInput, format, context, subjectIssuance } = opts;
|
|
94
98
|
|
|
95
99
|
const request = await this.createCredentialRequest({
|
|
@@ -101,12 +105,13 @@ export class CredentialRequestClient {
|
|
|
101
105
|
credentialIdentifier,
|
|
102
106
|
subjectIssuance,
|
|
103
107
|
});
|
|
104
|
-
return await this.acquireCredentialsUsingRequest(request);
|
|
108
|
+
return await this.acquireCredentialsUsingRequest(request, opts.createDPoPOpts);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
public async acquireCredentialsUsingRequest(
|
|
108
112
|
uniformRequest: UniformCredentialRequest,
|
|
109
|
-
|
|
113
|
+
createDPoPOpts?: CreateDPoPClientOpts,
|
|
114
|
+
): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
|
|
110
115
|
if (this.version() < OpenId4VCIVersion.VER_1_0_13) {
|
|
111
116
|
throw new Error('Versions below v1.0.13 (draft 13) are not supported by the V13 credential request client.');
|
|
112
117
|
}
|
|
@@ -119,9 +124,33 @@ export class CredentialRequestClient {
|
|
|
119
124
|
debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
|
|
120
125
|
debug(`request\n: ${JSON.stringify(request, null, 2)}`);
|
|
121
126
|
const requestToken: string = this.credentialRequestOpts.token;
|
|
122
|
-
|
|
127
|
+
|
|
128
|
+
let dPoP = createDPoPOpts ? await createDPoP(getCreateDPoPOptions(createDPoPOpts, credentialEndpoint, { accessToken: requestToken })) : undefined;
|
|
129
|
+
|
|
130
|
+
let response = (await post(credentialEndpoint, JSON.stringify(request), {
|
|
131
|
+
bearerToken: requestToken,
|
|
132
|
+
customHeaders: { ...(dPoP && { dpop: dPoP }) },
|
|
133
|
+
})) as OpenIDResponse<CredentialResponse> & {
|
|
123
134
|
access_token: string;
|
|
124
135
|
};
|
|
136
|
+
|
|
137
|
+
let nextDPoPNonce = createDPoPOpts?.jwtPayloadProps.nonce;
|
|
138
|
+
const retryWithNonce = shouldRetryResourceRequestWithDPoPNonce(response);
|
|
139
|
+
if (retryWithNonce.ok && createDPoPOpts) {
|
|
140
|
+
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
141
|
+
dPoP = await createDPoP(getCreateDPoPOptions(createDPoPOpts, credentialEndpoint, { accessToken: requestToken }));
|
|
142
|
+
|
|
143
|
+
response = (await post(credentialEndpoint, JSON.stringify(request), {
|
|
144
|
+
bearerToken: requestToken,
|
|
145
|
+
customHeaders: { ...(createDPoPOpts && { dpop: dPoP }) },
|
|
146
|
+
})) as OpenIDResponse<CredentialResponse> & {
|
|
147
|
+
access_token: string;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const successDPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
151
|
+
nextDPoPNonce = successDPoPNonce ?? retryWithNonce.dpopNonce;
|
|
152
|
+
}
|
|
153
|
+
|
|
125
154
|
this._isDeferred = isDeferredCredentialResponse(response);
|
|
126
155
|
if (this.isDeferred() && this.credentialRequestOpts.deferredCredentialAwait && response.successBody) {
|
|
127
156
|
response = await this.acquireDeferredCredential(response.successBody, { bearerToken: this.credentialRequestOpts.token });
|
|
@@ -134,7 +163,11 @@ export class CredentialRequestClient {
|
|
|
134
163
|
}
|
|
135
164
|
}
|
|
136
165
|
debug(`Credential endpoint ${credentialEndpoint} response:\r\n${JSON.stringify(response, null, 2)}`);
|
|
137
|
-
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
...response,
|
|
169
|
+
params: { ...(nextDPoPNonce && { dpop: { dpopNonce: nextDPoPNonce } }) },
|
|
170
|
+
};
|
|
138
171
|
}
|
|
139
172
|
|
|
140
173
|
public async acquireDeferredCredential(
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { createDPoP, CreateDPoPClientOpts, getCreateDPoPOptions } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
2
3
|
acquireDeferredCredential,
|
|
3
4
|
CredentialResponse,
|
|
5
|
+
DPoPResponseParams,
|
|
4
6
|
getCredentialRequestForVersion,
|
|
5
7
|
getUniformFormat,
|
|
6
8
|
isDeferredCredentialResponse,
|
|
@@ -20,6 +22,7 @@ import Debug from 'debug';
|
|
|
20
22
|
import { buildProof } from './CredentialRequestClient';
|
|
21
23
|
import { CredentialRequestClientBuilderV1_0_11 } from './CredentialRequestClientBuilderV1_0_11';
|
|
22
24
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
25
|
+
import { shouldRetryResourceRequestWithDPoPNonce } from './functions/dpopUtil';
|
|
23
26
|
|
|
24
27
|
const debug = Debug('sphereon:oid4vci:credential');
|
|
25
28
|
|
|
@@ -64,16 +67,18 @@ export class CredentialRequestClientV1_0_11 {
|
|
|
64
67
|
credentialTypes?: string | string[];
|
|
65
68
|
context?: string[];
|
|
66
69
|
format?: CredentialFormat | OID4VCICredentialFormat;
|
|
67
|
-
|
|
70
|
+
createDPoPOpts?: CreateDPoPClientOpts;
|
|
71
|
+
}): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
|
|
68
72
|
const { credentialTypes, proofInput, format, context } = opts;
|
|
69
73
|
|
|
70
74
|
const request = await this.createCredentialRequest({ proofInput, credentialTypes, context, format, version: this.version() });
|
|
71
|
-
return await this.acquireCredentialsUsingRequest(request);
|
|
75
|
+
return await this.acquireCredentialsUsingRequest(request, opts.createDPoPOpts);
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
public async acquireCredentialsUsingRequest(
|
|
75
79
|
uniformRequest: UniformCredentialRequest,
|
|
76
|
-
|
|
80
|
+
createDPoPOpts?: CreateDPoPClientOpts,
|
|
81
|
+
): Promise<OpenIDResponse<CredentialResponse, DPoPResponseParams> & { access_token: string }> {
|
|
77
82
|
const request = getCredentialRequestForVersion(uniformRequest, this.version());
|
|
78
83
|
const credentialEndpoint: string = this.credentialRequestOpts.credentialEndpoint;
|
|
79
84
|
if (!isValidURL(credentialEndpoint)) {
|
|
@@ -83,9 +88,33 @@ export class CredentialRequestClientV1_0_11 {
|
|
|
83
88
|
debug(`Acquiring credential(s) from: ${credentialEndpoint}`);
|
|
84
89
|
debug(`request\n: ${JSON.stringify(request, null, 2)}`);
|
|
85
90
|
const requestToken: string = this.credentialRequestOpts.token;
|
|
86
|
-
|
|
91
|
+
|
|
92
|
+
let dPoP = createDPoPOpts ? await createDPoP(getCreateDPoPOptions(createDPoPOpts, credentialEndpoint, { accessToken: requestToken })) : undefined;
|
|
93
|
+
|
|
94
|
+
let response = (await post(credentialEndpoint, JSON.stringify(request), {
|
|
95
|
+
bearerToken: requestToken,
|
|
96
|
+
customHeaders: { ...(createDPoPOpts && { dpop: dPoP }) },
|
|
97
|
+
})) as OpenIDResponse<CredentialResponse> & {
|
|
87
98
|
access_token: string;
|
|
88
99
|
};
|
|
100
|
+
|
|
101
|
+
let nextDPoPNonce = createDPoPOpts?.jwtPayloadProps.nonce;
|
|
102
|
+
const retryWithNonce = shouldRetryResourceRequestWithDPoPNonce(response);
|
|
103
|
+
if (retryWithNonce.ok && createDPoPOpts) {
|
|
104
|
+
createDPoPOpts.jwtPayloadProps.nonce = retryWithNonce.dpopNonce;
|
|
105
|
+
dPoP = await createDPoP(getCreateDPoPOptions(createDPoPOpts, credentialEndpoint, { accessToken: requestToken }));
|
|
106
|
+
|
|
107
|
+
response = (await post(credentialEndpoint, JSON.stringify(request), {
|
|
108
|
+
bearerToken: requestToken,
|
|
109
|
+
customHeaders: { ...(createDPoPOpts && { dpop: dPoP }) },
|
|
110
|
+
})) as OpenIDResponse<CredentialResponse> & {
|
|
111
|
+
access_token: string;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const successDPoPNonce = response.origResponse.headers.get('DPoP-Nonce');
|
|
115
|
+
nextDPoPNonce = successDPoPNonce ?? retryWithNonce.dpopNonce;
|
|
116
|
+
}
|
|
117
|
+
|
|
89
118
|
this._isDeferred = isDeferredCredentialResponse(response);
|
|
90
119
|
if (this.isDeferred() && this.credentialRequestOpts.deferredCredentialAwait && response.successBody) {
|
|
91
120
|
response = await this.acquireDeferredCredential(response.successBody, { bearerToken: this.credentialRequestOpts.token });
|
|
@@ -93,7 +122,11 @@ export class CredentialRequestClientV1_0_11 {
|
|
|
93
122
|
response.access_token = requestToken;
|
|
94
123
|
|
|
95
124
|
debug(`Credential endpoint ${credentialEndpoint} response:\r\n${JSON.stringify(response, null, 2)}`);
|
|
96
|
-
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
...response,
|
|
128
|
+
params: { ...(nextDPoPNonce && { dpop: { dpopNonce: nextDPoPNonce } }) },
|
|
129
|
+
};
|
|
97
130
|
}
|
|
98
131
|
|
|
99
132
|
public async acquireDeferredCredential(
|
|
@@ -50,7 +50,6 @@ export class MetadataClientV1_0_13 {
|
|
|
50
50
|
let credential_endpoint: string | undefined;
|
|
51
51
|
let deferred_credential_endpoint: string | undefined;
|
|
52
52
|
let authorization_endpoint: string | undefined;
|
|
53
|
-
let session_endpoint: string | undefined;
|
|
54
53
|
let authorizationServerType: AuthorizationServerType = 'OID4VCI';
|
|
55
54
|
let authorization_servers: string[] = [issuer];
|
|
56
55
|
const oid4vciResponse = await MetadataClientV1_0_13.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations
|
|
@@ -158,16 +157,11 @@ export class MetadataClientV1_0_13 {
|
|
|
158
157
|
credentialIssuerMetadata = authMetadata as CredentialIssuerMetadataV1_0_13;
|
|
159
158
|
}
|
|
160
159
|
debug(`Issuer ${issuer} token endpoint ${token_endpoint}, credential endpoint ${credential_endpoint}`);
|
|
161
|
-
|
|
162
|
-
if(credentialIssuerMetadata?.session_endpoint !== undefined) {
|
|
163
|
-
session_endpoint = credentialIssuerMetadata.session_endpoint
|
|
164
|
-
}
|
|
165
160
|
return {
|
|
166
161
|
issuer,
|
|
167
162
|
token_endpoint,
|
|
168
163
|
credential_endpoint,
|
|
169
164
|
deferred_credential_endpoint,
|
|
170
|
-
session_endpoint,
|
|
171
165
|
authorization_server: authorization_servers[0],
|
|
172
166
|
authorization_endpoint,
|
|
173
167
|
authorizationServerType,
|
package/lib/OpenID4VCIClient.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JWK } from '@sphereon/oid4vc-common';
|
|
1
2
|
import {
|
|
2
3
|
AccessTokenResponse,
|
|
3
4
|
Alg,
|
|
@@ -22,8 +23,7 @@ import {
|
|
|
22
23
|
getIssuerFromCredentialOfferPayload,
|
|
23
24
|
getSupportedCredentials,
|
|
24
25
|
getTypesFromCredentialSupported,
|
|
25
|
-
getTypesFromObject,
|
|
26
|
-
JWK,
|
|
26
|
+
getTypesFromObject,
|
|
27
27
|
KID_JWK_X5C_ERROR,
|
|
28
28
|
NotificationRequest,
|
|
29
29
|
NotificationResult,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
OpenId4VCIVersion,
|
|
32
32
|
PKCEOpts,
|
|
33
33
|
ProofOfPossessionCallbacks,
|
|
34
|
-
toAuthorizationResponsePayload
|
|
34
|
+
toAuthorizationResponsePayload,
|
|
35
35
|
} from '@sphereon/oid4vci-common';
|
|
36
36
|
import { CredentialFormat } from '@sphereon/ssi-types';
|
|
37
37
|
import Debug from 'debug';
|
|
@@ -49,7 +49,6 @@ import { OpenID4VCIClientStateV1_0_11 } from './OpenID4VCIClientV1_0_11';
|
|
|
49
49
|
import { OpenID4VCIClientStateV1_0_13 } from './OpenID4VCIClientV1_0_13';
|
|
50
50
|
import { ProofOfPossessionBuilder } from './ProofOfPossessionBuilder';
|
|
51
51
|
import { generateMissingPKCEOpts, sendNotification } from './functions';
|
|
52
|
-
import { acquireIssuerSessionId } from './IssuerSessionClient';
|
|
53
52
|
|
|
54
53
|
const debug = Debug('sphereon:oid4vci');
|
|
55
54
|
|
|
@@ -362,16 +361,6 @@ export class OpenID4VCIClient {
|
|
|
362
361
|
return this.accessTokenResponse;
|
|
363
362
|
}
|
|
364
363
|
|
|
365
|
-
public async acquireIssuerSessionId() : Promise<IssuerSessionResponse | undefined> {
|
|
366
|
-
if(!this._state.endpointMetadata) {
|
|
367
|
-
return Promise.reject('endpointMetadata no loaded, retrieveServerMetadata()')
|
|
368
|
-
}
|
|
369
|
-
if(!('session_endpoint' in this._state.endpointMetadata) || !this._state.endpointMetadata.session_endpoint) {
|
|
370
|
-
return undefined
|
|
371
|
-
}
|
|
372
|
-
return acquireIssuerSessionId({sessionEndpoint: this._state.endpointMetadata.session_endpoint})
|
|
373
|
-
}
|
|
374
|
-
|
|
375
364
|
public async acquireCredentials({
|
|
376
365
|
credentialTypes,
|
|
377
366
|
context,
|
|
@@ -560,7 +549,7 @@ export class OpenID4VCIClient {
|
|
|
560
549
|
issuerSupportedFlowTypes(): AuthzFlowType[] {
|
|
561
550
|
return (
|
|
562
551
|
this.credentialOffer?.supportedFlows ??
|
|
563
|
-
(this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server
|
|
552
|
+
((this._state.endpointMetadata?.credentialIssuerMetadata?.authorization_endpoint ?? this._state.endpointMetadata?.authorization_server)
|
|
564
553
|
? [AuthzFlowType.AUTHORIZATION_CODE_FLOW]
|
|
565
554
|
: [])
|
|
566
555
|
);
|