@digitalbazaar/ezcap-express 6.0.0 → 7.0.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/README.md +227 -11
- package/lib/authorize.js +14 -4
- package/lib/index.js +2 -5
- package/lib/revoke.js +7 -6
- package/package.json +45 -38
- package/CHANGELOG.md +0 -230
- package/lib/main.js +0 -5
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ for express.js HTTP servers and more.
|
|
|
19
19
|
|
|
20
20
|
## Background
|
|
21
21
|
|
|
22
|
-
This library provides
|
|
22
|
+
This library provides Node.js express middleware that can be used to protect
|
|
23
23
|
resources on HTTP servers using Authorization Capabilities (zcaps). The library
|
|
24
24
|
is configured with secure and sensible defaults to help developers get started
|
|
25
25
|
quickly and ensure that their server code is production-ready.
|
|
@@ -37,7 +37,16 @@ preferably via parties other than the implementer.
|
|
|
37
37
|
|
|
38
38
|
## Install
|
|
39
39
|
|
|
40
|
-
- Node.js 14+ is
|
|
40
|
+
- Node.js 14+ is supported.
|
|
41
|
+
- [Web Crypto API][] is required by dependencies. Node.js 14 must use a polyfill.
|
|
42
|
+
|
|
43
|
+
To install from NPM:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
npm install @digitalbazaar/ezcap-express
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
To install development code:
|
|
41
50
|
|
|
42
51
|
```sh
|
|
43
52
|
git clone git@github.com:digitalbazaar/ezcap-express.git
|
|
@@ -116,7 +125,7 @@ async function documentLoader(url) {
|
|
|
116
125
|
### Define authorizeMyZcapInvocation
|
|
117
126
|
|
|
118
127
|
```js
|
|
119
|
-
|
|
128
|
+
import {authorizeZcapInvocation} from '@digitalbazaar/ezcap-express';
|
|
120
129
|
|
|
121
130
|
async function authorizeMyZcapInvocation({expectedAction} = {}) {
|
|
122
131
|
return authorizeZcapInvocation({
|
|
@@ -201,24 +210,229 @@ very simple code.
|
|
|
201
210
|
These are the two assumptions that ezcap makes and with those two assumptions,
|
|
202
211
|
80% of all use cases we've encountered are covered.
|
|
203
212
|
|
|
213
|
+
## Functions
|
|
214
|
+
|
|
215
|
+
<dl>
|
|
216
|
+
<dt><a href="#authorizeZcapInvocation">authorizeZcapInvocation(options)</a> ⇒ <code>function</code></dt>
|
|
217
|
+
<dd><p>Authorizes an incoming request.</p>
|
|
218
|
+
</dd>
|
|
219
|
+
<dt><a href="#authorizeZcapRevocation">authorizeZcapRevocation(options)</a> ⇒ <code>function</code></dt>
|
|
220
|
+
<dd><p>Authorizes a request to submit a zcap revocation.</p>
|
|
221
|
+
<p>This middleware is opinionated; it MUST be attached to an endpoint that
|
|
222
|
+
terminates in <code>/zcaps/revocations/:revocationId</code>. This to enable the
|
|
223
|
+
middleware to automatically generate expected values for running zcap checks
|
|
224
|
+
and to support a common, conventional revocation API pattern.</p>
|
|
225
|
+
<p>The pattern is in support of controlled objects on a service, aka
|
|
226
|
+
"service objects". Each object's controller is used to populate the root
|
|
227
|
+
zcap for the object's controller field. This root zcap has an invocation
|
|
228
|
+
target that matches the URL for the service object, aka its
|
|
229
|
+
"serviceObjectId".</p>
|
|
230
|
+
<p>Therefore, any route that matches an invocation target for a root zcap for
|
|
231
|
+
a service SHOULD attach this middleware to:</p>
|
|
232
|
+
<p><code><serviceObjectId>/zcaps/revocations/:revocationId</code>.</p>
|
|
233
|
+
<p>This middleware will compute <code>serviceObjectId</code> by combining the expected
|
|
234
|
+
host with the subpath from the request URL that occurs before
|
|
235
|
+
<code>/zcaps/revocations/</code>. It assumes that the request URL will have this
|
|
236
|
+
pattern if the middleware code has been reached. IOW, <code>serviceObjectId</code> will
|
|
237
|
+
be set using:</p>
|
|
238
|
+
<p><code>https://<expectedHost>/<URL subpath before "/zcaps/revocations/"></code>.</p>
|
|
239
|
+
<p>Note: This middleware does NOT support having <code>/zcaps/revocations/</code> appear
|
|
240
|
+
multiple places in the request URL.</p>
|
|
241
|
+
<p>Attaching this middleware will enable any zcaps delegated from the service
|
|
242
|
+
object's root zcap to be revoked without having to issue an additional zcap
|
|
243
|
+
to use the revocation endpoint. This middleware makes that possible by
|
|
244
|
+
supporting the invocation of a dynamically generated root zcap with an
|
|
245
|
+
invocation target of:</p>
|
|
246
|
+
<p><code><serviceObjectId>/zcaps/revocations/:revocationId</code>.</p>
|
|
247
|
+
<p>This middleware will set the <code>controller</code> of this root zcap to all
|
|
248
|
+
controllers in the to-be-revoked zcap's delegation chain, permitting any
|
|
249
|
+
participant to revoke it. An error will be thrown prior to populating this
|
|
250
|
+
<code>controller</code> field if the root zcap in the to-be-revoked zcap's chain does
|
|
251
|
+
not have <code><serviceObjectId></code> as its invocation target (or a prefix of it).
|
|
252
|
+
This ensures that the only zcaps that have been delegated from a root zcap
|
|
253
|
+
using the service object's ID as part of its invocation target can be
|
|
254
|
+
revoked at its <code>/zcaps/revocations</code> route, i.e., other zcaps intended for
|
|
255
|
+
other service objects -- or entirely other services -- cannot be revoked via
|
|
256
|
+
this middleware.</p>
|
|
257
|
+
<p>This middleware will automatically generate two sets of expects values: one
|
|
258
|
+
for checking the invocation to revoke a capability and one for verifying the
|
|
259
|
+
delegation chain of the capability that is to be revoked. Only the expected
|
|
260
|
+
host value can and must be given as a parameter.</p>
|
|
261
|
+
<p>The expected values for checking the capability invocation will be:</p>
|
|
262
|
+
<p>host: <code><expectedHost></code>,
|
|
263
|
+
rootInvocationTarget: [
|
|
264
|
+
// root zcap with this target, RZ1, can be delegated w/target attenuation
|
|
265
|
+
// to allow delegates to revoke any zcap, Z1, with RZ1 as the root in its
|
|
266
|
+
// chain, even if the delegate is not a controller in Z1's chain
|
|
267
|
+
<code><serviceObjectId></code>,
|
|
268
|
+
// root zcap that this target, RZ2, can be used to revoke a zcap, Z2,
|
|
269
|
+
// with an "id" of <code>revocationId</code>; RZ2's controller will be populated
|
|
270
|
+
// using all controllers from Z2's chain, enabling any controller in that
|
|
271
|
+
// zcap's chain to invoke RZ2 to revoke Z2
|
|
272
|
+
<code><serviceObjectId>/zcaps/revocations/<revocationId></code>,
|
|
273
|
+
],
|
|
274
|
+
action: 'write'
|
|
275
|
+
.</p>
|
|
276
|
+
</dd>
|
|
277
|
+
</dl>
|
|
278
|
+
|
|
279
|
+
## Typedefs
|
|
280
|
+
|
|
281
|
+
<dl>
|
|
282
|
+
<dt><a href="#GetExpectedValues">GetExpectedValues</a></dt>
|
|
283
|
+
<dd></dd>
|
|
284
|
+
<dt><a href="#GetExpectedValues">GetExpectedValues</a> ⇒ <code><a href="#ExpectedValues">ExpectedValues</a></code></dt>
|
|
285
|
+
<dd><p>A function for returning expected values when checking a zcap invocation.</p>
|
|
286
|
+
</dd>
|
|
287
|
+
<dt><a href="#ExpectedValues">ExpectedValues</a> : <code>object</code></dt>
|
|
288
|
+
<dd><p>The expected values for checking a zcap invocation performed via an HTTP
|
|
289
|
+
request.</p>
|
|
290
|
+
</dd>
|
|
291
|
+
</dl>
|
|
292
|
+
|
|
204
293
|
<a name="authorizeZcapInvocation"></a>
|
|
205
294
|
|
|
206
295
|
## authorizeZcapInvocation(options) ⇒ <code>function</code>
|
|
207
296
|
Authorizes an incoming request.
|
|
208
297
|
|
|
209
|
-
**Kind**: global function
|
|
210
|
-
**Returns**: <code>function</code> - Returns an Express.js middleware route handler.
|
|
298
|
+
**Kind**: global function
|
|
299
|
+
**Returns**: <code>function</code> - Returns an Express.js style middleware route handler.
|
|
300
|
+
|
|
301
|
+
| Param | Type | Default | Description |
|
|
302
|
+
| --- | --- | --- | --- |
|
|
303
|
+
| options | <code>object</code> | | Options hashmap. |
|
|
304
|
+
| [options.allowTargetAttenuation] | <code>boolean</code> | <code>true</code> | Allow the invocationTarget of a delegation chain to be increasingly restrictive based on a hierarchical RESTful URL structure. |
|
|
305
|
+
| options.documentLoader | <code>object</code> | | Document loader used to load DID Documents, capability documents, and JSON-LD Contexts. |
|
|
306
|
+
| options.getExpectedValues | [<code>GetExpectedValues</code>](#GetExpectedValues) | | Used to get the expected values when checking the zcap invocation. |
|
|
307
|
+
| options.getRootController | <code>function</code> | | Used to get the controller of the root capability in the invoked capability's chain. |
|
|
308
|
+
| options.getVerifier | <code>function</code> | | An async function to call to get a verifier and verification method for the key ID. |
|
|
309
|
+
| [options.inspectCapabilityChain] | <code>function</code> | | A function that can inspect a capability chain, e.g., to check for revocations. |
|
|
310
|
+
| [options.maxChainLength] | <code>number</code> | <code>10</code> | The maximum length of the capability delegation chain. |
|
|
311
|
+
| [options.maxClockSkew] | <code>number</code> | <code>300</code> | A maximum number of seconds that clocks may be skewed when checking capability expiration date-times against `date`, when comparing invocation proof creation time against delegation proof creation time, and when comparing the capability invocation expiration time against `now`. |
|
|
312
|
+
| [options.maxDelegationTtl] | <code>number</code> | <code>1000*60*60*24*90</code> | The maximum milliseconds to live for a delegated zcap as measured by the time difference between `expires` and `created` on the delegation proof. |
|
|
313
|
+
| [options.onError] | <code>function</code> | | An error handler handler for customizable error handling. |
|
|
314
|
+
| options.suiteFactory | <code>object</code> | | A factory for creating the supported suite(s) to use when verifying zcap delegation chains; this is different from `getVerifier` which is used to produce a verifier for verifying HTTP signatures used to invoke zcaps. |
|
|
315
|
+
|
|
316
|
+
<a name="authorizeZcapRevocation"></a>
|
|
317
|
+
|
|
318
|
+
## authorizeZcapRevocation(options) ⇒ <code>function</code>
|
|
319
|
+
Authorizes a request to submit a zcap revocation.
|
|
320
|
+
|
|
321
|
+
This middleware is opinionated; it MUST be attached to an endpoint that
|
|
322
|
+
terminates in `/zcaps/revocations/:revocationId`. This to enable the
|
|
323
|
+
middleware to automatically generate expected values for running zcap checks
|
|
324
|
+
and to support a common, conventional revocation API pattern.
|
|
325
|
+
|
|
326
|
+
The pattern is in support of controlled objects on a service, aka
|
|
327
|
+
"service objects". Each object's controller is used to populate the root
|
|
328
|
+
zcap for the object's controller field. This root zcap has an invocation
|
|
329
|
+
target that matches the URL for the service object, aka its
|
|
330
|
+
"serviceObjectId".
|
|
331
|
+
|
|
332
|
+
Therefore, any route that matches an invocation target for a root zcap for
|
|
333
|
+
a service SHOULD attach this middleware to:
|
|
334
|
+
|
|
335
|
+
`<serviceObjectId>/zcaps/revocations/:revocationId`.
|
|
336
|
+
|
|
337
|
+
This middleware will compute `serviceObjectId` by combining the expected
|
|
338
|
+
host with the subpath from the request URL that occurs before
|
|
339
|
+
`/zcaps/revocations/`. It assumes that the request URL will have this
|
|
340
|
+
pattern if the middleware code has been reached. IOW, `serviceObjectId` will
|
|
341
|
+
be set using:
|
|
342
|
+
|
|
343
|
+
`https://<expectedHost>/<URL subpath before "/zcaps/revocations/">`.
|
|
344
|
+
|
|
345
|
+
Note: This middleware does NOT support having `/zcaps/revocations/` appear
|
|
346
|
+
multiple places in the request URL.
|
|
347
|
+
|
|
348
|
+
Attaching this middleware will enable any zcaps delegated from the service
|
|
349
|
+
object's root zcap to be revoked without having to issue an additional zcap
|
|
350
|
+
to use the revocation endpoint. This middleware makes that possible by
|
|
351
|
+
supporting the invocation of a dynamically generated root zcap with an
|
|
352
|
+
invocation target of:
|
|
353
|
+
|
|
354
|
+
`<serviceObjectId>/zcaps/revocations/:revocationId`.
|
|
355
|
+
|
|
356
|
+
This middleware will set the `controller` of this root zcap to all
|
|
357
|
+
controllers in the to-be-revoked zcap's delegation chain, permitting any
|
|
358
|
+
participant to revoke it. An error will be thrown prior to populating this
|
|
359
|
+
`controller` field if the root zcap in the to-be-revoked zcap's chain does
|
|
360
|
+
not have `<serviceObjectId>` as its invocation target (or a prefix of it).
|
|
361
|
+
This ensures that the only zcaps that have been delegated from a root zcap
|
|
362
|
+
using the service object's ID as part of its invocation target can be
|
|
363
|
+
revoked at its `/zcaps/revocations` route, i.e., other zcaps intended for
|
|
364
|
+
other service objects -- or entirely other services -- cannot be revoked via
|
|
365
|
+
this middleware.
|
|
366
|
+
|
|
367
|
+
This middleware will automatically generate two sets of expects values: one
|
|
368
|
+
for checking the invocation to revoke a capability and one for verifying the
|
|
369
|
+
delegation chain of the capability that is to be revoked. Only the expected
|
|
370
|
+
host value can and must be given as a parameter.
|
|
371
|
+
|
|
372
|
+
The expected values for checking the capability invocation will be:
|
|
373
|
+
|
|
374
|
+
host: `<expectedHost>`,
|
|
375
|
+
rootInvocationTarget: [
|
|
376
|
+
// root zcap with this target, RZ1, can be delegated w/target attenuation
|
|
377
|
+
// to allow delegates to revoke any zcap, Z1, with RZ1 as the root in its
|
|
378
|
+
// chain, even if the delegate is not a controller in Z1's chain
|
|
379
|
+
`<serviceObjectId>`,
|
|
380
|
+
// root zcap that this target, RZ2, can be used to revoke a zcap, Z2,
|
|
381
|
+
// with an "id" of `revocationId`; RZ2's controller will be populated
|
|
382
|
+
// using all controllers from Z2's chain, enabling any controller in that
|
|
383
|
+
// zcap's chain to invoke RZ2 to revoke Z2
|
|
384
|
+
`<serviceObjectId>/zcaps/revocations/<revocationId>`,
|
|
385
|
+
],
|
|
386
|
+
action: 'write'
|
|
387
|
+
.
|
|
388
|
+
|
|
389
|
+
**Kind**: global function
|
|
390
|
+
**Returns**: <code>function</code> - Returns an Express.js style middleware route handler.
|
|
211
391
|
|
|
212
392
|
| Param | Type | Description |
|
|
213
393
|
| --- | --- | --- |
|
|
214
394
|
| options | <code>object</code> | Options hashmap. |
|
|
215
395
|
| options.documentLoader | <code>object</code> | Document loader used to load DID Documents, capability documents, and JSON-LD Contexts. |
|
|
216
|
-
|
|
|
217
|
-
| options.
|
|
218
|
-
|
|
|
219
|
-
| options.
|
|
220
|
-
| [options.
|
|
221
|
-
|
|
|
396
|
+
| options.expectedHost | <code>string</code> | The expected host header value when checking the zcap invocation. |
|
|
397
|
+
| options.getRootController | <code>function</code> | Used to get the controller of the root capability for the service object. |
|
|
398
|
+
| options.getVerifier | <code>function</code> | An async function to call to get a verifier and verification method for the key ID. |
|
|
399
|
+
| [options.inspectCapabilityChain] | <code>function</code> | A function that can inspect a capability chain, e.g., to check for revocations; it will be used when verifying the invocation and the delegation chain for the to-be-revoked capability. |
|
|
400
|
+
| [options.onError] | <code>function</code> | An error handler handler for customizable error handling. |
|
|
401
|
+
| options.suiteFactory | <code>object</code> | A factory for creating the supported suite(s) to use when verifying zcap delegation chains; this is different from `getVerifier` which is used to produce a verifier for verifying HTTP signatures used to invoke zcaps. |
|
|
402
|
+
|
|
403
|
+
<a name="GetExpectedValues"></a>
|
|
404
|
+
|
|
405
|
+
## GetExpectedValues
|
|
406
|
+
**Kind**: global typedef
|
|
407
|
+
<a name="GetExpectedValues"></a>
|
|
408
|
+
|
|
409
|
+
## GetExpectedValues ⇒ [<code>ExpectedValues</code>](#ExpectedValues)
|
|
410
|
+
A function for returning expected values when checking a zcap invocation.
|
|
411
|
+
|
|
412
|
+
**Kind**: global typedef
|
|
413
|
+
**Returns**: [<code>ExpectedValues</code>](#ExpectedValues) - - The expected values.
|
|
414
|
+
|
|
415
|
+
| Param | Type | Description |
|
|
416
|
+
| --- | --- | --- |
|
|
417
|
+
| options | <code>object</code> | The options passed to the function. |
|
|
418
|
+
| options.req | <code>object</code> | The express request. |
|
|
419
|
+
|
|
420
|
+
<a name="ExpectedValues"></a>
|
|
421
|
+
|
|
422
|
+
## ExpectedValues : <code>object</code>
|
|
423
|
+
The expected values for checking a zcap invocation performed via an HTTP
|
|
424
|
+
request.
|
|
425
|
+
|
|
426
|
+
**Kind**: global typedef
|
|
427
|
+
**Properties**
|
|
428
|
+
|
|
429
|
+
| Name | Type | Description |
|
|
430
|
+
| --- | --- | --- |
|
|
431
|
+
| [action] | <code>string</code> | The expected capability action; if no action is specified during an invocation check, then a default action will be determined based on the HTTP method from the request -- which is only safe provided that the handler code path is also determined based on the HTTP method in the request (i.e., typical method-based express/connect routing); if the handler code path is determined by some other means, e.g., the request body, then `action` MUST be set. |
|
|
432
|
+
| host | <code>string</code> | The expected host in the request header. |
|
|
433
|
+
| rootInvocationTarget | <code>string</code> \| <code>Array</code> | The expected invocation target for every acceptable root capability; each string must express an absolute URI. |
|
|
434
|
+
| [target] | <code>string</code> | The expected invocation target; if no target is specified during an invocation check, then the target will default to the absolute URL computed from the relative request URL and expected host value. |
|
|
435
|
+
|
|
222
436
|
|
|
223
437
|
## Contribute
|
|
224
438
|
|
|
@@ -237,3 +451,5 @@ Digital Bazaar: support@digitalbazaar.com
|
|
|
237
451
|
## License
|
|
238
452
|
|
|
239
453
|
[New BSD License (3-clause)](LICENSE) © Digital Bazaar
|
|
454
|
+
|
|
455
|
+
[Web Crypto API]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API
|
package/lib/authorize.js
CHANGED
|
@@ -8,9 +8,11 @@ import {verifyCapabilityInvocation} from
|
|
|
8
8
|
'@digitalbazaar/http-signature-zcap-verify';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Authorizes an incoming request.
|
|
12
|
-
*
|
|
13
11
|
* @typedef GetExpectedValues - See helpers.js.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Authorizes an incoming request.
|
|
14
16
|
*
|
|
15
17
|
* @param {object} options - Options hashmap.
|
|
16
18
|
* @param {boolean} [options.allowTargetAttenuation=true] - Allow the
|
|
@@ -22,7 +24,7 @@ import {verifyCapabilityInvocation} from
|
|
|
22
24
|
* expected values when checking the zcap invocation.
|
|
23
25
|
* @param {Function} options.getRootController - Used to get the controller
|
|
24
26
|
* of the root capability in the invoked capability's chain.
|
|
25
|
-
* @param {Function
|
|
27
|
+
* @param {Function} options.getVerifier - An async function to
|
|
26
28
|
* call to get a verifier and verification method for the key ID.
|
|
27
29
|
* @param {Function} [options.inspectCapabilityChain] - A function that can
|
|
28
30
|
* inspect a capability chain, e.g., to check for revocations.
|
|
@@ -36,7 +38,7 @@ import {verifyCapabilityInvocation} from
|
|
|
36
38
|
* @param {number} [options.maxDelegationTtl=1000*60*60*24*90] - The maximum
|
|
37
39
|
* milliseconds to live for a delegated zcap as measured by the time
|
|
38
40
|
* difference between `expires` and `created` on the delegation proof.
|
|
39
|
-
* @param {Function} [options.onError] - An error handler handler for
|
|
41
|
+
* @param {Function} [options.onError] - An error handler handler for
|
|
40
42
|
* customizable error handling.
|
|
41
43
|
* @param {object} options.suiteFactory - A factory for creating the
|
|
42
44
|
* supported suite(s) to use when verifying zcap delegation chains; this is
|
|
@@ -106,6 +108,14 @@ export function authorizeZcapInvocationAfterParse({
|
|
|
106
108
|
suite: await suiteFactory({req}),
|
|
107
109
|
headers,
|
|
108
110
|
expectedHost,
|
|
111
|
+
async beforeValidatePurpose({
|
|
112
|
+
purpose, proof, capability, capabilityAction
|
|
113
|
+
}) {
|
|
114
|
+
// provide access to invocation parameters
|
|
115
|
+
req.ezcap.invocationParameters = {
|
|
116
|
+
purpose, proof, capability, capabilityAction
|
|
117
|
+
};
|
|
118
|
+
},
|
|
109
119
|
documentLoader: helpers.createRootCapabilityLoader({
|
|
110
120
|
documentLoader, getRootController, req
|
|
111
121
|
}),
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (c) 2021 Digital Bazaar, Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// translate `main.js` to CommonJS
|
|
7
|
-
require = require('esm')(module);
|
|
8
|
-
module.exports = require('./main.js');
|
|
4
|
+
export {authorizeZcapInvocation} from './authorize.js';
|
|
5
|
+
export {authorizeZcapRevocation} from './revoke.js';
|
package/lib/revoke.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* Copyright (c) 2021-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
import * as helpers from './helpers.js';
|
|
5
|
-
import * as jsigs from 'jsonld-signatures';
|
|
6
5
|
import assert from 'assert-plus';
|
|
7
6
|
import asyncHandler from 'express-async-handler';
|
|
8
7
|
import {authorizeZcapInvocationAfterParse} from './authorize.js';
|
|
9
8
|
import {CapabilityDelegation} from '@digitalbazaar/zcap';
|
|
9
|
+
import {createRequire} from 'node:module';
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const jsigs = require('jsonld-signatures');
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Authorizes a request to submit a zcap revocation.
|
|
@@ -86,7 +88,7 @@ import {CapabilityDelegation} from '@digitalbazaar/zcap';
|
|
|
86
88
|
* when checking the zcap invocation.
|
|
87
89
|
* @param {Function} options.getRootController - Used to get the controller
|
|
88
90
|
* of the root capability for the service object.
|
|
89
|
-
* @param {Function
|
|
91
|
+
* @param {Function} options.getVerifier - An async function to
|
|
90
92
|
* call to get a verifier and verification method for the key ID.
|
|
91
93
|
* @param {Function} [options.inspectCapabilityChain] - A function that can
|
|
92
94
|
* inspect a capability chain, e.g., to check for revocations; it will be
|
|
@@ -192,6 +194,9 @@ function createCheckRevocationMiddleware({
|
|
|
192
194
|
return helpers.handleError({res, error, onError});
|
|
193
195
|
}
|
|
194
196
|
|
|
197
|
+
// set capability to be revoked to enable access in other helpers
|
|
198
|
+
req.ezcap.capabilityToRevoke = capability;
|
|
199
|
+
|
|
195
200
|
// verify CapabilityDelegation
|
|
196
201
|
let delegator;
|
|
197
202
|
const capture = {};
|
|
@@ -235,10 +240,6 @@ async function _verifyDelegation({
|
|
|
235
240
|
// the expected values for the invocation are the same as those for checking
|
|
236
241
|
// the revocation delegation chain per the reasoning given in notes above
|
|
237
242
|
const {expectedRootCapability} = req.ezcap;
|
|
238
|
-
/* Note: We build the `expectedRootCapability` for the revoked capability
|
|
239
|
-
from the capability invocation expected values here. This is ok because the
|
|
240
|
-
revocation middleware feature presumes that the only zcaps that may be
|
|
241
|
-
revoked using it are rooted in the same authority... FIXME */
|
|
242
243
|
const {verified, error, results} = await jsigs.verify(capability, {
|
|
243
244
|
documentLoader,
|
|
244
245
|
purpose: new CapabilityDelegation({
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitalbazaar/ezcap-express",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": "./lib/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"lib/**/*.js"
|
|
8
|
+
],
|
|
6
9
|
"repository": {
|
|
7
10
|
"type": "git",
|
|
8
11
|
"url": "git@github.com:digitalbazaar/ezcap-express.git"
|
|
@@ -14,48 +17,52 @@
|
|
|
14
17
|
},
|
|
15
18
|
"scripts": {
|
|
16
19
|
"generate-readme": "jsdoc2md -t readme-template.hbs lib/*.js > README.md",
|
|
17
|
-
"lint": "eslint .",
|
|
18
20
|
"test": "npm run test-node",
|
|
19
|
-
"test-node": "cross-env NODE_ENV=test mocha
|
|
20
|
-
"coverage": "cross-env NODE_ENV=test
|
|
21
|
-
"coverage-ci": "cross-env NODE_ENV=test
|
|
22
|
-
"coverage-report": "
|
|
21
|
+
"test-node": "cross-env NODE_ENV=test mocha --preserve-symlinks -t 30000 -A -R ${REPORTER:-spec} --require tests/test-mocha.js tests/*.spec.js",
|
|
22
|
+
"coverage": "cross-env NODE_ENV=test c8 run test-node",
|
|
23
|
+
"coverage-ci": "cross-env NODE_ENV=test c8 --reporter=lcovonly --reporter=text-summary --reporter=text npm run test-node",
|
|
24
|
+
"coverage-report": "c8 report",
|
|
25
|
+
"lint": "eslint ."
|
|
23
26
|
},
|
|
24
27
|
"dependencies": {
|
|
25
|
-
"@digitalbazaar/http-digest-header": "^
|
|
26
|
-
"@digitalbazaar/http-signature-header": "^
|
|
27
|
-
"@digitalbazaar/http-signature-zcap-verify": "^
|
|
28
|
-
"@digitalbazaar/zcap": "^
|
|
28
|
+
"@digitalbazaar/http-digest-header": "^2.0.0",
|
|
29
|
+
"@digitalbazaar/http-signature-header": "^5.0.0",
|
|
30
|
+
"@digitalbazaar/http-signature-zcap-verify": "^11.0.0",
|
|
31
|
+
"@digitalbazaar/zcap": "^8.0.0",
|
|
29
32
|
"assert-plus": "^1.0.0",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"jsonld-signatures": "^9.3.0"
|
|
33
|
+
"express-async-handler": "^1.2.0",
|
|
34
|
+
"jsonld-signatures": "^10.0.0"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
|
-
"@digitalbazaar/did-method-key": "^
|
|
36
|
-
"@digitalbazaar/ed25519-signature-2020": "^
|
|
37
|
-
"@digitalbazaar/ed25519-verification-key-2020": "^
|
|
38
|
-
"@digitalbazaar/ezcap": "^
|
|
39
|
-
"@digitalbazaar/http-client": "^2.0
|
|
40
|
-
"@digitalbazaar/http-signature-zcap-invoke": "^
|
|
41
|
-
"@digitalbazaar/security-document-loader": "^
|
|
42
|
-
"bnid": "^
|
|
43
|
-
"
|
|
44
|
-
"chai
|
|
45
|
-
"cross-env": "^7.0.
|
|
46
|
-
"crypto-ld": "^
|
|
47
|
-
"eslint": "^
|
|
48
|
-
"eslint-config-digitalbazaar": "^
|
|
49
|
-
"eslint-plugin-jsdoc": "^
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
37
|
+
"@digitalbazaar/did-method-key": "^3.0.0",
|
|
38
|
+
"@digitalbazaar/ed25519-signature-2020": "^4.0.1",
|
|
39
|
+
"@digitalbazaar/ed25519-verification-key-2020": "^4.0.0",
|
|
40
|
+
"@digitalbazaar/ezcap": "^3.0.1",
|
|
41
|
+
"@digitalbazaar/http-client": "^3.2.0",
|
|
42
|
+
"@digitalbazaar/http-signature-zcap-invoke": "^6.0.0",
|
|
43
|
+
"@digitalbazaar/security-document-loader": "^2.0.0",
|
|
44
|
+
"bnid": "^3.0.0",
|
|
45
|
+
"c8": "^7.11.3",
|
|
46
|
+
"chai": "^4.3.6",
|
|
47
|
+
"cross-env": "^7.0.3",
|
|
48
|
+
"crypto-ld": "^7.0.0",
|
|
49
|
+
"eslint": "^8.17.0",
|
|
50
|
+
"eslint-config-digitalbazaar": "^3.0.0",
|
|
51
|
+
"eslint-plugin-jsdoc": "^39.3.2",
|
|
52
|
+
"eslint-plugin-unicorn": "^42.0.0",
|
|
53
|
+
"express": "^4.18.1",
|
|
54
|
+
"isomorphic-webcrypto": "^2.3.8",
|
|
55
|
+
"jsdoc-to-markdown": "^7.1.1",
|
|
56
|
+
"mocha": "^10.0.0"
|
|
54
57
|
},
|
|
55
58
|
"engines": {
|
|
56
|
-
"node": ">=14
|
|
59
|
+
"node": ">=14"
|
|
57
60
|
},
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
+
"c8": {
|
|
62
|
+
"reporter": [
|
|
63
|
+
"lcov",
|
|
64
|
+
"text-summary",
|
|
65
|
+
"text"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
61
68
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
# @digitalbazaar/ezcap-express Changelog
|
|
2
|
-
|
|
3
|
-
## 6.0.0 - 2022-03-01
|
|
4
|
-
|
|
5
|
-
### Changed
|
|
6
|
-
- **BREAKING**: Better future proof conventional zcap API endpoints by
|
|
7
|
-
prefixing `/revocations` route with `/zcaps`.
|
|
8
|
-
|
|
9
|
-
## 5.1.0 - 2022-01-14
|
|
10
|
-
|
|
11
|
-
### Added
|
|
12
|
-
- Use zcap@7.1 and http-signature-zcap-verify@10.1 to include
|
|
13
|
-
`dereferencedChain` in verification results and `req.zcap`.
|
|
14
|
-
|
|
15
|
-
## 5.0.1 - 2022-01-11
|
|
16
|
-
|
|
17
|
-
### Changed
|
|
18
|
-
- Update dependencies.
|
|
19
|
-
|
|
20
|
-
## 5.0.0 - 2022-01-11
|
|
21
|
-
|
|
22
|
-
### Added
|
|
23
|
-
- Add optional parameters `maxChainLength`, `maxDelegationTtl`, and
|
|
24
|
-
`maxTimestampDelta` to allow for more fine grained control. These parameters
|
|
25
|
-
all have defaults in `@digitalbazaar/zcap` that could previously not be set
|
|
26
|
-
to other values at this layer.
|
|
27
|
-
- **BREAKING**: Add required `getVerifier` async function parameter. The
|
|
28
|
-
function will be passed `{keyId, documentLoader}` to verify an HTTP signature
|
|
29
|
-
and must return `{verifier, verificationMethod}`. The `verifier` object must
|
|
30
|
-
have a `verify` function that takes `{data, signature}` and returns a
|
|
31
|
-
boolean indicating whether the `Uint8Array` `signature` is verified
|
|
32
|
-
against the `Uint8Array` `data` -- or throws an error if there is a reason
|
|
33
|
-
the cryptographic signature verification check cannot be run.
|
|
34
|
-
- Include `capabilityChain` in `req.zcapRevocation` when using revocation
|
|
35
|
-
middleware. This property includes the entire dereferenced chain.
|
|
36
|
-
|
|
37
|
-
### Changed
|
|
38
|
-
- **BREAKING**: Replace broken-out expected value parameters (e.g.,
|
|
39
|
-
`expectedHost`, `expectedTarget`), including duplicative / optional
|
|
40
|
-
parameters (e.g., `expectedAction`, `getExpectedAction`) with a single
|
|
41
|
-
async function `getExpectedValues({req})` that returns all required (and any
|
|
42
|
-
optional) expected values. This removes some optionality and simplifies
|
|
43
|
-
function signatures -- also allowing callers to decide how they want
|
|
44
|
-
to provide this information (e.g., by calling individual functions from
|
|
45
|
-
within `getExpectedValues` or whatever else).
|
|
46
|
-
- **BREAKING**: The `authorizeZcapRevocation` middleware may now only be used
|
|
47
|
-
on routes ending in `/revocations/:revocationId`. The API params have also
|
|
48
|
-
changed as the only expected value that is needed from the user is
|
|
49
|
-
`expectedHost`. The rest of the expected values are hard coded according to
|
|
50
|
-
a conventional pattern for supporting revocation of any zcaps delegated from
|
|
51
|
-
a root capability for a service object. The service object's root capability
|
|
52
|
-
MUST have an invocation target that matches the service object's URL (aka its
|
|
53
|
-
"ID", `<serviceObjectId>`). So for the absolute URL:
|
|
54
|
-
|
|
55
|
-
`<serviceObjectId>/revocations/:revocationId`
|
|
56
|
-
|
|
57
|
-
A zcap can only be revoked using the middleware if its chain has a root
|
|
58
|
-
zcap with an invocation target that is prefixed with `<serviceObjectId>`.
|
|
59
|
-
The middleware will use the `expectedHost` value to construct the absolute
|
|
60
|
-
URL.
|
|
61
|
-
- **BREAKING**: Require `suiteFactory` parameter, no default cryptosuites are
|
|
62
|
-
included with this package to ensure it is decoupled from particular
|
|
63
|
-
cryptosuites.
|
|
64
|
-
|
|
65
|
-
### Fixed
|
|
66
|
-
- **BREAKING**: HTTP status error codes have been fixed so that client errors
|
|
67
|
-
will result in 4xx status codes instead of 5xx status codes.
|
|
68
|
-
|
|
69
|
-
### Remove
|
|
70
|
-
- **BREAKING**: Remove `getExpectedRootCapabilityId` as there have been no
|
|
71
|
-
use cases that have needed it.
|
|
72
|
-
- **BREAKING**: Remove deprecated `suite` param, use `suiteFactory` instead.
|
|
73
|
-
|
|
74
|
-
## 4.5.0 - 2021-12-17
|
|
75
|
-
|
|
76
|
-
### Fixed
|
|
77
|
-
- Add `_createGetRevocationRootController` wrapper around
|
|
78
|
-
`_getRevocationRootController` and pass `getRootController` to it.
|
|
79
|
-
|
|
80
|
-
### Added
|
|
81
|
-
- Add tests for `authorizeZcapRevocation`.
|
|
82
|
-
|
|
83
|
-
## 4.4.0 - 2021-12-15
|
|
84
|
-
|
|
85
|
-
### Added
|
|
86
|
-
- Add additional tests.
|
|
87
|
-
|
|
88
|
-
## 4.3.1 - 2021-12-13
|
|
89
|
-
|
|
90
|
-
### Fixed
|
|
91
|
-
- Fix `expectedAction` to be `write` for `DELETE` method.
|
|
92
|
-
- Throw error when no `expectedAction` is given for a given HTTP method and
|
|
93
|
-
provide defaults for all common HTTP methods.
|
|
94
|
-
|
|
95
|
-
## 4.3.0 - 2021-12-10
|
|
96
|
-
|
|
97
|
-
### Added
|
|
98
|
-
- Allow any controller in a delegated zcap's chain to revoke it. This authority
|
|
99
|
-
is inherent in delegation and is now reflected in code. This feature gives
|
|
100
|
-
delegators more fine-grained control to revoke zcaps that they did not
|
|
101
|
-
delegate directly but one of their delegates did, allowing them to stop
|
|
102
|
-
specific zcap usage without having to revoke more of the chain. It also
|
|
103
|
-
gives zcap controllers the ability to revoke their own zcaps (if desired)
|
|
104
|
-
and adds a sanity check to prevent the revocation of root zcaps that use
|
|
105
|
-
the `urn:zcap:root:` ID scheme.
|
|
106
|
-
|
|
107
|
-
## 4.2.0 - 2021-08-26
|
|
108
|
-
|
|
109
|
-
### Added
|
|
110
|
-
- Add `suiteFactory` parameter to middleware creation functions. A
|
|
111
|
-
`suiteFactory` function should be passed and return the supported LD proof
|
|
112
|
-
suite (or an array of supported LD proof suites) that is supported for
|
|
113
|
-
authorizing zcap invocations and verifying capability chains.
|
|
114
|
-
- Add `authorizeZcapRevocation` middleware that can be attached to root
|
|
115
|
-
container/object endpoints to enable revocation of zcaps that have been
|
|
116
|
-
delegated to use them. This version assumes that the revocations endpoint
|
|
117
|
-
will follow this RESTful format: `<rootObjectUrl>/revocations/<zcapId>`
|
|
118
|
-
and that the body will be JSON and include a `capability` member with
|
|
119
|
-
the zcap to revoke. Future versions may allow for greater flexibility.
|
|
120
|
-
|
|
121
|
-
### Changed
|
|
122
|
-
- Deprecate passing a `suite` to any middleware creation functions. Instead,
|
|
123
|
-
`suiteFactory` should be passed. The next major version will remove `suite`.
|
|
124
|
-
This approach allows this library to remove npm dependencies that provide
|
|
125
|
-
cryptographic suites preventing this library from being affected when those
|
|
126
|
-
dependencies need to change.
|
|
127
|
-
|
|
128
|
-
## 4.1.1 - 2021-07-21
|
|
129
|
-
|
|
130
|
-
### Changed
|
|
131
|
-
- Updated dependencies.
|
|
132
|
-
|
|
133
|
-
## 4.1.0 - 2021-07-11
|
|
134
|
-
|
|
135
|
-
### Changed
|
|
136
|
-
- Updated http-signature-zcap-verify to 8.1.x to bring in optimizations
|
|
137
|
-
for controllers that use DID Documents.
|
|
138
|
-
|
|
139
|
-
## 4.0.1 - 2021-07-10
|
|
140
|
-
|
|
141
|
-
### Fixed
|
|
142
|
-
- Fix http-signature-zcap-verify dependency to use 8.x to function
|
|
143
|
-
properly with updated ed25519 libs.
|
|
144
|
-
|
|
145
|
-
## 4.0.0 - 2021-07-10
|
|
146
|
-
|
|
147
|
-
### Changed
|
|
148
|
-
- **BREAKING**: Updated to use `@digitalbazaar/ed25519-signature-2020` 3.x
|
|
149
|
-
and related libraries. These changes include breaking fixes to key
|
|
150
|
-
formats.
|
|
151
|
-
|
|
152
|
-
## 3.4.2 - 2021-07-10
|
|
153
|
-
|
|
154
|
-
### Fixed
|
|
155
|
-
- Fix bug with erroneously detecting request bodies. Some body
|
|
156
|
-
parsing middleware for express/connect (e.g., the main body-parser
|
|
157
|
-
npm package) will set a request body to an empty object even when
|
|
158
|
-
no body is present. This previously caused an error to be thrown
|
|
159
|
-
because no body digest header was present. The code has been updated
|
|
160
|
-
to check for http body headers per the spec now (instead of trusting
|
|
161
|
-
the `req.body` value) and it will set the `req.body` value to
|
|
162
|
-
`undefined` if it is not present.
|
|
163
|
-
|
|
164
|
-
## 3.4.1 - 2021-07-10
|
|
165
|
-
|
|
166
|
-
### Fixed
|
|
167
|
-
- Fix error handling bugs. Http signature errors thrown by the
|
|
168
|
-
middleware created via `authorizeZcapInvocation` will now be
|
|
169
|
-
properly passed to the `onError` handler.
|
|
170
|
-
|
|
171
|
-
## 3.4.0 - 2021-06-28
|
|
172
|
-
|
|
173
|
-
### Added
|
|
174
|
-
- Add missing `allowTargetAttenuation` option that defaults to `true`
|
|
175
|
-
to support RESTful-based attenuated delegation as the documentation
|
|
176
|
-
describes.
|
|
177
|
-
|
|
178
|
-
## 3.3.0 - 2021-05-19
|
|
179
|
-
|
|
180
|
-
### Added
|
|
181
|
-
- Verify HTTP "digest" header when a "content-type" header or body is present.
|
|
182
|
-
|
|
183
|
-
## 3.2.0 - 2021-05-13
|
|
184
|
-
|
|
185
|
-
### Added
|
|
186
|
-
- Add ability to specify an `inspectCapabilityChain` hook.
|
|
187
|
-
|
|
188
|
-
## 3.1.0 - 2021-05-11
|
|
189
|
-
|
|
190
|
-
### Added
|
|
191
|
-
- Add optional `getExpectedAction({req})` hook to provide expected action
|
|
192
|
-
based on, e.g., request body vs. HTTP method.
|
|
193
|
-
|
|
194
|
-
## 3.0.1 - 2021-04-06
|
|
195
|
-
|
|
196
|
-
### Fixed
|
|
197
|
-
- **BREAKING**: Change the default signature suite in `authorizeZcapInvocation`
|
|
198
|
-
to `Ed25519Signature2020` (was `Ed25519Signature2018` before). This change
|
|
199
|
-
should have been included in the 3.0 release.
|
|
200
|
-
|
|
201
|
-
### Changed
|
|
202
|
-
- Remove `jsonld-signatures` dependency.
|
|
203
|
-
|
|
204
|
-
## 3.0.0 - 2021-04-01
|
|
205
|
-
|
|
206
|
-
### Changed
|
|
207
|
-
- **BREAKING**: Use `http-signature-zcap-verify@5` which only supports
|
|
208
|
-
`Ed25519Signature2020` proofs.
|
|
209
|
-
|
|
210
|
-
## 2.0.0 - 2021-03-29
|
|
211
|
-
|
|
212
|
-
### Added
|
|
213
|
-
- Add optional `onError` handler for customizable error handling.
|
|
214
|
-
|
|
215
|
-
### Changed
|
|
216
|
-
- **BREAKING**: Replace `expectedTarget` parameter with `getExpectedTarget`.
|
|
217
|
-
`getExpectedTarget` is an async function used to return the expected
|
|
218
|
-
target(s) for the invoked capability.
|
|
219
|
-
- **BREAKING**: Remove the `logger` parameter. Errors may now be logged by the
|
|
220
|
-
`onError` handler.
|
|
221
|
-
|
|
222
|
-
## 1.0.1 - 2021-03-02
|
|
223
|
-
|
|
224
|
-
### Fixed
|
|
225
|
-
- Use `http-signature-zcap-verify@4`.
|
|
226
|
-
|
|
227
|
-
## 1.0.0 - 2021-03-02
|
|
228
|
-
|
|
229
|
-
### Added
|
|
230
|
-
- Initial commit, see individual commits for history.
|