@zhin.js/host-http 1.0.10 → 1.0.12
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/lib/console-events.d.ts +18 -4
- package/lib/console-events.js +121 -9
- package/lib/console-rest-pages.d.ts +15 -5
- package/lib/console-rest-pages.js +162 -16
- package/lib/console-rpc-extended.d.ts +92 -2
- package/lib/console-rpc-extended.js +243 -16
- package/lib/console-rpc.d.ts +10 -0
- package/lib/console-rpc.js +48 -0
- package/lib/http-host.d.ts +2 -2
- package/lib/http-host.js +4 -3
- package/lib/index.d.ts +2 -2
- package/lib/token-registry.d.ts +7 -0
- package/lib/token-registry.js +29 -8
- package/package.json +3 -3
- package/src/console-events.ts +170 -12
- package/src/console-rest-pages.ts +181 -20
- package/src/console-rpc-extended.ts +332 -18
- package/src/console-rpc.ts +55 -0
- package/src/http-host.ts +7 -4
- package/src/index.ts +3 -0
- package/src/token-registry.ts +36 -8
package/src/token-registry.ts
CHANGED
|
@@ -6,27 +6,55 @@ export type AuthScope = 'full' | 'demo';
|
|
|
6
6
|
export type ScopedTokenConfig = {
|
|
7
7
|
readonly token: string;
|
|
8
8
|
readonly scope: AuthScope;
|
|
9
|
+
/** Root-configured subject binding; never accepted from an HTTP payload. */
|
|
10
|
+
readonly principalId?: string;
|
|
9
11
|
};
|
|
10
12
|
|
|
13
|
+
export interface AuthenticatedTokenPrincipal {
|
|
14
|
+
readonly principalId: string;
|
|
15
|
+
readonly scope: AuthScope;
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
export type TokenRegistryConfig = {
|
|
12
19
|
readonly primaryToken?: string;
|
|
13
20
|
readonly scopedTokens?: readonly ScopedTokenConfig[];
|
|
14
21
|
};
|
|
15
22
|
|
|
16
23
|
export class TokenRegistry {
|
|
17
|
-
readonly #entries = new Map<string, AuthScope
|
|
24
|
+
readonly #entries = new Map<string, Readonly<{ scope: AuthScope; principalId?: string }>>();
|
|
18
25
|
|
|
19
26
|
constructor(config: TokenRegistryConfig = {}) {
|
|
20
|
-
if (config.primaryToken) this.#entries.set(config.primaryToken, 'full');
|
|
21
|
-
for (const { token, scope } of config.scopedTokens ?? []) {
|
|
22
|
-
if (token)
|
|
27
|
+
if (config.primaryToken) this.#entries.set(config.primaryToken, Object.freeze({ scope: 'full' }));
|
|
28
|
+
for (const { token, scope, principalId } of config.scopedTokens ?? []) {
|
|
29
|
+
if (!token) continue;
|
|
30
|
+
if (principalId !== undefined && (!principalId.trim() || principalId !== principalId.trim())) {
|
|
31
|
+
throw new Error('HTTP token principalId is invalid');
|
|
32
|
+
}
|
|
33
|
+
const candidate = Object.freeze({ scope, ...(principalId === undefined ? {} : { principalId }) });
|
|
34
|
+
const existing = this.#entries.get(token);
|
|
35
|
+
if (existing && (existing.scope !== candidate.scope || existing.principalId !== candidate.principalId)) {
|
|
36
|
+
throw new Error('HTTP token has conflicting authority bindings');
|
|
37
|
+
}
|
|
38
|
+
this.#entries.set(token, candidate);
|
|
23
39
|
}
|
|
24
40
|
}
|
|
25
41
|
|
|
26
42
|
resolve(token: string): AuthScope | null {
|
|
27
43
|
if (!token) return null;
|
|
28
|
-
for (const [known,
|
|
29
|
-
if (timingSafeEqualString(known, token)) return scope;
|
|
44
|
+
for (const [known, binding] of this.#entries) {
|
|
45
|
+
if (timingSafeEqualString(known, token)) return binding.scope;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
resolvePrincipal(token: string): AuthenticatedTokenPrincipal | null {
|
|
51
|
+
if (!token) return null;
|
|
52
|
+
for (const [known, binding] of this.#entries) {
|
|
53
|
+
if (timingSafeEqualString(known, token)) {
|
|
54
|
+
return binding.principalId
|
|
55
|
+
? Object.freeze({ principalId: binding.principalId, scope: binding.scope })
|
|
56
|
+
: null;
|
|
57
|
+
}
|
|
30
58
|
}
|
|
31
59
|
return null;
|
|
32
60
|
}
|
|
@@ -36,8 +64,8 @@ export class TokenRegistry {
|
|
|
36
64
|
}
|
|
37
65
|
|
|
38
66
|
primaryTokenPrefixForLog(): string {
|
|
39
|
-
for (const [tok,
|
|
40
|
-
if (scope === 'full') return tok.slice(0, 6);
|
|
67
|
+
for (const [tok, binding] of this.#entries) {
|
|
68
|
+
if (binding.scope === 'full') return tok.slice(0, 6);
|
|
41
69
|
}
|
|
42
70
|
const first = this.#entries.keys().next().value;
|
|
43
71
|
return first ? first.slice(0, 6) : '';
|