@interop/did-web-resolver 4.0.0 → 6.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 +38 -12
- package/dist/DidWebResolver.d.ts +267 -0
- package/dist/DidWebResolver.d.ts.map +1 -0
- package/dist/DidWebResolver.js +557 -0
- package/dist/DidWebResolver.js.map +1 -0
- package/dist/assertions.d.ts +47 -0
- package/dist/assertions.d.ts.map +1 -0
- package/dist/assertions.js +90 -0
- package/dist/assertions.js.map +1 -0
- package/dist/constants.d.ts +23 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +45 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -72
- package/dist/esm/DidWebResolver.d.ts +0 -147
- package/dist/esm/DidWebResolver.d.ts.map +0 -1
- package/dist/esm/DidWebResolver.js +0 -322
- package/dist/esm/DidWebResolver.js.map +0 -1
- package/dist/esm/index.d.ts +0 -8
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/index.js +0 -6
- package/dist/esm/index.js.map +0 -1
- package/dist/src/DidWebResolver.d.ts +0 -146
- package/dist/src/DidWebResolver.js +0 -329
- package/dist/src/DidWebResolver.js.map +0 -1
- package/dist/src/index.d.ts +0 -7
- package/dist/src/index.js +0 -12
- package/dist/src/index.js.map +0 -1
- package/dist/test/DidWebResolver.spec.d.ts +0 -1
- package/dist/test/DidWebResolver.spec.js +0 -183
- package/dist/test/DidWebResolver.spec.js.map +0 -1
- package/src/DidWebResolver.ts +0 -366
- package/src/declarations.d.ts +0 -11
- package/src/index.ts +0 -8
- /package/{LICENSE → LICENSE.md} +0 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `did:web` method resolver and document generator for the `@interop/did-io`
|
|
3
|
+
* library. Builds `did:web` DID documents directly from registered key-suite
|
|
4
|
+
* instances (no `crypto-ld` dependency) and resolves them over HTTPS with
|
|
5
|
+
* SSRF, response-size, and document-`id` safety checks.
|
|
6
|
+
*/
|
|
7
|
+
import { httpClient } from '@interop/http-client';
|
|
8
|
+
import * as didIo from '@interop/did-io';
|
|
9
|
+
import { decodeSecretKeySeed } from '@digitalcredentials/bnid';
|
|
10
|
+
import { DID_CONTEXT_URL, DEFAULT_PURPOSES, contextsBySuite, defaultFetchOptions } from './constants.js';
|
|
11
|
+
import { assertDomain } from './assertions.js';
|
|
12
|
+
const { VERIFICATION_RELATIONSHIPS } = didIo;
|
|
13
|
+
export function didFromUrl({ url } = {}) {
|
|
14
|
+
if (!url) {
|
|
15
|
+
throw new TypeError('Cannot convert url to did, missing url.');
|
|
16
|
+
}
|
|
17
|
+
if (url.startsWith('http:')) {
|
|
18
|
+
throw new TypeError('did:web does not support non-HTTPS URLs.');
|
|
19
|
+
}
|
|
20
|
+
let parsedUrl;
|
|
21
|
+
try {
|
|
22
|
+
parsedUrl = new URL(url);
|
|
23
|
+
}
|
|
24
|
+
catch (cause) {
|
|
25
|
+
throw new TypeError(`Invalid url: "${url}".`, { cause });
|
|
26
|
+
}
|
|
27
|
+
const { host } = parsedUrl;
|
|
28
|
+
let { pathname } = parsedUrl;
|
|
29
|
+
let pathComponent = '';
|
|
30
|
+
const didJsonSuffix = '/did.json';
|
|
31
|
+
const wellKnownSuffix = '/.well-known';
|
|
32
|
+
if (pathname?.endsWith(didJsonSuffix)) {
|
|
33
|
+
pathname = pathname.substring(0, pathname.length - didJsonSuffix.length);
|
|
34
|
+
}
|
|
35
|
+
if (pathname?.endsWith(wellKnownSuffix)) {
|
|
36
|
+
pathname = pathname.substring(0, pathname.length - wellKnownSuffix.length);
|
|
37
|
+
}
|
|
38
|
+
if (pathname && pathname !== '/') {
|
|
39
|
+
pathComponent = pathname.split('/').map(encodeURIComponent).join(':');
|
|
40
|
+
}
|
|
41
|
+
return 'did:web:' + encodeURIComponent(host) + pathComponent;
|
|
42
|
+
}
|
|
43
|
+
export function urlFromDid({ did }) {
|
|
44
|
+
if (!did?.startsWith('did:web:')) {
|
|
45
|
+
throw new TypeError(`DID Method not supported: "${did ?? ''}".`);
|
|
46
|
+
}
|
|
47
|
+
const [didUrl = '', hashFragment] = did.split('#');
|
|
48
|
+
const [_did, _web, urlNoProtocol = '', ...pathFragments] = didUrl.split(':');
|
|
49
|
+
if (urlNoProtocol.includes('/')) {
|
|
50
|
+
throw new TypeError(`Cannot construct url from did: "${did}". domain-name cannot contain a path.`);
|
|
51
|
+
}
|
|
52
|
+
let parsedUrl;
|
|
53
|
+
try {
|
|
54
|
+
// URI-decode the url (in case it contained a port number,
|
|
55
|
+
// for example, `did:web:localhost%3A8080`
|
|
56
|
+
parsedUrl = new URL('https://' + decodeURIComponent(urlNoProtocol));
|
|
57
|
+
}
|
|
58
|
+
catch (cause) {
|
|
59
|
+
throw new TypeError(`Cannot construct url from did: "${did}".`, { cause });
|
|
60
|
+
}
|
|
61
|
+
if (pathFragments.length === 0) {
|
|
62
|
+
parsedUrl.pathname = '/.well-known/did.json';
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
parsedUrl.pathname = pathFragments.map(decodeURIComponent).join('/') + '/did.json';
|
|
66
|
+
}
|
|
67
|
+
if (hashFragment) {
|
|
68
|
+
parsedUrl.hash = hashFragment;
|
|
69
|
+
}
|
|
70
|
+
return parsedUrl.toString();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns the subnode of a DID document identified by `id`, with the
|
|
74
|
+
* appropriate `@context` attached. Searches `verificationMethod` first, then
|
|
75
|
+
* any other top-level node (e.g. `service`), so it can dereference keys *and*
|
|
76
|
+
* non-key subnodes.
|
|
77
|
+
*
|
|
78
|
+
* @param options {object} - Options hashmap.
|
|
79
|
+
* @param options.didDocument {object} - The DID Document to search.
|
|
80
|
+
* @param options.id {string} - The full id of the subnode to return.
|
|
81
|
+
*
|
|
82
|
+
* @returns {object} The matched subnode, cloned, with `@context`.
|
|
83
|
+
*/
|
|
84
|
+
export function getNode({ didDocument, id }) {
|
|
85
|
+
let match = (didDocument.verificationMethod ?? [])
|
|
86
|
+
.find((vm) => vm?.id === id);
|
|
87
|
+
if (!match) {
|
|
88
|
+
for (const [key, value] of Object.entries(didDocument)) {
|
|
89
|
+
if (key === '@context' || key === 'verificationMethod') {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (Array.isArray(value)) {
|
|
93
|
+
match = value.find((entry) => entry?.id === id);
|
|
94
|
+
}
|
|
95
|
+
else if (value?.id === id) {
|
|
96
|
+
match = value;
|
|
97
|
+
}
|
|
98
|
+
if (match) {
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!match) {
|
|
104
|
+
throw new Error(`DID document entity with id "${id}" not found.`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
'@context': contextsBySuite.get(match.type) ?? didDocument['@context'],
|
|
108
|
+
...structuredClone(match)
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export class DidWebResolver {
|
|
112
|
+
method;
|
|
113
|
+
allowList;
|
|
114
|
+
fetchOptions;
|
|
115
|
+
logger;
|
|
116
|
+
_allowedKeyTypes;
|
|
117
|
+
/**
|
|
118
|
+
* @param options {object} - Options hashmap.
|
|
119
|
+
* @param [options.allowList] {string[]} - Hosts permitted as fetch targets
|
|
120
|
+
* (SSRF gate). Empty/absent means no restriction.
|
|
121
|
+
* @param [options.fetchOptions] {object} - Network limits passed to the http
|
|
122
|
+
* client (`size` in bytes, `timeout` in ms).
|
|
123
|
+
* @param [options.logger] {object} - Logger object (with .info, .error, etc).
|
|
124
|
+
*/
|
|
125
|
+
constructor({ allowList = [], fetchOptions = defaultFetchOptions, logger = console } = {}) {
|
|
126
|
+
this.method = 'web'; // did:web:... (used for didIo resolver harness)
|
|
127
|
+
this.allowList = allowList;
|
|
128
|
+
this.fetchOptions = fetchOptions;
|
|
129
|
+
this.logger = logger;
|
|
130
|
+
this._allowedKeyTypes = new Map();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Registers a key suite this driver may handle when generating documents and
|
|
134
|
+
* rebuilding key pairs from plain descriptions.
|
|
135
|
+
*
|
|
136
|
+
* Preferred form: pass a `keyPairClass` exposing static `multibaseHeader`,
|
|
137
|
+
* `from`, and (optionally) `generate`. The driver reads the header off the
|
|
138
|
+
* class, so callers need not know the literal value.
|
|
139
|
+
*
|
|
140
|
+
* Lower-level form: pass `multibaseMultikeyHeader` plus a `fromMultibase`
|
|
141
|
+
* deserializer. Suites registered this way support resolution/rebuilding but
|
|
142
|
+
* not `generate()`.
|
|
143
|
+
*
|
|
144
|
+
* @param options {object} - Options hashmap.
|
|
145
|
+
* @param [options.keyPairClass] {Function} - A KeyPair suite class.
|
|
146
|
+
* @param [options.multibaseMultikeyHeader] {string} - Multibase header.
|
|
147
|
+
* @param [options.fromMultibase] {Function} - `{publicKeyMultibase}` to key.
|
|
148
|
+
*/
|
|
149
|
+
use({ keyPairClass, multibaseMultikeyHeader, fromMultibase } = {}) {
|
|
150
|
+
if (keyPairClass) {
|
|
151
|
+
const header = keyPairClass.multibaseHeader;
|
|
152
|
+
if (!(header && typeof header === 'string')) {
|
|
153
|
+
throw new TypeError('"keyPairClass.multibaseHeader" must be a string.');
|
|
154
|
+
}
|
|
155
|
+
if (typeof keyPairClass.from !== 'function') {
|
|
156
|
+
throw new TypeError('"keyPairClass.from" must be a function.');
|
|
157
|
+
}
|
|
158
|
+
this._allowedKeyTypes.set(header, {
|
|
159
|
+
fromMultibase: keyPairClass.from.bind(keyPairClass),
|
|
160
|
+
generate: typeof keyPairClass.generate === 'function'
|
|
161
|
+
? keyPairClass.generate.bind(keyPairClass)
|
|
162
|
+
: undefined
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (!(multibaseMultikeyHeader && typeof multibaseMultikeyHeader === 'string')) {
|
|
167
|
+
throw new TypeError('"multibaseMultikeyHeader" must be a string.');
|
|
168
|
+
}
|
|
169
|
+
if (typeof fromMultibase !== 'function') {
|
|
170
|
+
throw new TypeError('"fromMultibase" must be a function.');
|
|
171
|
+
}
|
|
172
|
+
this._allowedKeyTypes.set(multibaseMultikeyHeader, { fromMultibase });
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Adds a single verification method to a DID document: exports the key's
|
|
176
|
+
* public node, assigns it the id `${did}#${fragment}`, pushes it into
|
|
177
|
+
* `verificationMethod`, references it under each requested purpose, and
|
|
178
|
+
* accumulates the key's `@context`.
|
|
179
|
+
*
|
|
180
|
+
* This is the foundational document-building primitive; it works on a freshly
|
|
181
|
+
* created document or on one fetched and republished with rotated keys.
|
|
182
|
+
*
|
|
183
|
+
* @param options {object} - Options hashmap.
|
|
184
|
+
* @param options.didDocument {object} - Document to mutate (must have `id`).
|
|
185
|
+
* @param options.keyPair {object} - A registered key suite instance.
|
|
186
|
+
* @param [options.keyPairs] {Map} - Optional key-id to key-pair map to update.
|
|
187
|
+
* @param [options.fragment] {string} - Author-chosen fragment (defaults to
|
|
188
|
+
* the key fingerprint).
|
|
189
|
+
* @param [options.purposes] {string[]} - Verification relationships to wire.
|
|
190
|
+
* @param [options.serialization] {string} - `'multibase'` (default); `'jwk'`
|
|
191
|
+
* is reserved for when key suites expose JWK export.
|
|
192
|
+
*
|
|
193
|
+
* @returns {object} The mutated DID document.
|
|
194
|
+
*/
|
|
195
|
+
addVerificationMethod({ didDocument, keyPairs, keyPair, fragment, purposes = DEFAULT_PURPOSES, serialization = 'multibase' }) {
|
|
196
|
+
if (!didDocument?.id) {
|
|
197
|
+
throw new TypeError('"didDocument.id" is required to add a verification method.');
|
|
198
|
+
}
|
|
199
|
+
if (!keyPair) {
|
|
200
|
+
throw new TypeError('A "keyPair" is required.');
|
|
201
|
+
}
|
|
202
|
+
if (serialization !== 'multibase') {
|
|
203
|
+
throw new Error(`Serialization "${serialization}" is not yet supported.`);
|
|
204
|
+
}
|
|
205
|
+
const did = didDocument.id;
|
|
206
|
+
fragment = fragment ?? _defaultFragment(keyPair);
|
|
207
|
+
keyPair.controller = did;
|
|
208
|
+
keyPair.id = `${did}#${fragment}`;
|
|
209
|
+
const publicNode = keyPair.export({ publicKey: true, includeContext: true });
|
|
210
|
+
const context = publicNode['@context'];
|
|
211
|
+
delete publicNode['@context'];
|
|
212
|
+
if (context) {
|
|
213
|
+
_addContext({ didDocument, context });
|
|
214
|
+
}
|
|
215
|
+
didDocument.verificationMethod = didDocument.verificationMethod ?? [];
|
|
216
|
+
didDocument.verificationMethod.push(publicNode);
|
|
217
|
+
for (const purpose of purposes) {
|
|
218
|
+
if (!VERIFICATION_RELATIONSHIPS.has(purpose)) {
|
|
219
|
+
throw new Error(`Unsupported key purpose: "${purpose}".`);
|
|
220
|
+
}
|
|
221
|
+
didDocument[purpose] = didDocument[purpose] ?? [];
|
|
222
|
+
didDocument[purpose].push(publicNode.id);
|
|
223
|
+
}
|
|
224
|
+
keyPairs?.set(keyPair.id, keyPair);
|
|
225
|
+
return didDocument;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Generates a new `did:web` DID Document.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* const { didDocument, keyPairs } = await didWeb.generate({
|
|
232
|
+
* url: 'https://example.com', verificationKeyPair
|
|
233
|
+
* })
|
|
234
|
+
* didDocument.id // -> 'did:web:example.com'
|
|
235
|
+
*
|
|
236
|
+
* Either an `id` or a `url` is required. For the single-key common case, pass
|
|
237
|
+
* a `verificationKeyPair` (or `seed`/`keyType` to generate one from a
|
|
238
|
+
* registered suite) and optionally a `keyAgreementKeyPair`. For multi-key
|
|
239
|
+
* documents, pass `verificationMethods`.
|
|
240
|
+
*
|
|
241
|
+
* @param options {object} - Options hashmap.
|
|
242
|
+
* @param [options.id] {string} - A did:web DID (else derived from `url`).
|
|
243
|
+
* @param [options.url] {string} - HTTPS url of the DID document.
|
|
244
|
+
* @param [options.seed] {string|Uint8Array} - Secret seed to derive a key.
|
|
245
|
+
* @param [options.keyType] {Function|string} - Which registered suite to
|
|
246
|
+
* generate with (a key class or its multibase header).
|
|
247
|
+
* @param [options.verificationKeyPair] {object} - A pre-made verification key.
|
|
248
|
+
* @param [options.keyAgreementKeyPair] {object} - A pre-made keyAgreement key.
|
|
249
|
+
* @param [options.verificationMethods] {Array} - Multi-key entries, each
|
|
250
|
+
* `{ keyPair, fragment?, purposes?, serialization? }`.
|
|
251
|
+
*
|
|
252
|
+
* @returns {Promise<{didDocument: object, keyPairs: Map, methodFor: Function}>}
|
|
253
|
+
*/
|
|
254
|
+
async generate({ id, url, seed, keyType, verificationKeyPair, keyAgreementKeyPair, verificationMethods } = {}) {
|
|
255
|
+
if (!id && !url) {
|
|
256
|
+
throw new TypeError('A "url" or an "id" parameter is required.');
|
|
257
|
+
}
|
|
258
|
+
const did = id ?? didFromUrl({ url });
|
|
259
|
+
assertDomain({ allowList: this.allowList, url: url ?? urlFromDid({ did }) });
|
|
260
|
+
const didDocument = { '@context': [DID_CONTEXT_URL], id: did };
|
|
261
|
+
const keyPairs = new Map();
|
|
262
|
+
if (verificationMethods && verificationMethods.length > 0) {
|
|
263
|
+
for (const entry of verificationMethods) {
|
|
264
|
+
this.addVerificationMethod({
|
|
265
|
+
didDocument,
|
|
266
|
+
keyPairs,
|
|
267
|
+
keyPair: entry.keyPair,
|
|
268
|
+
fragment: entry.fragment,
|
|
269
|
+
purposes: entry.purposes,
|
|
270
|
+
serialization: entry.serialization
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
let keyPair = verificationKeyPair;
|
|
276
|
+
if (!keyPair && !keyAgreementKeyPair) {
|
|
277
|
+
keyPair = await this._generateKeyPair({ seed, keyType });
|
|
278
|
+
}
|
|
279
|
+
if (keyPair) {
|
|
280
|
+
this.addVerificationMethod({
|
|
281
|
+
didDocument, keyPairs, keyPair, purposes: DEFAULT_PURPOSES
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
if (keyAgreementKeyPair) {
|
|
285
|
+
this.addVerificationMethod({
|
|
286
|
+
didDocument, keyPairs, keyPair: keyAgreementKeyPair,
|
|
287
|
+
purposes: ['keyAgreement']
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Convenience function that returns the public/private key pair instance
|
|
292
|
+
// for a given purpose (authentication, assertionMethod, keyAgreement, etc).
|
|
293
|
+
const methodFor = ({ purpose }) => {
|
|
294
|
+
const method = didIo.findVerificationMethod({
|
|
295
|
+
doc: didDocument, purpose
|
|
296
|
+
});
|
|
297
|
+
return keyPairs.get(method?.id);
|
|
298
|
+
};
|
|
299
|
+
return { didDocument, keyPairs, methodFor };
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Generates a `did:web` DID Document from existing key pairs. A `url` or `id`
|
|
303
|
+
* is required (unlike `did:key`, a `did:web` identifier is not derivable from
|
|
304
|
+
* key material alone).
|
|
305
|
+
*
|
|
306
|
+
* @param options {object} - Options hashmap.
|
|
307
|
+
* @param [options.url] {string} - HTTPS url of the DID document.
|
|
308
|
+
* @param [options.id] {string} - A did:web DID.
|
|
309
|
+
* @param [options.verificationKeyPair] {object} - A verification KeyPair.
|
|
310
|
+
* @param [options.keyAgreementKeyPair] {object} - A keyAgreement KeyPair.
|
|
311
|
+
*
|
|
312
|
+
* @returns {Promise<{didDocument: object, keyPairs: Map, methodFor: Function}>}
|
|
313
|
+
*/
|
|
314
|
+
async fromKeyPair({ url, id, verificationKeyPair, keyAgreementKeyPair } = {}) {
|
|
315
|
+
if (!(verificationKeyPair || keyAgreementKeyPair)) {
|
|
316
|
+
throw new TypeError('"verificationKeyPair" or "keyAgreementKeyPair" must be provided.');
|
|
317
|
+
}
|
|
318
|
+
if (!url && !id) {
|
|
319
|
+
throw new TypeError('A "url" or "id" is required to build a did:web document.');
|
|
320
|
+
}
|
|
321
|
+
return this.generate({ url, id, verificationKeyPair, keyAgreementKeyPair });
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Converts a public key description to a `did:web` DID Document. A `url` or
|
|
325
|
+
* `id` is required. Unlike `generate()`, no `keyPairs` map is returned.
|
|
326
|
+
*
|
|
327
|
+
* @param options {object} - Options hashmap.
|
|
328
|
+
* @param [options.url] {string} - HTTPS url of the DID document.
|
|
329
|
+
* @param [options.id] {string} - A did:web DID.
|
|
330
|
+
* @param options.publicKeyDescription {object} - A key pair instance or a
|
|
331
|
+
* plain public key description (e.g. from a KMS).
|
|
332
|
+
*
|
|
333
|
+
* @returns {Promise<{didDocument: object}>}
|
|
334
|
+
*/
|
|
335
|
+
async publicKeyToDidDoc({ url, id, publicKeyDescription } = {}) {
|
|
336
|
+
if (!publicKeyDescription) {
|
|
337
|
+
throw new TypeError('"publicKeyDescription" is required.');
|
|
338
|
+
}
|
|
339
|
+
if (!url && !id) {
|
|
340
|
+
throw new TypeError('A "url" or "id" is required to build a did:web document.');
|
|
341
|
+
}
|
|
342
|
+
const did = id ?? didFromUrl({ url });
|
|
343
|
+
const didDocument = { '@context': [DID_CONTEXT_URL], id: did };
|
|
344
|
+
const keyPair = await this._toKeyPair(publicKeyDescription);
|
|
345
|
+
this.addVerificationMethod({ didDocument, keyPair, purposes: DEFAULT_PURPOSES });
|
|
346
|
+
return { didDocument };
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Computes the id of a given key pair (used by `did-io` drivers). For
|
|
350
|
+
* `did:web` the id depends on the document's DID, so the key pair must
|
|
351
|
+
* already carry an `id` or a `controller`.
|
|
352
|
+
*
|
|
353
|
+
* @param options {object} - Options hashmap.
|
|
354
|
+
* @param options.keyPair {object} - The key pair.
|
|
355
|
+
*
|
|
356
|
+
* @returns {Promise<string>} The key's id.
|
|
357
|
+
*/
|
|
358
|
+
async computeId({ keyPair }) {
|
|
359
|
+
if (keyPair?.id) {
|
|
360
|
+
return keyPair.id;
|
|
361
|
+
}
|
|
362
|
+
if (keyPair?.controller) {
|
|
363
|
+
return `${keyPair.controller}#${_defaultFragment(keyPair)}`;
|
|
364
|
+
}
|
|
365
|
+
throw new TypeError('Cannot compute id: key pair has no "id" or "controller".');
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Fetches a `did:web` DID Document for a given DID, or dereferences a subnode
|
|
369
|
+
* when the DID carries a `#fragment`. Applies the SSRF allow list, network
|
|
370
|
+
* limits, and verifies that the fetched document's `id` matches the DID.
|
|
371
|
+
*
|
|
372
|
+
* @param options {object} - Options hashmap.
|
|
373
|
+
* @param [options.did] {string} - For example, 'did:web:example.com'.
|
|
374
|
+
* @param [options.url] {string} - Alias for `did`, for readability.
|
|
375
|
+
* @param [options.agent] {object} - Optional agent to customize network
|
|
376
|
+
* behavior in Node.js (such as `rejectUnauthorized: false`).
|
|
377
|
+
* @param [options.fetchOptions] {object} - Per-request network limits,
|
|
378
|
+
* merged over the driver's defaults.
|
|
379
|
+
* @param [options.logger] {object} - Logger object.
|
|
380
|
+
*
|
|
381
|
+
* @throws {Error}
|
|
382
|
+
*
|
|
383
|
+
* @returns {Promise<object>} The DID Document, or a public key / subnode.
|
|
384
|
+
*/
|
|
385
|
+
async get({ did, url, agent, fetchOptions = {}, logger = this.logger } = {}) {
|
|
386
|
+
did = did ?? url;
|
|
387
|
+
if (!did) {
|
|
388
|
+
throw new TypeError('A DID or a URL is required to fetch.');
|
|
389
|
+
}
|
|
390
|
+
// Separate the bare DID authority from any `?query` or `#fragment`.
|
|
391
|
+
const [didAuthority = ''] = did.split(/[#?]/);
|
|
392
|
+
const fragment = did.includes('#')
|
|
393
|
+
? did.slice(did.indexOf('#') + 1)
|
|
394
|
+
: undefined;
|
|
395
|
+
const fetchUrl = urlFromDid({ did: didAuthority });
|
|
396
|
+
// SSRF gate: reject disallowed hosts before making any network request.
|
|
397
|
+
assertDomain({ allowList: this.allowList, url: fetchUrl });
|
|
398
|
+
let didDocument;
|
|
399
|
+
try {
|
|
400
|
+
logger.info(`Fetching "${fetchUrl}" via http client.`);
|
|
401
|
+
const result = await httpClient.get(fetchUrl, { ...this.fetchOptions, ...fetchOptions, agent });
|
|
402
|
+
didDocument = result.data;
|
|
403
|
+
}
|
|
404
|
+
catch (err) {
|
|
405
|
+
// status is HTTP status code; data is the server's JSON error if any.
|
|
406
|
+
const { data, status } = err ?? {};
|
|
407
|
+
logger.error(`Http ${status ?? ''} error:`, data);
|
|
408
|
+
throw err;
|
|
409
|
+
}
|
|
410
|
+
if (didDocument?.id !== didAuthority) {
|
|
411
|
+
throw new Error(`DID document for DID "${didAuthority}" not found.`);
|
|
412
|
+
}
|
|
413
|
+
if (fragment) {
|
|
414
|
+
// Dereference an individual subnode (key or service) by id.
|
|
415
|
+
return getNode({ didDocument, id: `${didDocument.id}#${fragment}` });
|
|
416
|
+
}
|
|
417
|
+
return didDocument;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Returns the public key (verification method) object for a given DID
|
|
421
|
+
* Document and purpose. Useful in conjunction with a `.get()` call.
|
|
422
|
+
*
|
|
423
|
+
* @param options {object} - Options hashmap.
|
|
424
|
+
* @param options.didDocument {object} - DID Document (retrieved via a
|
|
425
|
+
* `.get()` or from some other source).
|
|
426
|
+
* @param options.purpose {string} - Verification method purpose, such as
|
|
427
|
+
* 'authentication', 'assertionMethod', 'keyAgreement' and so on.
|
|
428
|
+
*
|
|
429
|
+
* @returns {object} The public key object (without a `@context`).
|
|
430
|
+
*/
|
|
431
|
+
publicMethodFor({ didDocument, purpose }) {
|
|
432
|
+
if (!didDocument) {
|
|
433
|
+
throw new TypeError('The "didDocument" parameter is required.');
|
|
434
|
+
}
|
|
435
|
+
if (!purpose) {
|
|
436
|
+
throw new TypeError('The "purpose" parameter is required.');
|
|
437
|
+
}
|
|
438
|
+
const method = didIo.findVerificationMethod({ doc: didDocument, purpose });
|
|
439
|
+
if (!method) {
|
|
440
|
+
throw new Error(`No verification method found for purpose "${purpose}"`);
|
|
441
|
+
}
|
|
442
|
+
return method;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Generates a verification key pair from a registered suite.
|
|
446
|
+
*
|
|
447
|
+
* @param options {object} - Options hashmap.
|
|
448
|
+
* @param [options.seed] {string|Uint8Array} - Secret seed.
|
|
449
|
+
* @param [options.keyType] {Function|string} - Which registered suite to use.
|
|
450
|
+
*
|
|
451
|
+
* @returns {Promise<object>} The generated key pair.
|
|
452
|
+
*/
|
|
453
|
+
async _generateKeyPair({ seed, keyType } = {}) {
|
|
454
|
+
let header;
|
|
455
|
+
if (keyType) {
|
|
456
|
+
header = typeof keyType === 'string' ? keyType : keyType.multibaseHeader;
|
|
457
|
+
}
|
|
458
|
+
else if (this._allowedKeyTypes.size === 1) {
|
|
459
|
+
;
|
|
460
|
+
[header] = this._allowedKeyTypes.keys();
|
|
461
|
+
}
|
|
462
|
+
else if (this._allowedKeyTypes.size === 0) {
|
|
463
|
+
throw new Error('No key suite registered; call "use({keyPairClass})" or pass a ' +
|
|
464
|
+
'"verificationKeyPair".');
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
throw new Error('Multiple key suites registered; specify which via "keyType" or pass ' +
|
|
468
|
+
'a "verificationKeyPair".');
|
|
469
|
+
}
|
|
470
|
+
const registered = this._allowedKeyTypes.get(header);
|
|
471
|
+
if (!registered?.generate) {
|
|
472
|
+
throw new Error(`Registered suite "${header}" cannot generate keys; register it via ` +
|
|
473
|
+
'"use({keyPairClass})".');
|
|
474
|
+
}
|
|
475
|
+
const seedBytes = seed === undefined ? undefined : _decodeSeed(seed);
|
|
476
|
+
return registered.generate({ seed: seedBytes });
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Resolves a key pair instance from either a live key pair (with `.export`)
|
|
480
|
+
* or a plain public key description (rebuilt via the registry).
|
|
481
|
+
*
|
|
482
|
+
* @param description {object} - A key pair instance or key description.
|
|
483
|
+
*
|
|
484
|
+
* @returns {Promise<object>} A live key pair instance.
|
|
485
|
+
*/
|
|
486
|
+
async _toKeyPair(description) {
|
|
487
|
+
if (typeof description?.export === 'function') {
|
|
488
|
+
return description;
|
|
489
|
+
}
|
|
490
|
+
const publicKeyMultibase = description?.publicKeyMultibase;
|
|
491
|
+
if (!publicKeyMultibase) {
|
|
492
|
+
throw new TypeError('"publicKeyMultibase" is required to rebuild a key pair.');
|
|
493
|
+
}
|
|
494
|
+
const header = publicKeyMultibase.slice(0, 4);
|
|
495
|
+
const registered = this._allowedKeyTypes.get(header);
|
|
496
|
+
if (!registered) {
|
|
497
|
+
throw new Error(`Unsupported multibase header "${header}". Register the suite via ` +
|
|
498
|
+
'"use()".');
|
|
499
|
+
}
|
|
500
|
+
return registered.fromMultibase({ publicKeyMultibase });
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Adds one or more contexts to a DID document's `@context`, de-duplicating.
|
|
505
|
+
*
|
|
506
|
+
* @param options {object} - Options hashmap.
|
|
507
|
+
* @param options.didDocument {object} - The document to mutate.
|
|
508
|
+
* @param options.context {string|string[]} - Context(s) to add.
|
|
509
|
+
*/
|
|
510
|
+
function _addContext({ didDocument, context }) {
|
|
511
|
+
const contexts = Array.isArray(didDocument['@context'])
|
|
512
|
+
? didDocument['@context']
|
|
513
|
+
: [didDocument['@context']];
|
|
514
|
+
const toAdd = Array.isArray(context) ? context : [context];
|
|
515
|
+
for (const ctx of toAdd) {
|
|
516
|
+
if (!contexts.includes(ctx)) {
|
|
517
|
+
contexts.push(ctx);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
didDocument['@context'] = contexts;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Returns a default fragment for a key pair: its fingerprint when available,
|
|
524
|
+
* otherwise its `publicKeyMultibase`.
|
|
525
|
+
*
|
|
526
|
+
* @param keyPair {object} - The key pair.
|
|
527
|
+
*
|
|
528
|
+
* @returns {string} The fragment (without a leading `#`).
|
|
529
|
+
*/
|
|
530
|
+
function _defaultFragment(keyPair) {
|
|
531
|
+
if (typeof keyPair?.fingerprint === 'function') {
|
|
532
|
+
return keyPair.fingerprint();
|
|
533
|
+
}
|
|
534
|
+
if (keyPair?.publicKeyMultibase) {
|
|
535
|
+
return keyPair.publicKeyMultibase;
|
|
536
|
+
}
|
|
537
|
+
throw new TypeError('Cannot determine a default fragment; provide a "fragment".');
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Decodes a secret key seed to bytes. Accepts a multibase/multihash-encoded
|
|
541
|
+
* string (must start with `z1A`) or a `Uint8Array`.
|
|
542
|
+
*
|
|
543
|
+
* @param seed {string|Uint8Array} - The seed.
|
|
544
|
+
*
|
|
545
|
+
* @returns {Uint8Array} The decoded seed bytes.
|
|
546
|
+
*/
|
|
547
|
+
function _decodeSeed(seed) {
|
|
548
|
+
if (typeof seed === 'string') {
|
|
549
|
+
if (!seed.startsWith('z1A')) {
|
|
550
|
+
throw new TypeError('"seed" parameter must be a multibase/multihash encoded string, or a ' +
|
|
551
|
+
'Uint8Array.');
|
|
552
|
+
}
|
|
553
|
+
return decodeSecretKeySeed({ secretKeySeed: seed });
|
|
554
|
+
}
|
|
555
|
+
return new Uint8Array(seed);
|
|
556
|
+
}
|
|
557
|
+
//# sourceMappingURL=DidWebResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DidWebResolver.js","sourceRoot":"","sources":["../src/DidWebResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assertions guarding the resolver's network path: that a fetch target is an
|
|
3
|
+
* HTTPS URL, that an identifier is a well-formed `did:web` DID, and that a
|
|
4
|
+
* target host is permitted by an optional allow list (SSRF gate).
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Asserts that the given value is an HTTPS URL.
|
|
8
|
+
*
|
|
9
|
+
* @param url {URL|string} - The URL to check.
|
|
10
|
+
*
|
|
11
|
+
* @throws {TypeError} If the value is not a URL or its protocol is not https.
|
|
12
|
+
*/
|
|
13
|
+
export declare function assertHttpsUrl(url: URL | string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Coerces a string to a `URL`, or returns an existing `URL` instance.
|
|
16
|
+
*
|
|
17
|
+
* @param url {URL|string} - The value to coerce.
|
|
18
|
+
*
|
|
19
|
+
* @returns {URL} The parsed URL.
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertUrl(url: URL | string): URL;
|
|
22
|
+
/**
|
|
23
|
+
* Asserts that a DID is a well-formed `did:web` identifier whose
|
|
24
|
+
* method-specific id (the domain component) does not itself contain a path.
|
|
25
|
+
* Sets `err.code` to `'invalidDid'` or `'methodNotSupported'` where relevant.
|
|
26
|
+
*
|
|
27
|
+
* @param did {string} - The DID to check.
|
|
28
|
+
*
|
|
29
|
+
* @throws {Error} If the DID is missing, malformed, or not a did:web DID.
|
|
30
|
+
*/
|
|
31
|
+
export declare function assertDidWebUrl(did: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* SSRF gate: asserts that the host of `url` is present in `allowList`. An empty
|
|
34
|
+
* or absent allow list disables the check (all hosts permitted).
|
|
35
|
+
*
|
|
36
|
+
* @param options {object} - Options hashmap.
|
|
37
|
+
* @param [options.allowList] {string[]} - Permitted hosts (e.g. 'example.com'
|
|
38
|
+
* or 'example.com:3000'). When empty/absent, no restriction is applied.
|
|
39
|
+
* @param options.url {URL|string} - The fetch target URL.
|
|
40
|
+
*
|
|
41
|
+
* @throws {Error} If the host is not in a non-empty allow list.
|
|
42
|
+
*/
|
|
43
|
+
export declare function assertDomain({ allowList, url }: {
|
|
44
|
+
allowList?: string[];
|
|
45
|
+
url: URL | string;
|
|
46
|
+
}): void;
|
|
47
|
+
//# sourceMappingURL=assertions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAE,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAMvD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAE,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,GAAG,CAQjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CA0BlD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAAA;CAAE,GAC9D,IAAI,CASN"}
|