@smarthome.exchange/api 1.0.1 → 1.1.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/changelog.md +14 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.smarthomeexchangeapiclient.d.ts +7 -0
- package/dist_ts/classes.smarthomeexchangeapiclient.js +23 -2
- package/package.json +10 -12
- package/readme.md +34 -4
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.smarthomeexchangeapiclient.ts +36 -1
package/changelog.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-11-11 - 1.1.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- pin the hub's TLS public key with the client option `hubKeySha256` (client)
|
|
8
|
+
- The pin is the RFC 7469 `pin-sha256` of the hub key (padded standard base64, 44 characters) and requires an `https:` hubUrl; the constructor rejects hex, every other form and a non-`https:` hub URL with a `TypeError`.
|
|
9
|
+
- A pinned client sends every request over its started TypedSocket, opened with TypedSocket's `tls: { publicKeySha256 }`, and never over HTTP: requests before `start()` or after `stop()` reject, and a hub presenting another key rejects `start()` with `TypedSocketTlsPinError` before any request byte or credential is written.
|
|
10
|
+
- Clients without `hubKeySha256` are unchanged.
|
|
11
|
+
|
|
12
|
+
### Maintenance
|
|
13
|
+
|
|
14
|
+
- Move to TypedSocket ^10.1.0 and TypedRequest ^9.2.0, one TypedRequest copy in the production dependency graph, and test against SmartServe 10.0.1. The socket wire major stays 9, so started clients keep working with TypedSocket 9 hubs. TypedSocket 10 no longer supports Deno, and an HTTP answer outside 2xx now rejects with TypedRequest's `TypedRequestHttpError` (still an `Error` with the message `HTTP <status>: <statusText>`).
|
|
15
|
+
- Update release tooling: replace the deprecated @git.zone/tsbuild, @git.zone/tsdoc, @git.zone/tsrun and @git.zone/tstest with @git.zone/tsrepo 2.0.0 (`tsrepo build`, `tsrepo test`, `tsrepo docs`; tests import `@git.zone/tsrepo/tapbundle`), pnpm 12.17.0 and @types/node 26.6.6.
|
|
16
|
+
|
|
3
17
|
## 2026-10-12 - 1.0.1
|
|
4
18
|
|
|
5
19
|
### Fixes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@smarthome.exchange/api',
|
|
6
|
-
version: '1.0
|
|
6
|
+
version: '1.1.0',
|
|
7
7
|
description: 'Typed API client for smarthome.exchange hubs.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLCtDQUErQztDQUM3RCxDQUFBIn0=
|
|
@@ -4,6 +4,13 @@ export interface IShxApiClientOptions {
|
|
|
4
4
|
homeId: string;
|
|
5
5
|
authorizationHeaderProvider: TShxAuthorizationHeaderProvider;
|
|
6
6
|
socketConnectionPreparationTimeoutMs?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Pins the hub's TLS public key (Node.js): the RFC 7469 `pin-sha256` of the hub certificate's
|
|
9
|
+
* public key, the SHA-256 of its DER SubjectPublicKeyInfo as padded standard base64
|
|
10
|
+
* (44 characters). Requires an `https:` hubUrl. A pinned client sends every request over its
|
|
11
|
+
* started TypedSocket, which connects only to a hub presenting this key, and never over HTTP.
|
|
12
|
+
*/
|
|
13
|
+
hubKeySha256?: string;
|
|
7
14
|
}
|
|
8
15
|
export interface IShxAuthorizationContext {
|
|
9
16
|
readonly homeId: string;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
const maxLifecycleOperationCount = 64;
|
|
3
|
+
/**
|
|
4
|
+
* A SHA-256 digest (32 bytes) as canonical padded standard base64: 43 characters and `=`, where
|
|
5
|
+
* the last character before the padding carries four data bits and two zero bits.
|
|
6
|
+
*/
|
|
7
|
+
const hubKeySha256Pattern = /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/;
|
|
3
8
|
export class SmarthomeExchangeApiClient {
|
|
4
9
|
#homeId;
|
|
5
10
|
#httpEndpoint;
|
|
6
11
|
#hubUrl;
|
|
7
12
|
#socketConnectionPreparationTimeoutMs;
|
|
13
|
+
#hubKeySha256;
|
|
8
14
|
#authorizationHeaderProvider;
|
|
9
15
|
lifecycleTail = Promise.resolve();
|
|
10
16
|
lifecycleOperationCount = 0;
|
|
@@ -16,7 +22,7 @@ export class SmarthomeExchangeApiClient {
|
|
|
16
22
|
#typedsocketClient;
|
|
17
23
|
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
18
24
|
constructor(optionsArg) {
|
|
19
|
-
this.assertKnownProperties(optionsArg, ['hubUrl', 'homeId', 'authorizationHeaderProvider', 'socketConnectionPreparationTimeoutMs'], 'Client options');
|
|
25
|
+
this.assertKnownProperties(optionsArg, ['hubUrl', 'homeId', 'authorizationHeaderProvider', 'socketConnectionPreparationTimeoutMs', 'hubKeySha256'], 'Client options');
|
|
20
26
|
if (!optionsArg || typeof optionsArg.homeId !== 'string'
|
|
21
27
|
|| optionsArg.homeId.length < 1 || optionsArg.homeId.length > 200
|
|
22
28
|
|| optionsArg.homeId.trim() !== optionsArg.homeId
|
|
@@ -35,6 +41,17 @@ export class SmarthomeExchangeApiClient {
|
|
|
35
41
|
|| hubUrl.username || hubUrl.password || hubUrl.search || hubUrl.hash) {
|
|
36
42
|
throw new TypeError('hubUrl must be an HTTP or HTTPS URL without credentials, query, or fragment.');
|
|
37
43
|
}
|
|
44
|
+
const hubKeySha256 = optionsArg.hubKeySha256;
|
|
45
|
+
if (hubKeySha256 !== undefined) {
|
|
46
|
+
if (typeof hubKeySha256 !== 'string' || !hubKeySha256Pattern.test(hubKeySha256)) {
|
|
47
|
+
throw new TypeError('hubKeySha256 must be the RFC 7469 pin-sha256 of the hub public key: the SHA-256 of its DER '
|
|
48
|
+
+ 'SubjectPublicKeyInfo as padded standard base64, 44 characters. Hex is not accepted.');
|
|
49
|
+
}
|
|
50
|
+
if (hubUrl.protocol !== 'https:') {
|
|
51
|
+
throw new TypeError('hubKeySha256 requires an https: hubUrl.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
this.#hubKeySha256 = hubKeySha256;
|
|
38
55
|
const preparationTimeoutMs = optionsArg.socketConnectionPreparationTimeoutMs;
|
|
39
56
|
if (preparationTimeoutMs !== undefined && (!Number.isInteger(preparationTimeoutMs)
|
|
40
57
|
|| preparationTimeoutMs < 1
|
|
@@ -79,6 +96,9 @@ export class SmarthomeExchangeApiClient {
|
|
|
79
96
|
maxRetries: 0,
|
|
80
97
|
});
|
|
81
98
|
}
|
|
99
|
+
if (this.#hubKeySha256 !== undefined) {
|
|
100
|
+
throw new Error('This client is pinned to a hub key and sends requests only over its started TypedSocket; await start() first.');
|
|
101
|
+
}
|
|
82
102
|
const authorization = await this.getAuthorization(Object.freeze({
|
|
83
103
|
homeId: this.#homeId,
|
|
84
104
|
endpoint: this.#httpEndpoint,
|
|
@@ -233,6 +253,7 @@ export class SmarthomeExchangeApiClient {
|
|
|
233
253
|
autoReconnect: false,
|
|
234
254
|
prepareConnection: (contextArg) => this.prepareSocketConnection(contextArg),
|
|
235
255
|
connectionPreparationTimeoutMs: this.#socketConnectionPreparationTimeoutMs,
|
|
256
|
+
tls: this.#hubKeySha256 === undefined ? undefined : { publicKeySha256: this.#hubKeySha256 },
|
|
236
257
|
});
|
|
237
258
|
if (this.stopIntentGeneration !== startStopIntentGeneration) {
|
|
238
259
|
this.socketPendingStop = createdSocket;
|
|
@@ -429,4 +450,4 @@ export class SmarthomeExchangeApiClient {
|
|
|
429
450
|
return this.fire('submitApproval', this.prepareRequest(requestArg, ['approvalId', 'expectedActionDigest', 'decision']), optionsArg);
|
|
430
451
|
}
|
|
431
452
|
}
|
|
432
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbWFydGhvbWVleGNoYW5nZWFwaWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuc21hcnRob21lZXhjaGFuZ2VhcGljbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUF3RXhDLE1BQU0sMEJBQTBCLEdBQUcsRUFBRSxDQUFDO0FBRXRDLE1BQU0sT0FBTywwQkFBMEI7SUFDNUIsT0FBTyxDQUFTO0lBQ2hCLGFBQWEsQ0FBUztJQUN0QixPQUFPLENBQVM7SUFDaEIscUNBQXFDLENBQVU7SUFDL0MsNEJBQTRCLENBQWtDO0lBQy9ELGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbEMsdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO0lBQzVCLHdCQUF3QixDQUc5QjtJQUNNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztJQUN6QiwyQkFBMkIsQ0FBbUI7SUFDOUMsaUJBQWlCLENBQW1DO0lBQ3BELGtCQUFrQixHQUFHLEtBQUssQ0FBQztJQUNuQyxrQkFBa0IsQ0FBbUM7SUFDckMsV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUVyRSxZQUFZLFVBQWdDO1FBQzFDLElBQUksQ0FBQyxxQkFBcUIsQ0FDeEIsVUFBVSxFQUFFLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSw2QkFBNkIsRUFBRSxzQ0FBc0MsQ0FBQyxFQUFFLGdCQUFnQixDQUMxSCxDQUFDO1FBQ0YsSUFBSSxDQUFDLFVBQVUsSUFBSSxPQUFPLFVBQVUsQ0FBQyxNQUFNLEtBQUssUUFBUTtlQUNuRCxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRztlQUM5RCxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLFVBQVUs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
|
|
453
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zbWFydGhvbWVleGNoYW5nZWFwaWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuc21hcnRob21lZXhjaGFuZ2VhcGljbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUErRXhDLE1BQU0sMEJBQTBCLEdBQUcsRUFBRSxDQUFDO0FBRXRDOzs7R0FHRztBQUNILE1BQU0sbUJBQW1CLEdBQUcsd0NBQXdDLENBQUM7QUFFckUsTUFBTSxPQUFPLDBCQUEwQjtJQUM1QixPQUFPLENBQVM7SUFDaEIsYUFBYSxDQUFTO0lBQ3RCLE9BQU8sQ0FBUztJQUNoQixxQ0FBcUMsQ0FBVTtJQUMvQyxhQUFhLENBQVU7SUFDdkIsNEJBQTRCLENBQWtDO0lBQy9ELGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbEMsdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO0lBQzVCLHdCQUF3QixDQUc5QjtJQUNNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztJQUN6QiwyQkFBMkIsQ0FBbUI7SUFDOUMsaUJBQWlCLENBQW1DO0lBQ3BELGtCQUFrQixHQUFHLEtBQUssQ0FBQztJQUNuQyxrQkFBa0IsQ0FBbUM7SUFDckMsV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUVyRSxZQUFZLFVBQWdDO1FBQzFDLElBQUksQ0FBQyxxQkFBcUIsQ0FDeEIsVUFBVSxFQUNWLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSw2QkFBNkIsRUFBRSxzQ0FBc0MsRUFBRSxjQUFjLENBQUMsRUFDM0csZ0JBQWdCLENBQ2pCLENBQUM7UUFDRixJQUFJLENBQUMsVUFBVSxJQUFJLE9BQU8sVUFBVSxDQUFDLE1BQU0sS0FBSyxRQUFRO2VBQ25ELFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxVQUFVLENB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smarthome.exchange/api",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Typed API client for smarthome.exchange hubs.",
|
|
6
6
|
"exports": {
|
|
@@ -10,19 +10,17 @@
|
|
|
10
10
|
"author": "Task Venture Capital GmbH",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@api.global/typedrequest": "9.
|
|
13
|
+
"@api.global/typedrequest": "^9.2.0",
|
|
14
14
|
"@api.global/typedrequest-interfaces": "^7.0.0",
|
|
15
|
-
"@api.global/typedsocket": "
|
|
15
|
+
"@api.global/typedsocket": "^10.1.0",
|
|
16
16
|
"@push.rocks/smartpromise": "^4.2.4",
|
|
17
17
|
"@smarthome.exchange/interfaces": "2.1.0"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@git.zone/
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"@push.rocks/smartserve": "9.0.0",
|
|
25
|
-
"@types/node": "^26.6.3"
|
|
20
|
+
"@git.zone/tsrepo": "^2.0.0",
|
|
21
|
+
"@push.rocks/smartcrypto": "^3.3.0",
|
|
22
|
+
"@push.rocks/smartserve": "10.0.1",
|
|
23
|
+
"@types/node": "^26.6.6"
|
|
26
24
|
},
|
|
27
25
|
"files": [
|
|
28
26
|
"ts/**/*",
|
|
@@ -37,8 +35,8 @@
|
|
|
37
35
|
"last 1 chrome versions"
|
|
38
36
|
],
|
|
39
37
|
"scripts": {
|
|
40
|
-
"test": "
|
|
41
|
-
"build": "
|
|
42
|
-
"buildDocs": "
|
|
38
|
+
"test": "tsrepo test test/ --verbose --logfile --timeout 60",
|
|
39
|
+
"build": "tsrepo build tsfolders --allowimplicitany",
|
|
40
|
+
"buildDocs": "tsrepo docs"
|
|
43
41
|
}
|
|
44
42
|
}
|
package/readme.md
CHANGED
|
@@ -45,7 +45,7 @@ The constructor captures the home and provider from plain own data properties. C
|
|
|
45
45
|
|
|
46
46
|
## Transport and Cancellation
|
|
47
47
|
|
|
48
|
-
HTTP calls use published TypedRequest 9.
|
|
48
|
+
HTTP calls use published TypedRequest 9.2 and `${hubUrl}/typedrequest`. An answer outside 2xx rejects with TypedRequest's exported `TypedRequestHttpError`, which carries the status and the parsed response body. Credentials stay in HTTP headers outside RPC JSON. Header-bearing calls bypass the shared response cache, including when `useCache: true`, and reject redirects before credentials can be forwarded. Configure the final hub URL without embedded credentials, query parameters, or a fragment. HTTPS and server-managed browser CORS remain deployment responsibilities.
|
|
49
49
|
|
|
50
50
|
Every method accepts optional request options:
|
|
51
51
|
|
|
@@ -74,16 +74,46 @@ try {
|
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
Node `start()` consumes published TypedSocket
|
|
77
|
+
Node `start()` consumes published TypedSocket 10 and obtains an Authorization header before the WebSocket upgrade, including its transport compatibility handshake. Credentials stay outside URLs and RPC frames; upgrade redirects are disabled. Socket calls carry the captured home context, and the hub must enforce current subject grants on every message. The package-major handshake establishes compatibility only.
|
|
78
78
|
|
|
79
|
-
While started, methods use that authenticated socket and its bound subject; the header provider is not reevaluated for individual socket messages. To rotate credentials or change subjects, stop and explicitly start a new connection. Automatic reconnects are disabled, so denied upgrade admission settles immediately without repeatedly presenting stale credentials.
|
|
79
|
+
While started, methods use that authenticated socket and its bound subject; the header provider is not reevaluated for individual socket messages. To rotate credentials or change subjects, stop and explicitly start a new connection. Automatic reconnects are disabled, so denied upgrade admission settles immediately without repeatedly presenting stale credentials. Without a hub key pin, calls before startup and after successful stop use authenticated HTTP; a pinned client rejects them (see [Hub Key Pinning](#hub-key-pinning)). An in-flight socket request that fails or is stopped is never resent over HTTP. In socket mode, `timeoutMs` configures both the TypedRequest deadline and TypedSocket’s per-call timeout, with the owning maximum of `300000` milliseconds; omitting it retains the socket’s `30000`-millisecond default. Larger HTTP deadlines are unavailable in socket mode.
|
|
80
80
|
|
|
81
|
-
Browser
|
|
81
|
+
Browser WebSocket APIs cannot supply Authorization upgrade headers. Their `start()` fails with the owning `TypedSocketConnectionPreparationError`, code `callback-rejected`, whose `cause` is a `TypedSocketConnectionPreparationError` with code `unsupported-headers`. The capability check runs before obtaining credentials or opening a socket. Use the authenticated HTTP methods and snapshot polling in browsers. TypedSocket 10 does not support Deno, so socket mode is not supported there. The hub has no published application cookie-ticket issuer/consumer contract; this client creates no ticket endpoint and sends no authentication RPC. Native Fetch CORS and credential policy remain server/application responsibilities.
|
|
82
82
|
|
|
83
83
|
TypedSocket requires TLS for remote Node sockets; insecure `ws:` is permitted only on loopback. Configure an HTTPS hub URL for remote socket use. Credential preparation has the owning ten-second default/maximum deadline; set constructor `socketConnectionPreparationTimeoutMs` to a positive integer no greater than `10000` to reduce it. Its signal aborts on timeout, cancellation, disconnect, and stop. A noncooperative provider cannot hold socket stop open or open a connection with a late credential result.
|
|
84
84
|
|
|
85
85
|
Concurrent identical `start()`/`stop()` calls coalesce. Mixed lifecycle calls run in order, with at most 64 active and queued operations. `stop()` supersedes earlier queued starts and cancels an in-flight startup using TypedSocket's exported public startup-aborted error. A late-created socket remains owned until its exact cleanup succeeds. A cleanup failure retains that socket for a later `stop()` and blocks new startup; failed startup is retryable through a later explicit `start()`.
|
|
86
86
|
|
|
87
|
+
## Hub Key Pinning
|
|
88
|
+
|
|
89
|
+
A hub that serves its local listener over TLS with a self-signed certificate is trusted by its key instead of by a certificate authority. Pass the pin of the hub key as `hubKeySha256` with an `https:` hub URL:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const client = new SmarthomeExchangeApiClient({
|
|
93
|
+
hubUrl: 'https://192.168.1.10:8443',
|
|
94
|
+
homeId: 'home:primary',
|
|
95
|
+
hubKeySha256: 'hB3V5ryySb8VT4CKjozUKRHBW6gZuNoQWXWJBPSamxY=',
|
|
96
|
+
authorizationHeaderProvider: async ({ abortSignal }) => {
|
|
97
|
+
const accessToken = await yourCredentialProvider.getAccessToken({ abortSignal });
|
|
98
|
+
return `Bearer ${accessToken}`;
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await client.start();
|
|
103
|
+
try {
|
|
104
|
+
const snapshotResponse = await client.getHomeSnapshot();
|
|
105
|
+
console.log(snapshotResponse.snapshot.home.name);
|
|
106
|
+
} finally {
|
|
107
|
+
await client.stop();
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The pin is the RFC 7469 `pin-sha256` of the hub certificate's public key: the SHA-256 of its DER `SubjectPublicKeyInfo` as padded standard base64, 44 characters. The constructor rejects hex and every other form, and a pin with a hub URL that is not `https:`, with a `TypeError`. Compute the pin with `openssl x509 -in hub.pem -noout -pubkey | openssl pkey -pubin -outform DER | openssl dgst -sha256 -binary | base64`, or with `computePublicKeyPinSha256(certificatePem)` from `@push.rocks/smartcrypto`. A hub that issues every certificate for the same key keeps its pin across renewals.
|
|
112
|
+
|
|
113
|
+
A pinned client sends every request over its started TypedSocket, opened with TypedSocket's Node.js option `tls: { publicKeySha256 }`. Each connection completes the TLS handshake and compares the hub's public key with the pin before it writes the upgrade request and its Authorization header; the pin replaces certificate authority and hostname verification. A hub presenting another key rejects `start()` with TypedSocket's exported `TypedSocketTlsPinError` (`code` `public-key-mismatch`, or `certificate-missing`), whose message carries no header or credential. TypedSocket prepares the connection's header before it connects, so the credential provider has been asked once by then, but the header is never written.
|
|
114
|
+
|
|
115
|
+
A pinned client has no HTTP path. A request before `start()` resolves, after `stop()`, or after a failed start rejects with an `Error` that names `start()`, and a snapshot watcher reports that error to `onError`. Pinning needs Node.js 20.16 or a later 20.x release, or Node.js 22.3 or later; browsers refuse it, so a pinned client cannot start there. A client without `hubKeySha256` behaves as before.
|
|
116
|
+
|
|
87
117
|
|
|
88
118
|
## Client Methods
|
|
89
119
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -5,6 +5,13 @@ export interface IShxApiClientOptions {
|
|
|
5
5
|
homeId: string;
|
|
6
6
|
authorizationHeaderProvider: TShxAuthorizationHeaderProvider;
|
|
7
7
|
socketConnectionPreparationTimeoutMs?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Pins the hub's TLS public key (Node.js): the RFC 7469 `pin-sha256` of the hub certificate's
|
|
10
|
+
* public key, the SHA-256 of its DER SubjectPublicKeyInfo as padded standard base64
|
|
11
|
+
* (44 characters). Requires an `https:` hubUrl. A pinned client sends every request over its
|
|
12
|
+
* started TypedSocket, which connects only to a hub presenting this key, and never over HTTP.
|
|
13
|
+
*/
|
|
14
|
+
hubKeySha256?: string;
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
export interface IShxAuthorizationContext {
|
|
@@ -72,11 +79,18 @@ export type THomeSnapshotWatchStop = () => Promise<void>;
|
|
|
72
79
|
|
|
73
80
|
const maxLifecycleOperationCount = 64;
|
|
74
81
|
|
|
82
|
+
/**
|
|
83
|
+
* A SHA-256 digest (32 bytes) as canonical padded standard base64: 43 characters and `=`, where
|
|
84
|
+
* the last character before the padding carries four data bits and two zero bits.
|
|
85
|
+
*/
|
|
86
|
+
const hubKeySha256Pattern = /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/;
|
|
87
|
+
|
|
75
88
|
export class SmarthomeExchangeApiClient {
|
|
76
89
|
readonly #homeId: string;
|
|
77
90
|
readonly #httpEndpoint: string;
|
|
78
91
|
readonly #hubUrl: string;
|
|
79
92
|
readonly #socketConnectionPreparationTimeoutMs?: number;
|
|
93
|
+
readonly #hubKeySha256?: string;
|
|
80
94
|
readonly #authorizationHeaderProvider: TShxAuthorizationHeaderProvider;
|
|
81
95
|
private lifecycleTail = Promise.resolve();
|
|
82
96
|
private lifecycleOperationCount = 0;
|
|
@@ -93,7 +107,9 @@ export class SmarthomeExchangeApiClient {
|
|
|
93
107
|
|
|
94
108
|
constructor(optionsArg: IShxApiClientOptions) {
|
|
95
109
|
this.assertKnownProperties(
|
|
96
|
-
optionsArg,
|
|
110
|
+
optionsArg,
|
|
111
|
+
['hubUrl', 'homeId', 'authorizationHeaderProvider', 'socketConnectionPreparationTimeoutMs', 'hubKeySha256'],
|
|
112
|
+
'Client options'
|
|
97
113
|
);
|
|
98
114
|
if (!optionsArg || typeof optionsArg.homeId !== 'string'
|
|
99
115
|
|| optionsArg.homeId.length < 1 || optionsArg.homeId.length > 200
|
|
@@ -112,6 +128,19 @@ export class SmarthomeExchangeApiClient {
|
|
|
112
128
|
|| hubUrl.username || hubUrl.password || hubUrl.search || hubUrl.hash) {
|
|
113
129
|
throw new TypeError('hubUrl must be an HTTP or HTTPS URL without credentials, query, or fragment.');
|
|
114
130
|
}
|
|
131
|
+
const hubKeySha256 = optionsArg.hubKeySha256;
|
|
132
|
+
if (hubKeySha256 !== undefined) {
|
|
133
|
+
if (typeof hubKeySha256 !== 'string' || !hubKeySha256Pattern.test(hubKeySha256)) {
|
|
134
|
+
throw new TypeError(
|
|
135
|
+
'hubKeySha256 must be the RFC 7469 pin-sha256 of the hub public key: the SHA-256 of its DER '
|
|
136
|
+
+ 'SubjectPublicKeyInfo as padded standard base64, 44 characters. Hex is not accepted.'
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (hubUrl.protocol !== 'https:') {
|
|
140
|
+
throw new TypeError('hubKeySha256 requires an https: hubUrl.');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
this.#hubKeySha256 = hubKeySha256;
|
|
115
144
|
const preparationTimeoutMs = optionsArg.socketConnectionPreparationTimeoutMs;
|
|
116
145
|
if (preparationTimeoutMs !== undefined && (!Number.isInteger(preparationTimeoutMs)
|
|
117
146
|
|| preparationTimeoutMs < 1
|
|
@@ -167,6 +196,11 @@ export class SmarthomeExchangeApiClient {
|
|
|
167
196
|
maxRetries: 0,
|
|
168
197
|
});
|
|
169
198
|
}
|
|
199
|
+
if (this.#hubKeySha256 !== undefined) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
'This client is pinned to a hub key and sends requests only over its started TypedSocket; await start() first.'
|
|
202
|
+
);
|
|
203
|
+
}
|
|
170
204
|
const authorization = await this.getAuthorization(Object.freeze({
|
|
171
205
|
homeId: this.#homeId,
|
|
172
206
|
endpoint: this.#httpEndpoint,
|
|
@@ -337,6 +371,7 @@ export class SmarthomeExchangeApiClient {
|
|
|
337
371
|
autoReconnect: false,
|
|
338
372
|
prepareConnection: (contextArg) => this.prepareSocketConnection(contextArg),
|
|
339
373
|
connectionPreparationTimeoutMs: this.#socketConnectionPreparationTimeoutMs,
|
|
374
|
+
tls: this.#hubKeySha256 === undefined ? undefined : { publicKeySha256: this.#hubKeySha256 },
|
|
340
375
|
}
|
|
341
376
|
);
|
|
342
377
|
if (this.stopIntentGeneration !== startStopIntentGeneration) {
|