@interop/zcap 10.0.2 → 11.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 +21 -3
- package/dist/CapabilityDelegation.d.ts +173 -0
- package/dist/CapabilityDelegation.d.ts.map +1 -0
- package/dist/CapabilityDelegation.js +372 -0
- package/dist/CapabilityDelegation.js.map +1 -0
- package/dist/CapabilityInvocation.d.ts +151 -0
- package/dist/CapabilityInvocation.d.ts.map +1 -0
- package/dist/CapabilityInvocation.js +365 -0
- package/dist/CapabilityInvocation.js.map +1 -0
- package/dist/CapabilityProofPurpose.d.ts +203 -0
- package/dist/CapabilityProofPurpose.d.ts.map +1 -0
- package/dist/CapabilityProofPurpose.js +531 -0
- package/dist/CapabilityProofPurpose.js.map +1 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +23 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +224 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +250 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +591 -0
- package/dist/utils.js.map +1 -0
- package/package.json +47 -34
- package/lib/CapabilityDelegation.js +0 -312
- package/lib/CapabilityInvocation.js +0 -343
- package/lib/CapabilityProofPurpose.js +0 -538
- package/lib/constants.js +0 -32
- package/lib/index.js +0 -55
- package/lib/utils.js +0 -672
- package/types/lib/CapabilityDelegation.d.ts +0 -101
- package/types/lib/CapabilityDelegation.d.ts.map +0 -1
- package/types/lib/CapabilityInvocation.d.ts +0 -100
- package/types/lib/CapabilityInvocation.d.ts.map +0 -1
- package/types/lib/CapabilityProofPurpose.d.ts +0 -126
- package/types/lib/CapabilityProofPurpose.d.ts.map +0 -1
- package/types/lib/constants.d.ts +0 -15
- package/types/lib/constants.d.ts.map +0 -1
- package/types/lib/index.d.ts +0 -42
- package/types/lib/index.d.ts.map +0 -1
- package/types/lib/utils.d.ts +0 -304
- package/types/lib/utils.d.ts.map +0 -1
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2018-2024 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as utils from './utils.js';
|
|
5
|
-
import {CapabilityDelegation} from './CapabilityDelegation.js';
|
|
6
|
-
import {CapabilityProofPurpose} from './CapabilityProofPurpose.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {import('./utils.js').InspectCapabilityChain} InspectCapabilityChain
|
|
10
|
-
* @typedef {import('./utils.js').IDelegatedZcap} IDelegatedZcap
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export class CapabilityInvocation extends CapabilityProofPurpose {
|
|
14
|
-
/**
|
|
15
|
-
* @param {object} options - The options.
|
|
16
|
-
* @param {string|IDelegatedZcap} [options.capability] - The capability to
|
|
17
|
-
* add/reference in a created proof. A root zcap MUST be passed as its ID
|
|
18
|
-
* string; a delegated zcap must be passed as the full object.
|
|
19
|
-
* @param {string} [options.capabilityAction] - The capability action that is
|
|
20
|
-
* to be added to a proof.
|
|
21
|
-
* @param {string} [options.invocationTarget] - The invocation target to
|
|
22
|
-
* use; this is required and can be used to attenuate the capability's
|
|
23
|
-
* invocation target if the verifier supports target attenuation.
|
|
24
|
-
* @param {boolean} [options.allowTargetAttenuation=false] - Allow the
|
|
25
|
-
* invocationTarget of a delegation chain to be increasingly restrictive
|
|
26
|
-
* based on a hierarchical RESTful URL structure.
|
|
27
|
-
* @param {object} [options.controller] - The description of the controller,
|
|
28
|
-
* if it is not to be dereferenced via a `documentLoader`.
|
|
29
|
-
* @param {string|Date|number} [options.date] - Used during proof
|
|
30
|
-
* verification as the expected date for the creation of the proof
|
|
31
|
-
* (within a maximum timestamp delta) and for checking to see if a
|
|
32
|
-
* capability has expired; if not passed the current date will be used.
|
|
33
|
-
* @param {string} [options.expectedAction] - The capability action that is
|
|
34
|
-
* expected when validating a proof.
|
|
35
|
-
* @param {string|string[]} [options.expectedRootCapability] - The expected
|
|
36
|
-
* root capability for the delegation chain (a single root capability ID
|
|
37
|
-
* string, or an array of acceptable root capability ID strings).
|
|
38
|
-
* @param {string|string[]} [options.expectedTarget] - The target(s) we
|
|
39
|
-
* expect a capability to apply to (absolute URI, or array of URIs).
|
|
40
|
-
* @param {InspectCapabilityChain} [options.inspectCapabilityChain] - An
|
|
41
|
-
* async function that can be used to check for revocations related to any
|
|
42
|
-
* of verified capabilities.
|
|
43
|
-
* @param {number} [options.maxChainLength=10] - The maximum length of the
|
|
44
|
-
* capability delegation chain.
|
|
45
|
-
* @param {number} [options.maxClockSkew=300] - A maximum number of seconds
|
|
46
|
-
* that clocks may be skewed when checking capability expiration date-times
|
|
47
|
-
* against `date` and when comparing invocation proof creation time against
|
|
48
|
-
* delegation proof creation time.
|
|
49
|
-
* @param {number} [options.maxDelegationTtl=Infinity] - The maximum
|
|
50
|
-
* milliseconds to live for a delegated zcap as measured by the time
|
|
51
|
-
* difference between `expires` and `created` on the delegation proof.
|
|
52
|
-
* @param {number} [options.maxTimestampDelta=Infinity] - A maximum number
|
|
53
|
-
* of seconds that "created" date on the capability invocation proof can
|
|
54
|
-
* deviate from `date`, defaults to `Infinity`.
|
|
55
|
-
* @param {object|object[]} [options.suite] - The jsonld-signature suite(s) to
|
|
56
|
-
* use to verify the capability chain. Required only in verify-proof mode;
|
|
57
|
-
* unused (and omitted) when creating an invocation proof.
|
|
58
|
-
*/
|
|
59
|
-
constructor({
|
|
60
|
-
// proof creation params
|
|
61
|
-
capability,
|
|
62
|
-
capabilityAction,
|
|
63
|
-
invocationTarget,
|
|
64
|
-
// proof verification params
|
|
65
|
-
allowTargetAttenuation,
|
|
66
|
-
controller,
|
|
67
|
-
date,
|
|
68
|
-
expectedAction,
|
|
69
|
-
expectedRootCapability,
|
|
70
|
-
expectedTarget,
|
|
71
|
-
inspectCapabilityChain,
|
|
72
|
-
maxChainLength,
|
|
73
|
-
maxClockSkew,
|
|
74
|
-
maxDelegationTtl,
|
|
75
|
-
maxTimestampDelta,
|
|
76
|
-
suite
|
|
77
|
-
} = {}) {
|
|
78
|
-
// parameters used to create a proof
|
|
79
|
-
const hasCreateProofParams = capability || capabilityAction ||
|
|
80
|
-
invocationTarget;
|
|
81
|
-
// params used to verify a proof
|
|
82
|
-
const hasVerifyProofParams = controller || date ||
|
|
83
|
-
expectedAction || expectedRootCapability || expectedTarget ||
|
|
84
|
-
inspectCapabilityChain || suite;
|
|
85
|
-
|
|
86
|
-
if(hasCreateProofParams && hasVerifyProofParams) {
|
|
87
|
-
// cannot provide both create and verify params
|
|
88
|
-
throw new Error(
|
|
89
|
-
'Parameters for both creating and verifying a proof must not be ' +
|
|
90
|
-
'provided together.');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
super({
|
|
94
|
-
allowTargetAttenuation,
|
|
95
|
-
controller, date,
|
|
96
|
-
expectedRootCapability, inspectCapabilityChain,
|
|
97
|
-
maxChainLength, maxClockSkew, maxDelegationTtl, maxTimestampDelta,
|
|
98
|
-
suite,
|
|
99
|
-
term: 'capabilityInvocation'
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// validate `CapabilityInvocation` specific params, the base class will
|
|
103
|
-
// have already handled validating common ones...
|
|
104
|
-
|
|
105
|
-
// use negative conditional to cover case where neither create nor
|
|
106
|
-
// verify params were provided and default to proof creation case to
|
|
107
|
-
// avoid creating bad proofs
|
|
108
|
-
if(!hasVerifyProofParams) {
|
|
109
|
-
if(typeof capability === 'object') {
|
|
110
|
-
// root capabilities MUST be passed as strings
|
|
111
|
-
if(!(capability && capability.parentCapability)) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
'"capability" must be a string if it is a root capability.');
|
|
114
|
-
}
|
|
115
|
-
} else if(typeof capability !== 'string') {
|
|
116
|
-
throw new TypeError('"capability" must be a string or object.');
|
|
117
|
-
}
|
|
118
|
-
if(typeof capabilityAction !== 'string') {
|
|
119
|
-
throw new TypeError('"capabilityAction" must be a string.');
|
|
120
|
-
}
|
|
121
|
-
if(!(typeof invocationTarget === 'string' &&
|
|
122
|
-
invocationTarget.includes(':'))) {
|
|
123
|
-
throw new TypeError(
|
|
124
|
-
'"invocationTarget" must be a string that expresses an absolute ' +
|
|
125
|
-
'URI.');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
this.capability = capability;
|
|
129
|
-
this.capabilityAction = capabilityAction;
|
|
130
|
-
this.invocationTarget = invocationTarget;
|
|
131
|
-
} else {
|
|
132
|
-
if(typeof expectedAction !== 'string') {
|
|
133
|
-
throw new TypeError('"expectedAction" must be a string.');
|
|
134
|
-
}
|
|
135
|
-
if(!(typeof expectedTarget === 'string' ||
|
|
136
|
-
Array.isArray(expectedTarget))) {
|
|
137
|
-
throw new TypeError('"expectedTarget" must be a string or array.');
|
|
138
|
-
}
|
|
139
|
-
// expected target values must be absolute URIs
|
|
140
|
-
const expectedTargets = Array.isArray(expectedTarget) ?
|
|
141
|
-
expectedTarget : [expectedTarget];
|
|
142
|
-
for(const et of expectedTargets) {
|
|
143
|
-
if(!(typeof et === 'string' && et.includes(':'))) {
|
|
144
|
-
throw new Error(
|
|
145
|
-
'"expectedTargets" values must be absolute URI strings.');
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
this.expectedTarget = expectedTarget;
|
|
150
|
-
this.expectedAction = expectedAction;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
async update(proof) {
|
|
155
|
-
const {capability, capabilityAction, invocationTarget} = this;
|
|
156
|
-
proof.proofPurpose = this.term;
|
|
157
|
-
proof.capability = capability;
|
|
158
|
-
proof.invocationTarget = invocationTarget;
|
|
159
|
-
proof.capabilityAction = capabilityAction;
|
|
160
|
-
return proof;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async match(proof, {document, documentLoader}) {
|
|
164
|
-
const {expectedAction, expectedTarget} = this;
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
// check the `proof` context before using its terms
|
|
168
|
-
utils.checkProofContext({proof});
|
|
169
|
-
} catch(e) {
|
|
170
|
-
// context does not match, so proof does not match
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if(!proof.capability) {
|
|
175
|
-
// capability not in the proof, not a match
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// ensure basic purpose and expected action match the proof
|
|
180
|
-
if(!(await super.match(proof, {document, documentLoader}) &&
|
|
181
|
-
(expectedAction === proof.capabilityAction))) {
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// ensure the proof's declared invocation target matches an expected one
|
|
186
|
-
if(Array.isArray(expectedTarget)) {
|
|
187
|
-
return expectedTarget.includes(proof.invocationTarget);
|
|
188
|
-
}
|
|
189
|
-
return expectedTarget === proof.invocationTarget;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
_getCapabilityDelegationClass() {
|
|
193
|
-
return CapabilityDelegation;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
_getTailCapability({proof}) {
|
|
197
|
-
return {capability: proof.capability};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async _runChecksBeforeChainVerification({dereferencedChain, proof}) {
|
|
201
|
-
const {
|
|
202
|
-
allowTargetAttenuation,
|
|
203
|
-
expectedAction,
|
|
204
|
-
expectedTarget
|
|
205
|
-
} = this;
|
|
206
|
-
|
|
207
|
-
/* 1. Ensure that `capabilityAction` is an allowed action and that
|
|
208
|
-
it matches `expectedAction`. Note that if it doesn't match and `match`
|
|
209
|
-
was called to gate calling `validate`, then this code will not execute.
|
|
210
|
-
However, if `validate` is called directly, this check MUST run here.
|
|
211
|
-
|
|
212
|
-
If the capability restricts the actions via `allowedAction` then
|
|
213
|
-
`capabilityAction` must be in its set. */
|
|
214
|
-
const capability = dereferencedChain[dereferencedChain.length - 1];
|
|
215
|
-
const {capabilityAction} = proof;
|
|
216
|
-
const allowedActions = utils.getAllowedActions({capability});
|
|
217
|
-
if(allowedActions.length > 0 &&
|
|
218
|
-
!allowedActions.includes(capabilityAction)) {
|
|
219
|
-
throw new Error(
|
|
220
|
-
`Capability action "${capabilityAction}" is not allowed by the ` +
|
|
221
|
-
'capability; allowed actions are: ' +
|
|
222
|
-
allowedActions.map(x => `"${x}"`).join(', '));
|
|
223
|
-
}
|
|
224
|
-
if(capabilityAction !== expectedAction) {
|
|
225
|
-
throw new Error(
|
|
226
|
-
`Capability action "${capabilityAction}" does not match the ` +
|
|
227
|
-
`expected action of "${expectedAction}".`);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/* 2. Ensure `expectedTarget` is as expected. The invocation target
|
|
231
|
-
will also be checked to ensure it hasn't changed from previous zcaps
|
|
232
|
-
in the chain (unless attenuation is permitted) later. */
|
|
233
|
-
|
|
234
|
-
/* 3. Verify the invocation target in the proof is as expected. The
|
|
235
|
-
`invocationTarget` specified in the capability invocation proof must
|
|
236
|
-
match exactly (or follow acceptable target attenuation rules) the
|
|
237
|
-
`invocationTarget` specified in the invoked capability. */
|
|
238
|
-
const capabilityTarget = utils.getTarget({capability});
|
|
239
|
-
const {invocationTarget} = proof;
|
|
240
|
-
if(!(typeof invocationTarget === 'string' &&
|
|
241
|
-
invocationTarget.includes(':'))) {
|
|
242
|
-
throw new TypeError(
|
|
243
|
-
`Invocation target (${invocationTarget}) must be a string that ` +
|
|
244
|
-
'expresses an absolute URI.');
|
|
245
|
-
}
|
|
246
|
-
if(!utils.isValidTarget({
|
|
247
|
-
invocationTarget,
|
|
248
|
-
baseInvocationTarget: capabilityTarget,
|
|
249
|
-
allowTargetAttenuation
|
|
250
|
-
})) {
|
|
251
|
-
throw new Error(
|
|
252
|
-
`Invocation target (${invocationTarget}) does not match ` +
|
|
253
|
-
`capability target (${capabilityTarget}).`);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/* 4. Verify the invocation target is an expected target. Prior to this
|
|
257
|
-
step we ensured that the invocation target used matched th capability
|
|
258
|
-
that was invoked, but this check ensures that the invocation target used
|
|
259
|
-
matches the endpoint (the `expectedTarget`) where the capability was
|
|
260
|
-
actually invoked. */
|
|
261
|
-
if(!((Array.isArray(expectedTarget) &&
|
|
262
|
-
expectedTarget.includes(invocationTarget)) ||
|
|
263
|
-
(typeof expectedTarget === 'string' &&
|
|
264
|
-
invocationTarget === expectedTarget))) {
|
|
265
|
-
throw new Error(
|
|
266
|
-
`Expected target (${expectedTarget}) does not match ` +
|
|
267
|
-
`invocation target (${invocationTarget}).`);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/* 5. If capability is delegated (not root), then ensure the capability
|
|
271
|
-
invocation proof `created` date is not before the capability delegation
|
|
272
|
-
proof creation date. */
|
|
273
|
-
if(capability.parentCapability) {
|
|
274
|
-
const invoked = Date.parse(proof.created);
|
|
275
|
-
const [delegationProof] = utils.getDelegationProofs({capability});
|
|
276
|
-
const delegated = Date.parse(delegationProof.created);
|
|
277
|
-
const {maxClockSkew} = this;
|
|
278
|
-
// use `utils.compareTime` to allow for clock drift from the machine
|
|
279
|
-
// that created the delegation proof and the machine that created
|
|
280
|
-
// the invocation proof
|
|
281
|
-
if(utils.compareTime({t1: invoked, t2: delegated, maxClockSkew}) < 0) {
|
|
282
|
-
throw new Error(
|
|
283
|
-
'A delegated capability must not be invoked before the "created" ' +
|
|
284
|
-
'date in its delegation proof.');
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// return no capability delegation verify results yet; the tail's
|
|
289
|
-
// capability delegation proof must be verified via
|
|
290
|
-
// `_verifyCapabilityChain`
|
|
291
|
-
return {capabilityChainMeta: []};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
async _runChecksAfterChainVerification({
|
|
295
|
-
dereferencedChain, proof, validateOptions
|
|
296
|
-
}) {
|
|
297
|
-
/* Verify the controller of the capability. The zcap controller must
|
|
298
|
-
match the invoking verification method (or its controller). */
|
|
299
|
-
const capability = dereferencedChain[dereferencedChain.length - 1];
|
|
300
|
-
const {verificationMethod} = validateOptions;
|
|
301
|
-
if(!utils.isController({capability, verificationMethod})) {
|
|
302
|
-
const error = new Error(
|
|
303
|
-
'The capability controller does not match the verification method ' +
|
|
304
|
-
'(or its controller) used to invoke.');
|
|
305
|
-
error.details = {
|
|
306
|
-
capability,
|
|
307
|
-
verificationMethod
|
|
308
|
-
};
|
|
309
|
-
throw error;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// if capability is delegated, verify that it has not expired
|
|
313
|
-
if(capability.parentCapability) {
|
|
314
|
-
// verify expiration dates
|
|
315
|
-
// expires date has been previously validated, so just parse it
|
|
316
|
-
const currentCapabilityExpirationTime = Date.parse(capability.expires);
|
|
317
|
-
|
|
318
|
-
// use `utils.compareTime` to allow for allow for clock drift because
|
|
319
|
-
// we are comparing against `currentDate`
|
|
320
|
-
const {date, maxClockSkew} = this;
|
|
321
|
-
const currentDate = (date && new Date(date)) || new Date();
|
|
322
|
-
if(utils.compareTime({
|
|
323
|
-
t1: currentDate.getTime(),
|
|
324
|
-
t2: currentCapabilityExpirationTime,
|
|
325
|
-
maxClockSkew
|
|
326
|
-
}) > 0) {
|
|
327
|
-
throw new Error('The invoked capability has expired.');
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// run base level validation checks
|
|
332
|
-
const result = await this._runBaseProofValidation({proof, validateOptions});
|
|
333
|
-
if(!result.valid) {
|
|
334
|
-
throw result.error;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// the controller of the verification method from the proof is the
|
|
338
|
-
// invoker of the capability
|
|
339
|
-
result.invoker = result.controller;
|
|
340
|
-
|
|
341
|
-
return result;
|
|
342
|
-
}
|
|
343
|
-
}
|