@interop/ezcap 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/LICENSE +29 -0
- package/README.md +379 -0
- package/dist/ZcapClient.d.ts +238 -0
- package/dist/ZcapClient.d.ts.map +1 -0
- package/dist/ZcapClient.js +404 -0
- package/dist/ZcapClient.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/util.d.ts +70 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +92 -0
- package/dist/util.js.map +1 -0
- package/package.json +86 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020, Digital Bazaar, Inc.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# ezcap (_@interop/ezcap_)
|
|
2
|
+
|
|
3
|
+
[](https://github.com/interop-alliance/ezcap/actions?query=workflow%3ACI)
|
|
4
|
+
[](https://npm.im/@interop/ezcap)
|
|
5
|
+
|
|
6
|
+
> An easy to use, opinionated Authorization Capabilities (zcap) client library
|
|
7
|
+
> for the browser and Node.js.
|
|
8
|
+
|
|
9
|
+
This is an [Interop Alliance](https://github.com/interop-alliance) fork of the
|
|
10
|
+
Digital Credentials / Digital Bazaar `ezcap`, switched to the `@interop`
|
|
11
|
+
dependency forks and converted from JavaScript to TypeScript.
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Background](#background)
|
|
16
|
+
- [Security](#security)
|
|
17
|
+
- [Install](#install)
|
|
18
|
+
- [Usage](#usage)
|
|
19
|
+
- [API Reference](#api-reference)
|
|
20
|
+
- [Contribute](#contribute)
|
|
21
|
+
- [Commercial Support](#commercial-support)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
## Background
|
|
25
|
+
|
|
26
|
+
This library provides a client that browser and node.js applications can use to
|
|
27
|
+
interact with HTTP servers protected by zcap-based authorization. The library
|
|
28
|
+
is configured with secure and sensible defaults to help developers get started
|
|
29
|
+
quickly and ensure that their client code is production-ready.
|
|
30
|
+
|
|
31
|
+
## Security
|
|
32
|
+
|
|
33
|
+
The security characteristics of this library are largely influenced by design
|
|
34
|
+
decisions made by client and server software. For clients, implementers should
|
|
35
|
+
pay particular attention to secure private key management. For servers, security
|
|
36
|
+
characteristics are largely dependent on how carefully the server manages zcap
|
|
37
|
+
registrations, zcap invocations, and zcap delegations. Bugs or failures related
|
|
38
|
+
to client key management, or server zcap validity checking will lead to security
|
|
39
|
+
failures. It is imperative that implementers audit their implementations,
|
|
40
|
+
preferably via parties other than the implementer.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
- Browsers and Node.js 20+ are supported.
|
|
45
|
+
- This package is ESM-only (`"type": "module"`).
|
|
46
|
+
|
|
47
|
+
To install from NPM:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
npm install @interop/ezcap
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
To install locally (for development), using [pnpm](https://pnpm.io/):
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
git clone https://github.com/interop-alliance/ezcap.git
|
|
57
|
+
cd ezcap
|
|
58
|
+
pnpm install
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
* [Creating a Client](#creating-a-client)
|
|
64
|
+
* [Reading with a Root Capability](#reading-with-a-root-capability)
|
|
65
|
+
* [Writing with a Root Capability](#writing-with-a-root-capability)
|
|
66
|
+
* [Delegating a Capability](#delegating-a-capability)
|
|
67
|
+
* [Reading with a Delegated Capability](#reading-with-a-delegated-capability)
|
|
68
|
+
* [Writing with a Delegated Capability](#writing-with-a-delegated-capability)
|
|
69
|
+
* [Requesting with a Root Capability](#requesting-with-a-root-capability)
|
|
70
|
+
* [Requesting with a Delegated Capability](#requesting-with-a-delegated-capability)
|
|
71
|
+
|
|
72
|
+
### Creating a Client
|
|
73
|
+
|
|
74
|
+
Creating a zcap client involves generating cryptographic key material and then
|
|
75
|
+
using that key material to instantiate a client designed to operate on a
|
|
76
|
+
specific base URL.
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { ZcapClient } from '@interop/ezcap'
|
|
80
|
+
import * as didKey from '@interop/did-method-key'
|
|
81
|
+
import { Ed25519Signature2020 } from '@interop/ed25519-signature'
|
|
82
|
+
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'
|
|
83
|
+
|
|
84
|
+
const didKeyDriver = didKey.driver()
|
|
85
|
+
didKeyDriver.use({ keyPairClass: Ed25519VerificationKey })
|
|
86
|
+
|
|
87
|
+
// generate a DID Document and set of key pairs
|
|
88
|
+
const { didDocument, keyPairs } = await didKeyDriver.generate()
|
|
89
|
+
|
|
90
|
+
// create a new zcap client using the generated cryptographic material
|
|
91
|
+
const zcapClient = new ZcapClient({
|
|
92
|
+
didDocument,
|
|
93
|
+
keyPairs,
|
|
94
|
+
SuiteClass: Ed25519Signature2020
|
|
95
|
+
})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Reading with a Root Capability
|
|
99
|
+
|
|
100
|
+
Reading data from a URL using a capability is performed in a way that is
|
|
101
|
+
very similar to using a regular HTTP client to perform an HTTP GET. Using
|
|
102
|
+
a root capability means that your client has been directly authorized to access
|
|
103
|
+
the URL, usually because it created the resource that is being accessed.
|
|
104
|
+
The term "root" means that your client is the "root of authority".
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
const url = 'https://zcap.example/my-account/items';
|
|
108
|
+
|
|
109
|
+
// reading a URL using a zcap will result in an HTTP Response
|
|
110
|
+
const response = await zcapClient.read({url});
|
|
111
|
+
|
|
112
|
+
// retrieve the JSON data
|
|
113
|
+
const items = await response.json();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Writing with a Root Capability
|
|
117
|
+
|
|
118
|
+
Writing data to URL using a capability is performed in a way that is
|
|
119
|
+
very similar to using a regular HTTP client to perform an HTTP POST. Using
|
|
120
|
+
a root capability means that your client has been directly authorized to
|
|
121
|
+
modify the resource at the URL, usually because it created the resource that is
|
|
122
|
+
being written to. The term "root" means that your client is the "root of
|
|
123
|
+
authority". In the example below, the server most likely registered the
|
|
124
|
+
client as being the root authority for the `/my-account` path on the server.
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
const url = 'https://zcap.example/my-account/items';
|
|
128
|
+
const item = {label: 'Widget'};
|
|
129
|
+
|
|
130
|
+
// writing a URL using a zcap will result in an HTTP Response
|
|
131
|
+
const response = await zcapClient.write({url, json: item});
|
|
132
|
+
|
|
133
|
+
// process the response appropriately
|
|
134
|
+
const writtenItem = await response.json();
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Delegating a Capability
|
|
138
|
+
|
|
139
|
+
Delegating a capability consists of the client authorizing another entity to
|
|
140
|
+
use the capability. The example below uses a DID as the target for the
|
|
141
|
+
delegation. The returned `delegatedCapability` would need to be transmitted
|
|
142
|
+
to the entity identified by the delegation target so that they can use it
|
|
143
|
+
to access the resource.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
const invocationTarget = 'https://zcap.example/my-account/items';
|
|
147
|
+
const controller =
|
|
148
|
+
'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH';
|
|
149
|
+
const allowedActions = ['read'];
|
|
150
|
+
const delegatedCapability = zcapClient.delegate(
|
|
151
|
+
{invocationTarget, controller, allowedActions});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Reading with a Delegated Capability
|
|
155
|
+
|
|
156
|
+
Reading with a delegated capability is similar to reading with a root
|
|
157
|
+
capability. The only difference is that the delegated capability needs to be
|
|
158
|
+
retrieved from somewhere using application-specific code and then passed
|
|
159
|
+
to the `read` method.
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
const url = 'https://zcap.example/my-account/items/123';
|
|
163
|
+
// defined by your code
|
|
164
|
+
const capability = await getCapabilityFromDatabase({url});
|
|
165
|
+
|
|
166
|
+
// reading a URL using a zcap will result in an HTTP Response; the
|
|
167
|
+
// `invocationTarget` from the capability provides the URL if one is not
|
|
168
|
+
// specified; if a URL is specified, the capability's invocation target
|
|
169
|
+
// MUST be a RESTful prefix of or equivalent to the URL
|
|
170
|
+
const response = await zcapClient.read({capability});
|
|
171
|
+
|
|
172
|
+
// retrieve the JSON data
|
|
173
|
+
const items = await response.json();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Writing with a Delegated Capability
|
|
177
|
+
|
|
178
|
+
Writing with a delegated capability is similar to writing with a root
|
|
179
|
+
capability. The only difference is that the delegated capability needs to be
|
|
180
|
+
retrieved from somewhere using application-specific code and then passed
|
|
181
|
+
to the `write` method.
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
const item = {label: 'Widget'};
|
|
186
|
+
const url = 'https://zcap.example/my-account/items';
|
|
187
|
+
// defined by your code
|
|
188
|
+
const capability = await getCapabilityFromDatabase({url});
|
|
189
|
+
|
|
190
|
+
// writing a URL using a zcap will result in an HTTP Response; the
|
|
191
|
+
// `invocationTarget` from the capability provides the URL if one is not
|
|
192
|
+
// specified; if a URL is specified, the capability's invocation target
|
|
193
|
+
// MUST be a RESTful prefix of or equivalent to the URL
|
|
194
|
+
const response = await zcapClient.write({capability, json: item});
|
|
195
|
+
|
|
196
|
+
// process the response appropriately
|
|
197
|
+
const writtenItem = await response.json();
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Requesting with a non-JSON binary blob body
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
const body = new Blob(['line 1\nline2\n'], {type: 'text/plain'})
|
|
204
|
+
await zcapClient.request({
|
|
205
|
+
url, method: 'POST', body
|
|
206
|
+
})
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Requesting with a Root Capability
|
|
210
|
+
|
|
211
|
+
In the event that the server API does not operate using HTTP GET and HTTP POST,
|
|
212
|
+
it is possible to create a zcap client request that uses other HTTP verbs. This
|
|
213
|
+
is done by specifying the HTTP `method` to use.
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
const url = 'https://zcap.example/my-account/items';
|
|
217
|
+
const item = {count: 12};
|
|
218
|
+
|
|
219
|
+
// send a request to a URL by invoking a capability
|
|
220
|
+
const response = await zcapClient.request({url, method: 'patch', json: item});
|
|
221
|
+
|
|
222
|
+
// process the response appropriately
|
|
223
|
+
const updatedItem = await response.json();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Requesting with a Delegated Capability
|
|
227
|
+
|
|
228
|
+
Performing an HTTP request with a delegated capability is similar to
|
|
229
|
+
doing the same with a root capability. The only difference is that the
|
|
230
|
+
delegated capability needs to be retrieved from somewhere using application-specific code and then passed to the `request` method.
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
const item = {count: 12};
|
|
234
|
+
const url = 'https://zcap.example/my-account/items/123';
|
|
235
|
+
// defined by your code
|
|
236
|
+
const capability = await getCapabilityFromDatabase({url});
|
|
237
|
+
|
|
238
|
+
// invoking a capability against a URL will result in an HTTP Response; the
|
|
239
|
+
// `invocationTarget` from the capability provides the URL if one is not
|
|
240
|
+
// specified; if a URL is specified, the capability's invocation target
|
|
241
|
+
// MUST be a RESTful prefix of or equivalent to the URL
|
|
242
|
+
const response = await zcapClient.request(
|
|
243
|
+
{capability, method: 'patch', json: item});
|
|
244
|
+
|
|
245
|
+
// process the response appropriately
|
|
246
|
+
const updatedItem = await response.json();
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## API Reference
|
|
250
|
+
|
|
251
|
+
The ezcap approach is opinionated in order to make using zcaps a pleasant
|
|
252
|
+
experience for developers. To do this, it makes two fundamental assumptions
|
|
253
|
+
regarding the systems it interacts with:
|
|
254
|
+
|
|
255
|
+
* The systems are HTTP-based and REST-ful in nature.
|
|
256
|
+
* The REST-ful systems center around reading and writing resources.
|
|
257
|
+
|
|
258
|
+
If these assumptions do not apply to your system, the
|
|
259
|
+
[`@interop/zcap`](https://github.com/interop-alliance/zcap) library might
|
|
260
|
+
be a better, albeit more complex, solution for you.
|
|
261
|
+
|
|
262
|
+
Looking at each of these core assumptions more closely will help explain how designing systems to these constraints make it much easier to think about
|
|
263
|
+
zcaps. Let's take a look at the first assumption:
|
|
264
|
+
|
|
265
|
+
> The systems are HTTP-based and REST-ful in nature.
|
|
266
|
+
|
|
267
|
+
Many modern systems tend to have HTTP-based interfaces that are REST-ful in
|
|
268
|
+
nature. That typically means that most resource URLs are organized by namespaces, collections, and items:
|
|
269
|
+
`/<root-namespace>/<collection-id>/<item-id>`. In practice,
|
|
270
|
+
this tends to manifest itself as URLs that look like
|
|
271
|
+
`/my-account/things/1`. The ezcap approach maps the authorization model
|
|
272
|
+
in a 1-to-1 way to the URL. Following along with the example, the root
|
|
273
|
+
capability would then be `/my-account`, which you will typically create and
|
|
274
|
+
have access to. You can then take that root capability and delegate access
|
|
275
|
+
to things like `/my-account/things` to let entities you trust modify the
|
|
276
|
+
`things` collection. You can also choose to be more specific and only
|
|
277
|
+
delegate to `/my-account/things/1` to really lock down access. ezcap attempts
|
|
278
|
+
to keep things very simple by mapping URL hierarchy to authorization scope.
|
|
279
|
+
|
|
280
|
+
Now, let's examine the second assumption that makes things easier:
|
|
281
|
+
|
|
282
|
+
> The REST-ful systems center around reading and writing resources.
|
|
283
|
+
|
|
284
|
+
There is an incredible amount of flexibility that zcaps provide. You can
|
|
285
|
+
define a variety of actions: read, write, bounce, atomicSwap, start, etc.
|
|
286
|
+
However, all that flexibility adds complexity and one of the goals of ezcap
|
|
287
|
+
is to reduce complexity to the point where the solution is good enough for
|
|
288
|
+
80% of the use cases. A large amount of REST-ful interactions tend to
|
|
289
|
+
revolve around reading and writing collections and the items in those
|
|
290
|
+
collections. For this reason, there are only two actions that are exposed
|
|
291
|
+
by default in ezcap: read and write. Keeping the number of actions to a
|
|
292
|
+
bare minimum has allowed implementers to achieve very complex use cases with
|
|
293
|
+
very simple code.
|
|
294
|
+
|
|
295
|
+
These are the two assumptions that ezcap makes and with those two assumptions,
|
|
296
|
+
80% of all use cases we've encountered are covered.
|
|
297
|
+
|
|
298
|
+
### `new ZcapClient(options)`
|
|
299
|
+
|
|
300
|
+
Creates a new `ZcapClient` instance for performing requests against HTTP URLs
|
|
301
|
+
authorized via Authorization Capabilities (zcaps). Provide a signing
|
|
302
|
+
`SuiteClass`, plus **either** `{ didDocument, keyPairs }` (the invocation and
|
|
303
|
+
delegation signers are derived via `getCapabilitySigners`) **or** explicit
|
|
304
|
+
`{ invocationSigner, delegationSigner }`.
|
|
305
|
+
|
|
306
|
+
| Param | Type | Description |
|
|
307
|
+
| --- | --- | --- |
|
|
308
|
+
| `options.SuiteClass` | `LinkedDataSignatureSuiteClass` | The Linked Data Signature suite class used to sign requests and delegations (e.g. `Ed25519Signature2020`). Required. |
|
|
309
|
+
| `options.didDocument` | `object` | A DID Document with `capabilityInvocation` and `capabilityDelegation` verification relationships. Use together with `keyPairs`. |
|
|
310
|
+
| `options.keyPairs` | `Map` | A map of key pairs associated with `didDocument`, indexed by key id. |
|
|
311
|
+
| `options.invocationSigner` | `object` | A signer (`.sign()`, `id`, `controller`) used for signing requests. Alternative to `didDocument` + `keyPairs`. |
|
|
312
|
+
| `options.delegationSigner` | `object` | A signer (`.sign()`, `id`, `controller`) used for delegating zcaps. Alternative to `didDocument` + `keyPairs`. |
|
|
313
|
+
| `options.agent` | `HttpsAgent` | Optional Node.js HTTPS agent for connection reuse. |
|
|
314
|
+
| `options.defaultHeaders` | `object` | Optional default HTTP headers included on every invocation request. |
|
|
315
|
+
| `options.documentLoader` | `function` | Optional document loader for suite-related contexts. If omitted, one is auto-generated from the suite class's static `CONTEXT` / `CONTEXT_URL`. |
|
|
316
|
+
|
|
317
|
+
### `zcapClient.delegate(options) ⇒ Promise<ZcapObject>`
|
|
318
|
+
|
|
319
|
+
Delegates an Authorization Capability to a target controller. Returns the signed
|
|
320
|
+
delegated zcap.
|
|
321
|
+
|
|
322
|
+
| Param | Type | Description |
|
|
323
|
+
| --- | --- | --- |
|
|
324
|
+
| `options.controller` | `string` | The URL/DID identifying the entity to delegate to (the party that will control the new zcap). Required. |
|
|
325
|
+
| `options.capability` | `string \| object` | The parent capability to delegate. Must be an object if it is a delegated zcap; may be a string for a root zcap (then `invocationTarget` is required). If omitted, a root zcap is auto-generated for `invocationTarget`. |
|
|
326
|
+
| `options.invocationTarget` | `string` | Optional invocation target used to narrow a `capability`'s existing target. Defaults to `capability.invocationTarget`. |
|
|
327
|
+
| `options.expires` | `string \| Date` | Optional expiration. Default: 5 minutes after `Date.now()`. |
|
|
328
|
+
| `options.allowedActions` | `string \| string[]` | Optional allowed action(s). Default: `[]` (delegate all actions). |
|
|
329
|
+
|
|
330
|
+
### `zcapClient.request(options) ⇒ Promise<Response>`
|
|
331
|
+
|
|
332
|
+
Performs an HTTP request authorized by a zcap and/or a target URL. If no URL is
|
|
333
|
+
given, the capability's invocation target is used. A string `capability` MUST be
|
|
334
|
+
a root capability. If both `url` and `capability` are given, the capability's
|
|
335
|
+
invocation target MUST be a RESTful prefix of (or equal to) the URL.
|
|
336
|
+
|
|
337
|
+
| Param | Type | Description |
|
|
338
|
+
| --- | --- | --- |
|
|
339
|
+
| `options.url` | `string` | The URL to invoke against; required if no `capability` is provided. |
|
|
340
|
+
| `options.capability` | `string \| object` | The capability to invoke. Default: a root capability generated from `options.url`. |
|
|
341
|
+
| `options.method` | `string` | The HTTP method. Default: `'GET'`. |
|
|
342
|
+
| `options.action` | `string` | The capability action being invoked. Default: same as `method`. |
|
|
343
|
+
| `options.headers` | `object` | Additional headers to sign and send. Default: `{}`. |
|
|
344
|
+
| `options.json` | `object` | The JSON body, if any, to send. |
|
|
345
|
+
| `options.body` | `Blob \| Uint8Array` | A non-JSON body to send (file uploads, binary blobs, etc.). |
|
|
346
|
+
|
|
347
|
+
### `zcapClient.read(options) ⇒ Promise<Response>`
|
|
348
|
+
|
|
349
|
+
Convenience wrapper for a `GET` / `read` invocation. Accepts `url`, `headers`,
|
|
350
|
+
and `capability` (see `request`).
|
|
351
|
+
|
|
352
|
+
### `zcapClient.write(options) ⇒ Promise<Response>`
|
|
353
|
+
|
|
354
|
+
Convenience wrapper for a `POST` / `write` invocation. Accepts `url`, `json`,
|
|
355
|
+
`body`, `headers`, and `capability` (see `request`).
|
|
356
|
+
|
|
357
|
+
### `getCapabilitySigners(options) ⇒ CapabilitySigners`
|
|
358
|
+
|
|
359
|
+
Resolves the first set of capability invocation and delegation signers
|
|
360
|
+
associated with a `didDocument` from its `keyPairs`. Returns
|
|
361
|
+
`{ invocationSigner, delegationSigner }`.
|
|
362
|
+
|
|
363
|
+
| Param | Type | Description |
|
|
364
|
+
| --- | --- | --- |
|
|
365
|
+
| `options.didDocument` | `object` | A DID Document containing `capabilityInvocation` and `capabilityDelegation` verification relationships. |
|
|
366
|
+
| `options.keyPairs` | `Map` | A map of key pairs indexed by key id. |
|
|
367
|
+
|
|
368
|
+
### TypeScript types
|
|
369
|
+
|
|
370
|
+
The package is written in TypeScript and ships generated declarations. In
|
|
371
|
+
addition to the runtime exports, the following types are exported from
|
|
372
|
+
`@interop/ezcap`: `ZcapObject`, `Proof`, `ZcapClientOptions`, `DelegateOptions`,
|
|
373
|
+
`RequestOptions`, `ReadOptions`, `WriteOptions`, `HttpsAgent`,
|
|
374
|
+
`LinkedDataSignatureSuiteClass`, `DocumentLoader`, `Signer`,
|
|
375
|
+
`VerificationMethodReference`, `DidDocument`, `KeyPair`, and
|
|
376
|
+
`CapabilitySigners`.
|
|
377
|
+
|
|
378
|
+
## License
|
|
379
|
+
[New BSD License (3-clause)](LICENSE) © Digital Bazaar and Interop Alliance
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import type { HttpResponse } from '@interop/http-client';
|
|
2
|
+
import type { DidDocument, KeyPair, Signer } from './util.js';
|
|
3
|
+
/**
|
|
4
|
+
* A loaded remote document returned by a JSON-LD document loader.
|
|
5
|
+
*/
|
|
6
|
+
export interface RemoteDocument {
|
|
7
|
+
contextUrl?: string | null;
|
|
8
|
+
documentUrl?: string;
|
|
9
|
+
document: unknown;
|
|
10
|
+
tag?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A JSON-LD document loader: resolves a URL to a remote document.
|
|
14
|
+
*/
|
|
15
|
+
export type DocumentLoader = (url: string) => Promise<RemoteDocument>;
|
|
16
|
+
/**
|
|
17
|
+
* An object that manages connection persistence and reuse for HTTPS requests.
|
|
18
|
+
*
|
|
19
|
+
* @see https://nodejs.org/api/https.html#https_class_https_agent
|
|
20
|
+
*/
|
|
21
|
+
export type HttpsAgent = object;
|
|
22
|
+
/**
|
|
23
|
+
* A class that can be instantiated to create a suite capable of generating a
|
|
24
|
+
* Linked Data Signature. Its constructor must receive a `signer` instance
|
|
25
|
+
* that includes a `.sign()` function and `id` and `controller` properties.
|
|
26
|
+
*/
|
|
27
|
+
export interface LinkedDataSignatureSuiteClass {
|
|
28
|
+
new (options: {
|
|
29
|
+
date?: Date;
|
|
30
|
+
signer: Signer;
|
|
31
|
+
}): object;
|
|
32
|
+
/** Optional suite context document. */
|
|
33
|
+
CONTEXT?: object;
|
|
34
|
+
/** Optional suite context URL. */
|
|
35
|
+
CONTEXT_URL?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A proof attached to a capability.
|
|
39
|
+
*/
|
|
40
|
+
export interface Proof {
|
|
41
|
+
proofPurpose?: string;
|
|
42
|
+
created?: string;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A zcap (Authorization Capability) object.
|
|
47
|
+
*/
|
|
48
|
+
export interface ZcapObject {
|
|
49
|
+
'@context': string | string[];
|
|
50
|
+
id: string;
|
|
51
|
+
controller?: string;
|
|
52
|
+
invocationTarget: string;
|
|
53
|
+
parentCapability?: string;
|
|
54
|
+
allowedAction?: string | string[];
|
|
55
|
+
expires?: string;
|
|
56
|
+
proof?: Proof | Proof[];
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
}
|
|
59
|
+
export interface ZcapClientOptions {
|
|
60
|
+
/** The LD signature suite class to use to sign requests and delegations. */
|
|
61
|
+
SuiteClass: LinkedDataSignatureSuiteClass;
|
|
62
|
+
/**
|
|
63
|
+
* A DID Document that contains `capabilityInvocation` and
|
|
64
|
+
* `capabilityDelegation` verification relationships; `didDocument` and
|
|
65
|
+
* `keyPairs`, or `invocationSigner` and `delegationSigner` must be
|
|
66
|
+
* provided in order to invoke or delegate zcaps, respectively.
|
|
67
|
+
*/
|
|
68
|
+
didDocument?: DidDocument;
|
|
69
|
+
/**
|
|
70
|
+
* A map of key pairs associated with `didDocument` indexed by key ID;
|
|
71
|
+
* `didDocument` and `keyPairs`, or `invocationSigner` and
|
|
72
|
+
* `delegationSigner` must be provided in order to invoke or delegate
|
|
73
|
+
* zcaps, respectively.
|
|
74
|
+
*/
|
|
75
|
+
keyPairs?: Map<string, KeyPair>;
|
|
76
|
+
/**
|
|
77
|
+
* A signer with `.sign()`, `id`, and `controller` used for delegating zcaps;
|
|
78
|
+
* `delegationSigner` or `didDocument` and `keyPairs` must be provided to
|
|
79
|
+
* delegate zcaps.
|
|
80
|
+
*/
|
|
81
|
+
delegationSigner?: Signer;
|
|
82
|
+
/**
|
|
83
|
+
* A signer with `.sign()`, `id`, and `controller` used for signing requests;
|
|
84
|
+
* `invocationSigner` or `didDocument` and `keyPairs` must be provided to
|
|
85
|
+
* invoke zcaps.
|
|
86
|
+
*/
|
|
87
|
+
invocationSigner?: Signer;
|
|
88
|
+
/** An optional HttpsAgent to use when performing HTTPS requests. */
|
|
89
|
+
agent?: HttpsAgent;
|
|
90
|
+
/** Optional default HTTP headers to include in every invocation request. */
|
|
91
|
+
defaultHeaders?: Record<string, string>;
|
|
92
|
+
/**
|
|
93
|
+
* Optional document loader to load suite-related contexts. If none is
|
|
94
|
+
* provided, one will be auto-generated if the suite class expresses its
|
|
95
|
+
* required context.
|
|
96
|
+
*/
|
|
97
|
+
documentLoader?: DocumentLoader;
|
|
98
|
+
}
|
|
99
|
+
export interface DelegateOptions {
|
|
100
|
+
/**
|
|
101
|
+
* The parent capability to delegate; must be an object if it is a delegated
|
|
102
|
+
* zcap, can be a string if it is a root zcap but then `invocationTarget`
|
|
103
|
+
* must be specified; if not specified, this will be auto-generated as a
|
|
104
|
+
* root zcap for the given `invocationTarget`.
|
|
105
|
+
*/
|
|
106
|
+
capability?: string | ZcapObject;
|
|
107
|
+
/** The URL identifying the entity to delegate to. */
|
|
108
|
+
controller: string;
|
|
109
|
+
/**
|
|
110
|
+
* Optional invocation target to use when narrowing a `capability`'s
|
|
111
|
+
* existing invocationTarget. Default is to use
|
|
112
|
+
* `capability.invocationTarget`.
|
|
113
|
+
*/
|
|
114
|
+
invocationTarget?: string;
|
|
115
|
+
/**
|
|
116
|
+
* Optional expiration value for the delegation. Default is 5 minutes after
|
|
117
|
+
* `Date.now()`.
|
|
118
|
+
*/
|
|
119
|
+
expires?: string | Date;
|
|
120
|
+
/**
|
|
121
|
+
* Optional list of allowed actions or string specifying allowed delegated
|
|
122
|
+
* action. Default: [] - delegate all actions.
|
|
123
|
+
*/
|
|
124
|
+
allowedActions?: string | string[];
|
|
125
|
+
}
|
|
126
|
+
export interface RequestOptions {
|
|
127
|
+
/**
|
|
128
|
+
* The URL to invoke the Authorization Capability against; if not provided,
|
|
129
|
+
* a `capability` must be provided instead.
|
|
130
|
+
*/
|
|
131
|
+
url?: string;
|
|
132
|
+
/**
|
|
133
|
+
* The capability to invoke at the given URL. Default: generate root
|
|
134
|
+
* capability from options.url.
|
|
135
|
+
*/
|
|
136
|
+
capability?: string | ZcapObject;
|
|
137
|
+
/** The HTTP method to use when accessing the resource. Default: 'GET'. */
|
|
138
|
+
method?: string;
|
|
139
|
+
/** The capability action that is being invoked. Default: same as method. */
|
|
140
|
+
action?: string;
|
|
141
|
+
/** Additional headers to sign and send along with the HTTP request. */
|
|
142
|
+
headers?: Record<string, string>;
|
|
143
|
+
/** The JSON object, if any, to send with the request. */
|
|
144
|
+
json?: object;
|
|
145
|
+
/** A non-JSON body to send with the request (file uploads, PDFs, etc.). */
|
|
146
|
+
body?: Blob | Uint8Array;
|
|
147
|
+
}
|
|
148
|
+
export interface ReadOptions {
|
|
149
|
+
/** The URL to invoke the Authorization Capability against. */
|
|
150
|
+
url: string;
|
|
151
|
+
/** Additional headers to sign and send along with the HTTP request. */
|
|
152
|
+
headers?: Record<string, string>;
|
|
153
|
+
/**
|
|
154
|
+
* The capability to invoke at the given URL. Default: generate root
|
|
155
|
+
* capability from options.url.
|
|
156
|
+
*/
|
|
157
|
+
capability?: string | ZcapObject;
|
|
158
|
+
}
|
|
159
|
+
export interface WriteOptions {
|
|
160
|
+
/** The URL to invoke the Authorization Capability against. */
|
|
161
|
+
url: string;
|
|
162
|
+
/** The JSON object, if any, to send with the request. */
|
|
163
|
+
json?: object;
|
|
164
|
+
/** A non-JSON body to send with the request (file uploads, PDFs, etc.). */
|
|
165
|
+
body?: Blob | Uint8Array;
|
|
166
|
+
/** Additional headers to sign and send along with the HTTP request. */
|
|
167
|
+
headers?: Record<string, string>;
|
|
168
|
+
/**
|
|
169
|
+
* The capability to invoke at the given URL. Default: generate root
|
|
170
|
+
* capability from options.url.
|
|
171
|
+
*/
|
|
172
|
+
capability?: string | ZcapObject;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* A client for performing HTTP requests authorized via Authorization
|
|
176
|
+
* Capabilities (zcaps): delegating zcaps and invoking them against zcap-
|
|
177
|
+
* protected HTTP servers in both the browser and Node.js.
|
|
178
|
+
*/
|
|
179
|
+
export declare class ZcapClient {
|
|
180
|
+
agent?: HttpsAgent;
|
|
181
|
+
defaultHeaders: Record<string, string>;
|
|
182
|
+
SuiteClass: LinkedDataSignatureSuiteClass;
|
|
183
|
+
invocationSigner?: Signer;
|
|
184
|
+
delegationSigner?: Signer;
|
|
185
|
+
documentLoader: DocumentLoader;
|
|
186
|
+
/**
|
|
187
|
+
* Creates a new ZcapClient instance that can be used to perform requests
|
|
188
|
+
* against HTTP URLs that are authorized via Authorization Capabilities
|
|
189
|
+
* (zcaps).
|
|
190
|
+
*
|
|
191
|
+
* @param options {ZcapClientOptions} - The options to use.
|
|
192
|
+
*/
|
|
193
|
+
constructor({ SuiteClass, didDocument, keyPairs, delegationSigner, invocationSigner, agent, defaultHeaders, documentLoader }: ZcapClientOptions);
|
|
194
|
+
/**
|
|
195
|
+
* Delegates an Authorization Capability to a target delegate.
|
|
196
|
+
*
|
|
197
|
+
* @param options {DelegateOptions} - The options to use.
|
|
198
|
+
*
|
|
199
|
+
* @returns {Promise<ZcapObject>} - A promise that resolves to a delegated
|
|
200
|
+
* capability.
|
|
201
|
+
*/
|
|
202
|
+
delegate({ capability, controller, invocationTarget, expires, allowedActions }: DelegateOptions): Promise<ZcapObject>;
|
|
203
|
+
/**
|
|
204
|
+
* Performs an HTTP request given an Authorization Capability (zcap) and/or
|
|
205
|
+
* a target URL. If no URL is given, the invocation target from the
|
|
206
|
+
* capability will be used. If a capability is given as a string, it MUST
|
|
207
|
+
* be a root capability. If both a capability and a URL are given, then
|
|
208
|
+
* the capability's invocation target MUST be a RESTful prefix of or
|
|
209
|
+
* equivalent to the URL.
|
|
210
|
+
*
|
|
211
|
+
* @param options {RequestOptions} - The options to use.
|
|
212
|
+
*
|
|
213
|
+
* @returns {Promise<HttpResponse>} - A promise that resolves to an HTTP
|
|
214
|
+
* response.
|
|
215
|
+
*/
|
|
216
|
+
request({ url, capability, method, action, headers, json, body }: RequestOptions): Promise<HttpResponse>;
|
|
217
|
+
/**
|
|
218
|
+
* Convenience function that invokes an Authorization Capability against a
|
|
219
|
+
* given URL to perform a read operation.
|
|
220
|
+
*
|
|
221
|
+
* @param options {ReadOptions} - The options to use.
|
|
222
|
+
*
|
|
223
|
+
* @returns {Promise<HttpResponse>} - A promise that resolves to an HTTP
|
|
224
|
+
* response.
|
|
225
|
+
*/
|
|
226
|
+
read({ url, headers, capability }: ReadOptions): Promise<HttpResponse>;
|
|
227
|
+
/**
|
|
228
|
+
* Convenience function that invokes an Authorization Capability against a
|
|
229
|
+
* given URL to perform a write operation.
|
|
230
|
+
*
|
|
231
|
+
* @param options {WriteOptions} - The options to use.
|
|
232
|
+
*
|
|
233
|
+
* @returns {Promise<HttpResponse>} - A promise that resolves to an HTTP
|
|
234
|
+
* response.
|
|
235
|
+
*/
|
|
236
|
+
write({ url, json, body, headers, capability }: WriteOptions): Promise<HttpResponse>;
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=ZcapClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ZcapClient.d.ts","sourceRoot":"","sources":["../src/ZcapClient.ts"],"names":[],"mappings":"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"}
|