signify-ts 0.4.0 → 0.4.1
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 +18 -0
- package/dist/exports.d.ts +1 -0
- package/dist/exports.js +1 -0
- package/dist/keri/app/aiding.d.ts +20 -5
- package/dist/keri/app/aiding.js +14 -18
- package/dist/keri/app/clienting.d.ts +27 -24
- package/dist/keri/app/clienting.js +86 -92
- package/dist/keri/app/controller.d.ts +4 -1
- package/dist/keri/app/controller.js +7 -3
- package/dist/keri/core/authing.d.ts +24 -5
- package/dist/keri/core/authing.js +188 -15
- package/dist/keri/core/eventing.js +1 -1
- package/dist/keri/core/httping.d.ts +3 -0
- package/dist/keri/core/httping.js +3 -0
- package/dist/keri/core/keeping.d.ts +7 -20
- package/dist/keri/core/keeping.js +9 -4
- package/dist/keri/core/keyState.d.ts +29 -3
- package/dist/keri/core/keyState.js +9 -1
- package/dist/keri/end/ending.js +2 -1
- package/dist/types/keria-api-schema.d.ts +142 -209
- package/dist/types/keria-api-schema.js +5 -0
- package/package.json +4 -4
- package/dist/keri/app/didwebing.d.ts +0 -146
- package/dist/keri/app/didwebing.js +0 -359
- package/dist/keri/app/signaling.d.ts +0 -50
- package/dist/keri/app/signaling.js +0 -52
- package/dist/keri/app/w3cing.d.ts +0 -137
- package/dist/keri/app/w3cing.js +0 -337
package/README.md
CHANGED
|
@@ -154,6 +154,20 @@ Account Creation Workflow
|
|
|
154
154
|
|
|
155
155
|
This package is published on npm: https://www.npmjs.com/package/signify-ts.
|
|
156
156
|
|
|
157
|
+
## Release publishing
|
|
158
|
+
|
|
159
|
+
Releases are published with npm trusted publishing from GitHub Actions. The
|
|
160
|
+
normal release flow is:
|
|
161
|
+
|
|
162
|
+
1. Validate the release locally.
|
|
163
|
+
2. Create and push a signed version tag.
|
|
164
|
+
3. Run the `Publish NPM` workflow against that tag with the intended npm dist tag.
|
|
165
|
+
4. Approve the `npm-publish` GitHub environment when prompted.
|
|
166
|
+
5. Verify the published package and npm dist tag.
|
|
167
|
+
|
|
168
|
+
The npm package has a trusted publisher configured for the `WebOfTrust/signify-ts` repository,
|
|
169
|
+
the `publish-npm.yml` workflow, and the `npm-publish` environment.
|
|
170
|
+
|
|
157
171
|
If you need to publish a version under your own scope, you can use the [publish script](./publish.sh). This enables you to create development packages. For example:
|
|
158
172
|
|
|
159
173
|
```bash
|
|
@@ -189,3 +203,7 @@ npm notice
|
|
|
189
203
|
npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)
|
|
190
204
|
+ @myorg/signify-ts@0.3.0-rc1
|
|
191
205
|
```
|
|
206
|
+
|
|
207
|
+
Direct local publishing to the public `signify-ts` package should be treated as
|
|
208
|
+
an emergency fallback. It requires an npm account with publish access and any
|
|
209
|
+
OTP required by npm.
|
package/dist/exports.d.ts
CHANGED
package/dist/exports.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Tier } from '../core/salter.ts';
|
|
|
2
2
|
import { Algos } from '../core/manager.ts';
|
|
3
3
|
import { Serder } from '../core/serder.ts';
|
|
4
4
|
import { IdentifierManagerFactory } from '../core/keeping.ts';
|
|
5
|
-
import { HabState } from '../core/keyState.ts';
|
|
5
|
+
import { HabState, PendingHabState } from '../core/keyState.ts';
|
|
6
6
|
import { components } from '../../types/keria-api-schema.ts';
|
|
7
7
|
/** Arguments required to create an identfier */
|
|
8
8
|
export interface CreateIdentiferArgs {
|
|
@@ -86,17 +86,32 @@ export declare class Identifier {
|
|
|
86
86
|
* Get information for a managed identifier
|
|
87
87
|
* @async
|
|
88
88
|
* @param {string} name Prefix or alias of the identifier
|
|
89
|
-
* @
|
|
89
|
+
* @param {boolean} [requireAccepted=true] When true, requires key state to
|
|
90
|
+
* be present and throws otherwise. Key state is absent only for a
|
|
91
|
+
* multisig group whose inception is still collecting member
|
|
92
|
+
* signatures; pass false to fetch such a pending group.
|
|
93
|
+
* @returns {Promise<HabState | PendingHabState>} A promise to the
|
|
94
|
+
* identifier information, narrowed to HabState unless requireAccepted
|
|
95
|
+
* is false
|
|
90
96
|
*/
|
|
91
|
-
get(name: string): Promise<HabState>;
|
|
97
|
+
get(name: string, requireAccepted?: true): Promise<HabState>;
|
|
98
|
+
get(name: string, requireAccepted: false): Promise<HabState | PendingHabState>;
|
|
99
|
+
get(name: string, requireAccepted: boolean): Promise<HabState | PendingHabState>;
|
|
92
100
|
/**
|
|
93
101
|
* Update managed identifier
|
|
94
102
|
* @async
|
|
95
103
|
* @param {string} name Prefix or alias of the identifier
|
|
96
104
|
* @param {IdentifierInfo} info Information to update for the given identifier
|
|
97
|
-
* @
|
|
105
|
+
* @param {boolean} [requireAccepted=true] When true, requires key state to
|
|
106
|
+
* be present on the updated identifier and throws otherwise; pass
|
|
107
|
+
* false to update a still-pending multisig group.
|
|
108
|
+
* @returns {Promise<HabState | PendingHabState>} A promise to the
|
|
109
|
+
* identifier information after updating, narrowed to HabState unless
|
|
110
|
+
* requireAccepted is false
|
|
98
111
|
*/
|
|
99
|
-
update(name: string, info: IdentifierInfo): Promise<HabState>;
|
|
112
|
+
update(name: string, info: IdentifierInfo, requireAccepted?: true): Promise<HabState>;
|
|
113
|
+
update(name: string, info: IdentifierInfo, requireAccepted: false): Promise<HabState | PendingHabState>;
|
|
114
|
+
update(name: string, info: IdentifierInfo, requireAccepted: boolean): Promise<HabState | PendingHabState>;
|
|
100
115
|
/**
|
|
101
116
|
* Create a managed identifier
|
|
102
117
|
* @async
|
package/dist/keri/app/aiding.js
CHANGED
|
@@ -4,6 +4,7 @@ import { b, Ilks, Serials, Vrsn_1_0 } from "../core/core.js";
|
|
|
4
4
|
import { Tholder } from "../core/tholder.js";
|
|
5
5
|
import { MtrDex } from "../core/matter.js";
|
|
6
6
|
import { parseRangeHeaders } from "../core/httping.js";
|
|
7
|
+
import { requireKeyState, } from "../core/keyState.js";
|
|
7
8
|
/** Identifier */
|
|
8
9
|
export class Identifier {
|
|
9
10
|
/**
|
|
@@ -37,31 +38,26 @@ export class Identifier {
|
|
|
37
38
|
aids: aids,
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* @async
|
|
43
|
-
* @param {string} name Prefix or alias of the identifier
|
|
44
|
-
* @returns {Promise<HabState>} A promise to the identifier information
|
|
45
|
-
*/
|
|
46
|
-
async get(name) {
|
|
47
|
-
const path = `/identifiers/${encodeURIComponent(name)}`;
|
|
41
|
+
async get(name, requireAccepted = true) {
|
|
42
|
+
const path = `/identifiers/${name}`;
|
|
48
43
|
const data = null;
|
|
49
44
|
const method = 'GET';
|
|
50
45
|
const res = await this.client.fetch(path, method, data);
|
|
51
|
-
|
|
46
|
+
const hab = await res.json();
|
|
47
|
+
if (requireAccepted) {
|
|
48
|
+
requireKeyState(hab);
|
|
49
|
+
}
|
|
50
|
+
return hab;
|
|
52
51
|
}
|
|
53
|
-
|
|
54
|
-
* Update managed identifier
|
|
55
|
-
* @async
|
|
56
|
-
* @param {string} name Prefix or alias of the identifier
|
|
57
|
-
* @param {IdentifierInfo} info Information to update for the given identifier
|
|
58
|
-
* @returns {Promise<HabState>} A promise to the identifier information after updating
|
|
59
|
-
*/
|
|
60
|
-
async update(name, info) {
|
|
52
|
+
async update(name, info, requireAccepted = true) {
|
|
61
53
|
const path = `/identifiers/${name}`;
|
|
62
54
|
const method = 'PUT';
|
|
63
55
|
const res = await this.client.fetch(path, method, info);
|
|
64
|
-
|
|
56
|
+
const hab = await res.json();
|
|
57
|
+
if (requireAccepted) {
|
|
58
|
+
requireKeyState(hab);
|
|
59
|
+
}
|
|
60
|
+
return hab;
|
|
65
61
|
}
|
|
66
62
|
/**
|
|
67
63
|
* Create a managed identifier
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { Authenticator } from '../core/authing.ts';
|
|
1
2
|
import { components } from '../../types/keria-api-schema.ts';
|
|
2
|
-
import { Authenticater } from '../core/authing.ts';
|
|
3
3
|
import { ExternalModule, IdentifierManagerFactory } from '../core/keeping.ts';
|
|
4
4
|
import { Tier } from '../core/salter.ts';
|
|
5
5
|
import { Identifier } from './aiding.ts';
|
|
@@ -13,6 +13,10 @@ import { Exchanges } from './exchanging.ts';
|
|
|
13
13
|
import { Groups } from './grouping.ts';
|
|
14
14
|
import { Notifications } from './notifying.ts';
|
|
15
15
|
export type AgentResourceResult = components['schemas']['AgentResourceResult'];
|
|
16
|
+
/** Cancellation options for booting or connecting a Signify client. */
|
|
17
|
+
export interface ConnectionOptions {
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}
|
|
16
20
|
declare class State {
|
|
17
21
|
agent: any | null;
|
|
18
22
|
controller: any | null;
|
|
@@ -20,6 +24,10 @@ declare class State {
|
|
|
20
24
|
pidx: number;
|
|
21
25
|
constructor();
|
|
22
26
|
}
|
|
27
|
+
export declare enum AuthMode {
|
|
28
|
+
SignedHeaders = "SIGNED_HEADERS",
|
|
29
|
+
ESSR = "ESSR"
|
|
30
|
+
}
|
|
23
31
|
/**
|
|
24
32
|
* An in-memory key manager that can connect to a KERIA Agent and use it to
|
|
25
33
|
* receive messages and act as a proxy for multi-signature operations and delegation operations.
|
|
@@ -30,11 +38,12 @@ export declare class SignifyClient {
|
|
|
30
38
|
bran: string;
|
|
31
39
|
pidx: number;
|
|
32
40
|
agent: Agent | null;
|
|
33
|
-
authn:
|
|
41
|
+
authn: Authenticator | null;
|
|
34
42
|
manager: IdentifierManagerFactory | null;
|
|
35
43
|
tier: Tier;
|
|
36
44
|
bootUrl: string;
|
|
37
45
|
exteralModules: ExternalModule[];
|
|
46
|
+
authMode: AuthMode;
|
|
38
47
|
private _identifiers;
|
|
39
48
|
private _operations;
|
|
40
49
|
private _keyEvents;
|
|
@@ -60,34 +69,40 @@ export declare class SignifyClient {
|
|
|
60
69
|
* @param {string} bootUrl KERIA boot interface URL
|
|
61
70
|
* @param {ExternalModule[]} externalModules list of external modules to load
|
|
62
71
|
*/
|
|
63
|
-
constructor(url: string, bran: string, tier?: Tier, bootUrl?: string, externalModules?: ExternalModule[]);
|
|
64
|
-
get data(): (string | number |
|
|
72
|
+
constructor(url: string, bran: string, tier?: Tier, bootUrl?: string, externalModules?: ExternalModule[], authMode?: AuthMode);
|
|
73
|
+
get data(): (string | number | Authenticator | null)[];
|
|
65
74
|
/**
|
|
66
75
|
* Boot a KERIA agent
|
|
67
76
|
* @async
|
|
77
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
68
78
|
* @returns {Promise<Response>} A promise to the result of the boot
|
|
69
79
|
*/
|
|
70
|
-
boot(): Promise<Response>;
|
|
80
|
+
boot(options?: ConnectionOptions): Promise<Response>;
|
|
71
81
|
/**
|
|
72
82
|
* Get state of the agent and the client
|
|
73
83
|
* @async
|
|
84
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
74
85
|
* @returns {Promise<Response>} A promise to the state
|
|
75
86
|
*/
|
|
76
|
-
state(): Promise<State>;
|
|
77
|
-
/**
|
|
87
|
+
state(options?: ConnectionOptions): Promise<State>;
|
|
88
|
+
/**
|
|
89
|
+
* Connect to an existing KERIA Agent and restore its in-memory Controller,
|
|
90
|
+
* load agent state, and initialize authenticated client services.
|
|
91
|
+
*
|
|
78
92
|
* @async
|
|
93
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
79
94
|
*/
|
|
80
|
-
connect(): Promise<void>;
|
|
95
|
+
connect(options?: ConnectionOptions): Promise<void>;
|
|
81
96
|
/**
|
|
82
97
|
* Fetch a resource from the KERIA agent
|
|
83
98
|
* @async
|
|
84
99
|
* @param {string} path Path to the resource
|
|
85
100
|
* @param {string} method HTTP method
|
|
86
|
-
* @param {
|
|
101
|
+
* @param {unknown} [data] Data to be sent in the body of the resource
|
|
87
102
|
* @param {Headers} [extraHeaders] Optional extra headers to be sent with the request
|
|
88
103
|
* @returns {Promise<Response>} A promise to the result of the fetch
|
|
89
104
|
*/
|
|
90
|
-
fetch(path: string, method: string, data
|
|
105
|
+
fetch(path: string, method: string, data?: unknown, extraHeaders?: Headers): Promise<Response>;
|
|
91
106
|
/**
|
|
92
107
|
* Create a Signed Request to fetch a resource from an external URL with headers signed by an AID
|
|
93
108
|
* @async
|
|
@@ -106,22 +121,10 @@ export declare class SignifyClient {
|
|
|
106
121
|
/**
|
|
107
122
|
* Approve the delegation of the client AID to the KERIA agent
|
|
108
123
|
* @async
|
|
124
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
109
125
|
* @returns {Promise<Response>} A promise to the result of the approval
|
|
110
126
|
*/
|
|
111
|
-
approveDelegation
|
|
112
|
-
/**
|
|
113
|
-
* Save old client passcode in KERIA agent
|
|
114
|
-
* @async
|
|
115
|
-
* @param {string} passcode Passcode to be saved
|
|
116
|
-
* @returns {Promise<Response>} A promise to the result of the save
|
|
117
|
-
*/
|
|
118
|
-
saveOldPasscode(passcode: string): Promise<Response>;
|
|
119
|
-
/**
|
|
120
|
-
* Delete a saved passcode from KERIA agent
|
|
121
|
-
* @async
|
|
122
|
-
* @returns {Promise<Response>} A promise to the result of the deletion
|
|
123
|
-
*/
|
|
124
|
-
deletePasscode(): Promise<Response>;
|
|
127
|
+
private approveDelegation;
|
|
125
128
|
/**
|
|
126
129
|
* Rotate the client AID
|
|
127
130
|
* @async
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HEADER_SIG_TIME } from "../core/httping.js";
|
|
1
|
+
import { EssrAuthenticator, SignedHeaderAuthenticator, } from "../core/authing.js";
|
|
2
|
+
import { HEADER_SIG_SENDER, HEADER_SIG_TIME } from "../core/httping.js";
|
|
3
3
|
import { IdentifierManagerFactory } from "../core/keeping.js";
|
|
4
|
+
import { CesrNumber } from "../core/number.js";
|
|
4
5
|
import { Tier } from "../core/salter.js";
|
|
5
6
|
import { Identifier } from "./aiding.js";
|
|
6
7
|
import { Contacts, Challenges } from "./contacting.js";
|
|
@@ -21,6 +22,16 @@ class State {
|
|
|
21
22
|
this.ridx = 0;
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
export var AuthMode;
|
|
26
|
+
(function (AuthMode) {
|
|
27
|
+
AuthMode["SignedHeaders"] = "SIGNED_HEADERS";
|
|
28
|
+
AuthMode["ESSR"] = "ESSR";
|
|
29
|
+
})(AuthMode || (AuthMode = {}));
|
|
30
|
+
function jsonBody(data) {
|
|
31
|
+
// typed as string, but returns undefined for undefined/functions/symbols
|
|
32
|
+
const json = JSON.stringify(data);
|
|
33
|
+
return json !== null && json !== void 0 ? json : null;
|
|
34
|
+
}
|
|
24
35
|
/**
|
|
25
36
|
* An in-memory key manager that can connect to a KERIA Agent and use it to
|
|
26
37
|
* receive messages and act as a proxy for multi-signature operations and delegation operations.
|
|
@@ -34,7 +45,7 @@ export class SignifyClient {
|
|
|
34
45
|
* @param {string} bootUrl KERIA boot interface URL
|
|
35
46
|
* @param {ExternalModule[]} externalModules list of external modules to load
|
|
36
47
|
*/
|
|
37
|
-
constructor(url, bran, tier = Tier.low, bootUrl = DEFAULT_BOOT_URL, externalModules = []) {
|
|
48
|
+
constructor(url, bran, tier = Tier.low, bootUrl = DEFAULT_BOOT_URL, externalModules = [], authMode = AuthMode.SignedHeaders) {
|
|
38
49
|
this._identifiers = new Identifier(this);
|
|
39
50
|
this._operations = new Operations(this);
|
|
40
51
|
this._keyEvents = new KeyEvents(this);
|
|
@@ -65,6 +76,7 @@ export class SignifyClient {
|
|
|
65
76
|
this.tier = tier;
|
|
66
77
|
this.bootUrl = bootUrl;
|
|
67
78
|
this.exteralModules = externalModules;
|
|
79
|
+
this.authMode = authMode;
|
|
68
80
|
}
|
|
69
81
|
get data() {
|
|
70
82
|
return [this.url, this.bran, this.pidx, this.authn];
|
|
@@ -72,9 +84,10 @@ export class SignifyClient {
|
|
|
72
84
|
/**
|
|
73
85
|
* Boot a KERIA agent
|
|
74
86
|
* @async
|
|
87
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
75
88
|
* @returns {Promise<Response>} A promise to the result of the boot
|
|
76
89
|
*/
|
|
77
|
-
async boot() {
|
|
90
|
+
async boot(options = {}) {
|
|
78
91
|
var _a, _b, _c, _d;
|
|
79
92
|
const [evt, sign] = (_b = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.event) !== null && _b !== void 0 ? _b : [];
|
|
80
93
|
const data = {
|
|
@@ -90,17 +103,21 @@ export class SignifyClient {
|
|
|
90
103
|
headers: {
|
|
91
104
|
'Content-Type': 'application/json',
|
|
92
105
|
},
|
|
106
|
+
signal: options.signal,
|
|
93
107
|
});
|
|
94
108
|
}
|
|
95
109
|
/**
|
|
96
110
|
* Get state of the agent and the client
|
|
97
111
|
* @async
|
|
112
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
98
113
|
* @returns {Promise<Response>} A promise to the state
|
|
99
114
|
*/
|
|
100
|
-
async state() {
|
|
115
|
+
async state(options = {}) {
|
|
101
116
|
var _a, _b, _c, _d, _e;
|
|
102
117
|
const caid = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.pre;
|
|
103
|
-
const res = await fetch(this.url + `/agent/${caid}
|
|
118
|
+
const res = await fetch(this.url + `/agent/${caid}`, {
|
|
119
|
+
signal: options.signal,
|
|
120
|
+
});
|
|
104
121
|
if (res.status == 404) {
|
|
105
122
|
throw new Error(`agent does not exist for controller ${caid}`);
|
|
106
123
|
}
|
|
@@ -112,79 +129,77 @@ export class SignifyClient {
|
|
|
112
129
|
state.pidx = (_e = data.pidx) !== null && _e !== void 0 ? _e : 0;
|
|
113
130
|
return state;
|
|
114
131
|
}
|
|
115
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* Connect to an existing KERIA Agent and restore its in-memory Controller,
|
|
134
|
+
* load agent state, and initialize authenticated client services.
|
|
135
|
+
*
|
|
116
136
|
* @async
|
|
137
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
117
138
|
*/
|
|
118
|
-
async connect() {
|
|
119
|
-
|
|
139
|
+
async connect(options = {}) {
|
|
140
|
+
var _a, _b;
|
|
141
|
+
const state = await this.state(options);
|
|
120
142
|
this.pidx = state.pidx;
|
|
121
|
-
//
|
|
143
|
+
// Restore the controller from KERIA's authoritative persisted state.
|
|
122
144
|
this.controller = new Controller(this.bran, this.tier, 0, state.controller);
|
|
123
145
|
this.controller.ridx = state.ridx !== undefined ? state.ridx : 0;
|
|
124
146
|
// Create agent representing the AID of KERIA cloud agent
|
|
125
147
|
this.agent = new Agent(state.agent);
|
|
126
|
-
if (this.agent.anchor
|
|
148
|
+
if (this.agent.anchor !== this.controller.pre) {
|
|
127
149
|
throw Error('commitment to controller AID missing in agent inception event');
|
|
128
150
|
}
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
const controllerSequence = (_b = (_a = state.controller) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.s;
|
|
152
|
+
if (typeof controllerSequence !== 'string') {
|
|
153
|
+
throw new Error('KERIA controller state is missing a string sequence number');
|
|
154
|
+
}
|
|
155
|
+
if (new CesrNumber({}, controllerSequence).num === 0) {
|
|
156
|
+
await this.approveDelegation(options);
|
|
131
157
|
}
|
|
132
158
|
this.manager = new IdentifierManagerFactory(this.controller.salter, this.exteralModules);
|
|
133
|
-
|
|
159
|
+
if (this.authMode === AuthMode.SignedHeaders) {
|
|
160
|
+
this.authn = new SignedHeaderAuthenticator(this.controller.signer, this.agent.verfer);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
this.authn = new EssrAuthenticator(this.controller.signer, this.agent.verfer);
|
|
164
|
+
}
|
|
134
165
|
}
|
|
135
166
|
/**
|
|
136
167
|
* Fetch a resource from the KERIA agent
|
|
137
168
|
* @async
|
|
138
169
|
* @param {string} path Path to the resource
|
|
139
170
|
* @param {string} method HTTP method
|
|
140
|
-
* @param {
|
|
171
|
+
* @param {unknown} [data] Data to be sent in the body of the resource
|
|
141
172
|
* @param {Headers} [extraHeaders] Optional extra headers to be sent with the request
|
|
142
173
|
* @returns {Promise<Response>} A promise to the result of the fetch
|
|
143
174
|
*/
|
|
144
175
|
async fetch(path, method, data, extraHeaders) {
|
|
145
|
-
|
|
176
|
+
if (!this.authn) {
|
|
177
|
+
throw new Error('Client needs to call connect first');
|
|
178
|
+
}
|
|
146
179
|
const headers = new Headers();
|
|
147
|
-
|
|
148
|
-
const final_headers = new Headers();
|
|
149
|
-
headers.set('Signify-Resource', this.controller.pre);
|
|
180
|
+
headers.set(HEADER_SIG_SENDER, this.controller.pre);
|
|
150
181
|
headers.set(HEADER_SIG_TIME, new Date().toISOString().replace('Z', '000+00:00'));
|
|
151
|
-
|
|
152
|
-
const _body = method == 'GET' ? null : JSON.stringify(data);
|
|
153
|
-
if (this.authn) {
|
|
154
|
-
signed_headers = this.authn.sign(headers, method, path.split('?')[0]);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
throw new Error('client need to call connect first');
|
|
158
|
-
}
|
|
159
|
-
signed_headers.forEach((value, key) => {
|
|
160
|
-
final_headers.set(key, value);
|
|
161
|
-
});
|
|
162
|
-
if (extraHeaders !== undefined) {
|
|
182
|
+
if (extraHeaders) {
|
|
163
183
|
extraHeaders.forEach((value, key) => {
|
|
164
|
-
|
|
184
|
+
headers.append(key, value);
|
|
165
185
|
});
|
|
166
186
|
}
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
187
|
+
const body = method === 'GET' ? null : jsonBody(data);
|
|
188
|
+
if (body) {
|
|
189
|
+
headers.set('Content-Type', 'application/json');
|
|
190
|
+
}
|
|
191
|
+
const baseRequest = new Request(this.url + path, {
|
|
192
|
+
method,
|
|
193
|
+
body,
|
|
194
|
+
headers,
|
|
171
195
|
});
|
|
196
|
+
const request = await this.authn.prepare(baseRequest, this.controller.pre, this.agent.pre);
|
|
197
|
+
const res = await this.authn.verify(baseRequest, await fetch(request), this.controller.pre, this.agent.pre);
|
|
172
198
|
if (!res.ok) {
|
|
173
199
|
const error = await res.text();
|
|
174
|
-
|
|
175
|
-
throw new Error(message);
|
|
176
|
-
}
|
|
177
|
-
const isSameAgent = ((_a = this.agent) === null || _a === void 0 ? void 0 : _a.pre) === res.headers.get('signify-resource');
|
|
178
|
-
if (!isSameAgent) {
|
|
179
|
-
throw new Error('message from a different remote agent');
|
|
180
|
-
}
|
|
181
|
-
const verification = this.authn.verify(res.headers, method, path.split('?')[0]);
|
|
182
|
-
if (verification) {
|
|
183
|
-
return res;
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
throw new Error('response verification failed');
|
|
200
|
+
throw new Error(`HTTP ${method} ${path} - ${res.status} ${res.statusText} - ${error}`);
|
|
187
201
|
}
|
|
202
|
+
return res;
|
|
188
203
|
}
|
|
189
204
|
/**
|
|
190
205
|
* Create a Signed Request to fetch a resource from an external URL with headers signed by an AID
|
|
@@ -204,65 +219,44 @@ export class SignifyClient {
|
|
|
204
219
|
var _a;
|
|
205
220
|
const hab = await this.identifiers().get(aidName);
|
|
206
221
|
const keeper = this.manager.get(hab);
|
|
207
|
-
const authenticator = new
|
|
222
|
+
const authenticator = new SignedHeaderAuthenticator(keeper.signers[0], keeper.signers[0].verfer);
|
|
208
223
|
const headers = new Headers(req.headers);
|
|
209
|
-
headers.set(
|
|
224
|
+
headers.set(HEADER_SIG_SENDER, hab.prefix);
|
|
210
225
|
headers.set(HEADER_SIG_TIME, new Date().toISOString().replace('Z', '000+00:00'));
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
226
|
+
return await authenticator.prepare(new Request(url, {
|
|
227
|
+
headers,
|
|
228
|
+
method: (_a = req.method) !== null && _a !== void 0 ? _a : 'GET',
|
|
229
|
+
body: req.body,
|
|
230
|
+
}), hab.prefix, hab.prefix);
|
|
214
231
|
}
|
|
215
232
|
/**
|
|
216
233
|
* Approve the delegation of the client AID to the KERIA agent
|
|
217
234
|
* @async
|
|
235
|
+
* @param {ConnectionOptions} [options] Cancellation options
|
|
218
236
|
* @returns {Promise<Response>} A promise to the result of the approval
|
|
219
237
|
*/
|
|
220
|
-
async approveDelegation() {
|
|
221
|
-
|
|
238
|
+
async approveDelegation(options = {}) {
|
|
239
|
+
var _a;
|
|
240
|
+
(_a = options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
|
|
241
|
+
const approval = this.controller.approveDelegation(this.agent);
|
|
222
242
|
const data = {
|
|
223
|
-
ixn:
|
|
224
|
-
sigs:
|
|
243
|
+
ixn: approval.event.sad,
|
|
244
|
+
sigs: approval.signatures,
|
|
225
245
|
};
|
|
226
|
-
|
|
246
|
+
const response = await fetch(this.url + '/agent/' + this.controller.pre + '?type=ixn', {
|
|
227
247
|
method: 'PUT',
|
|
228
248
|
body: JSON.stringify(data),
|
|
229
249
|
headers: {
|
|
230
250
|
'Content-Type': 'application/json',
|
|
231
251
|
},
|
|
252
|
+
signal: options.signal,
|
|
232
253
|
});
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
*/
|
|
240
|
-
async saveOldPasscode(passcode) {
|
|
241
|
-
var _a;
|
|
242
|
-
const caid = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.pre;
|
|
243
|
-
const body = { salt: passcode };
|
|
244
|
-
return await fetch(this.url + '/salt/' + caid, {
|
|
245
|
-
method: 'PUT',
|
|
246
|
-
body: JSON.stringify(body),
|
|
247
|
-
headers: {
|
|
248
|
-
'Content-Type': 'application/json',
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Delete a saved passcode from KERIA agent
|
|
254
|
-
* @async
|
|
255
|
-
* @returns {Promise<Response>} A promise to the result of the deletion
|
|
256
|
-
*/
|
|
257
|
-
async deletePasscode() {
|
|
258
|
-
var _a;
|
|
259
|
-
const caid = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.pre;
|
|
260
|
-
return await fetch(this.url + '/salt/' + caid, {
|
|
261
|
-
method: 'DELETE',
|
|
262
|
-
headers: {
|
|
263
|
-
'Content-Type': 'application/json',
|
|
264
|
-
},
|
|
265
|
-
});
|
|
254
|
+
if (!response.ok) {
|
|
255
|
+
const body = await response.text();
|
|
256
|
+
const details = body.length > 0 ? ` - ${body}` : '';
|
|
257
|
+
throw new Error(`agent delegation approval failed: ${response.status} ${response.statusText}${details}`);
|
|
258
|
+
}
|
|
259
|
+
return response;
|
|
266
260
|
}
|
|
267
261
|
/**
|
|
268
262
|
* Rotate the client AID
|
|
@@ -77,7 +77,10 @@ export declare class Controller {
|
|
|
77
77
|
* @param state
|
|
78
78
|
*/
|
|
79
79
|
constructor(bran: string, tier: Tier, ridx?: number, state?: any | null);
|
|
80
|
-
approveDelegation(_agent: Agent):
|
|
80
|
+
approveDelegation(_agent: Agent): {
|
|
81
|
+
event: Serder;
|
|
82
|
+
signatures: any[];
|
|
83
|
+
};
|
|
81
84
|
get pre(): string;
|
|
82
85
|
get event(): any[];
|
|
83
86
|
get verfers(): [];
|
|
@@ -107,7 +107,7 @@ export class Controller {
|
|
|
107
107
|
new Diger({ code: MtrDex.Blake3_256 }, this.nsigner.verfer.qb64b)
|
|
108
108
|
.qb64,
|
|
109
109
|
];
|
|
110
|
-
if (state
|
|
110
|
+
if (state === null || state['ee']['s'] === '0') {
|
|
111
111
|
this.serder = incept({
|
|
112
112
|
keys: this.keys,
|
|
113
113
|
isith: '1',
|
|
@@ -126,7 +126,7 @@ export class Controller {
|
|
|
126
126
|
const seqner = new Seqner({ sn: _agent.sn });
|
|
127
127
|
const anchor = { i: _agent.pre, s: seqner.snh, d: _agent.said };
|
|
128
128
|
const sn = new CesrNumber({}, this.serder.sad['s']).num + 1;
|
|
129
|
-
|
|
129
|
+
const event = interact({
|
|
130
130
|
pre: this.serder.pre,
|
|
131
131
|
dig: this.serder.sad['d'],
|
|
132
132
|
sn: sn,
|
|
@@ -134,7 +134,11 @@ export class Controller {
|
|
|
134
134
|
version: Vrsn_1_0,
|
|
135
135
|
kind: Serials.JSON,
|
|
136
136
|
});
|
|
137
|
-
|
|
137
|
+
this.serder = event;
|
|
138
|
+
return {
|
|
139
|
+
event,
|
|
140
|
+
signatures: [this.signer.sign(event.raw, 0).qb64],
|
|
141
|
+
};
|
|
138
142
|
}
|
|
139
143
|
get pre() {
|
|
140
144
|
return this.serder.pre;
|
|
@@ -1,10 +1,29 @@
|
|
|
1
1
|
import { Signer } from './signer.ts';
|
|
2
2
|
import { Verfer } from './verfer.ts';
|
|
3
|
-
export declare class
|
|
3
|
+
export declare abstract class Authenticator {
|
|
4
|
+
protected verfer: Verfer;
|
|
5
|
+
protected readonly csig: Signer;
|
|
6
|
+
constructor(csig: Signer, verfer: Verfer);
|
|
7
|
+
abstract prepare(request: Request, local: string, remote: string): Promise<Request>;
|
|
8
|
+
abstract verify(request: Request, response: Response, local: string, remote: string): Promise<Response>;
|
|
9
|
+
}
|
|
10
|
+
export declare class SignedHeaderAuthenticator extends Authenticator {
|
|
4
11
|
static DefaultFields: string[];
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
prepare(request: Request, _local: string, _remote: string): Promise<Request>;
|
|
13
|
+
verify(request: Request, response: Response, _local: string, remote: string): Promise<Response>;
|
|
14
|
+
private verifyHeaders;
|
|
15
|
+
private sign;
|
|
16
|
+
}
|
|
17
|
+
export declare class EssrAuthenticator extends Authenticator {
|
|
18
|
+
private readonly cx25519Pub;
|
|
19
|
+
private readonly cx25519Priv;
|
|
20
|
+
private readonly vx25519Pub;
|
|
7
21
|
constructor(csig: Signer, verfer: Verfer);
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
prepare(request: Request, local: string, remote: string): Promise<Request>;
|
|
23
|
+
verify(request: Request, response: Response, local: string, remote: string): Promise<Response>;
|
|
24
|
+
static serializeRequest(request: Request): Promise<string>;
|
|
25
|
+
static streamToBytes(stream: ReadableStream): Promise<Uint8Array>;
|
|
26
|
+
private unwrap;
|
|
27
|
+
private decrypt;
|
|
28
|
+
static deserializeResponse(httpString: string): Response;
|
|
10
29
|
}
|