402-mcp 4.2.1 → 4.3.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 +60 -22
- package/build/config.d.ts +12 -1
- package/build/config.js +53 -12
- package/build/config.js.map +1 -1
- package/build/fetch/resilient-fetch.d.ts +7 -2
- package/build/fetch/resilient-fetch.js +32 -10
- package/build/fetch/resilient-fetch.js.map +1 -1
- package/build/fetch/socks-proxy.d.ts +25 -0
- package/build/fetch/socks-proxy.js +41 -0
- package/build/fetch/socks-proxy.js.map +1 -0
- package/build/fetch/ssrf-guard.d.ts +10 -0
- package/build/fetch/ssrf-guard.js +17 -1
- package/build/fetch/ssrf-guard.js.map +1 -1
- package/build/fetch/transport.d.ts +1 -0
- package/build/fetch/transport.js +37 -14
- package/build/fetch/transport.js.map +1 -1
- package/build/http-security.d.ts +13 -0
- package/build/http-security.js +38 -0
- package/build/http-security.js.map +1 -0
- package/build/index.js +186 -120
- package/build/index.js.map +1 -1
- package/build/l402/bolt11.js +3 -2
- package/build/l402/bolt11.js.map +1 -1
- package/build/spend-tracker.d.ts +31 -4
- package/build/spend-tracker.js +102 -17
- package/build/spend-tracker.js.map +1 -1
- package/build/store/cashu-tokens.d.ts +19 -0
- package/build/store/cashu-tokens.js +32 -0
- package/build/store/cashu-tokens.js.map +1 -1
- package/build/store/credentials.d.ts +5 -0
- package/build/store/credentials.js +1 -0
- package/build/store/credentials.js.map +1 -1
- package/build/store/pending-payments.d.ts +36 -0
- package/build/store/pending-payments.js +88 -0
- package/build/store/pending-payments.js.map +1 -0
- package/build/tools/buy-credits.d.ts +9 -0
- package/build/tools/buy-credits.js +40 -3
- package/build/tools/buy-credits.js.map +1 -1
- package/build/tools/config.d.ts +5 -0
- package/build/tools/config.js.map +1 -1
- package/build/tools/confirm.d.ts +12 -0
- package/build/tools/confirm.js +27 -0
- package/build/tools/confirm.js.map +1 -0
- package/build/tools/fetch-preview.js +9 -3
- package/build/tools/fetch-preview.js.map +1 -1
- package/build/tools/fetch.d.ts +7 -1
- package/build/tools/fetch.js +281 -140
- package/build/tools/fetch.js.map +1 -1
- package/build/tools/nostr-subscribe.js.map +1 -1
- package/build/tools/pay.d.ts +9 -0
- package/build/tools/pay.js +65 -8
- package/build/tools/pay.js.map +1 -1
- package/build/tools/reconcile.d.ts +33 -0
- package/build/tools/reconcile.js +111 -0
- package/build/tools/reconcile.js.map +1 -0
- package/build/tools/redeem-cashu.js +1 -1
- package/build/tools/redeem-cashu.js.map +1 -1
- package/build/tools/register-widgets.js +5 -5
- package/build/tools/register-widgets.js.map +1 -1
- package/build/tools/search.js +17 -3
- package/build/tools/search.js.map +1 -1
- package/build/tools/untrusted.d.ts +3 -0
- package/build/tools/untrusted.js +18 -0
- package/build/tools/untrusted.js.map +1 -0
- package/build/wallet/cashu.js +101 -21
- package/build/wallet/cashu.js.map +1 -1
- package/build/wallet/lnurlcash.js +25 -7
- package/build/wallet/lnurlcash.js.map +1 -1
- package/build/wallet/nwc.js +51 -3
- package/build/wallet/nwc.js.map +1 -1
- package/build/wallet/types.d.ts +17 -0
- package/build/x402/parse.d.ts +15 -3
- package/build/x402/parse.js +23 -9
- package/build/x402/parse.js.map +1 -1
- package/build/x402/payment.js +11 -6
- package/build/x402/payment.js.map +1 -1
- package/llms-full.txt +73 -34
- package/llms.txt +52 -24
- package/package.json +6 -5
- package/src/widgets/dist/payment-confirmation.html +28 -28
- package/src/widgets/dist/service-directory.html +39 -30
- package/src/widgets/dist/wallet-dashboard.html +28 -28
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socks-proxy.js","sourceRoot":"","sources":["../../src/fetch/socks-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAA;AAgB/D;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAW;IAC1D,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,kFAAkF,CAAC,CAAA;IAC5G,CAAC;IACD,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oDAAoD,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAA;IAC9F,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,8DAA8D,CAAC,CAAA;IACxF,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,6CAA6C,CAAC,CAAA;IACvE,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IAC5F,OAAO,YAAY,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;AACtC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,UAAU,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACjD,OAAO,CAAC,CAAC,KAAmB,EAAE,IAAkB,EAAE,EAAE,CAClD,WAAW,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAuC,CAAC,CAA4B,CAAA;AAChH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,SAAS,CAAC,KAA6B,EAAE,QAAgB;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IACxB,OAAO,KAAK,CAAC,KAAK,KAAK,KAAK,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC9F,CAAC"}
|
|
@@ -5,6 +5,12 @@ export interface ValidateUrlOptions {
|
|
|
5
5
|
resolveHns?: (hostname: string) => Promise<ResolvedAddress>;
|
|
6
6
|
/** Whether a Tor SOCKS proxy is available — required for .onion URLs */
|
|
7
7
|
hasTorProxy?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Every request goes through a SOCKS proxy that resolves names itself.
|
|
10
|
+
* No local DNS lookup is made (it would leak the host name around the
|
|
11
|
+
* proxy); IP literals and local-only names are still refused.
|
|
12
|
+
*/
|
|
13
|
+
remoteDns?: boolean;
|
|
8
14
|
}
|
|
9
15
|
/**
|
|
10
16
|
* Validate a URL against SSRF rules and return the resolved IP address.
|
|
@@ -23,6 +29,10 @@ export interface ValidateUrlOptions {
|
|
|
23
29
|
* - If `options.hasTorProxy` is true, returns `undefined` (route via SOCKS proxy; skip SSRF).
|
|
24
30
|
* - Otherwise throws `TransportUnavailableError`.
|
|
25
31
|
*
|
|
32
|
+
* With `options.remoteDns` (all traffic via SOCKS), nothing is resolved here:
|
|
33
|
+
* IP literals are checked against the blocked ranges, local-only names are
|
|
34
|
+
* refused, and `undefined` is returned so nothing is pinned.
|
|
35
|
+
*
|
|
26
36
|
* HNS fallback:
|
|
27
37
|
* - If standard DNS fails with NXDOMAIN (ENOTFOUND) and `options.resolveHns` is provided,
|
|
28
38
|
* it is tried as a fallback. The resolved IP still goes through blocked-range checks.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { promises as dns } from 'node:dns';
|
|
2
|
+
import { isIP } from 'node:net';
|
|
2
3
|
import { SsrfError, TransportUnavailableError } from './errors.js';
|
|
3
4
|
function isBlockedIp(address, family) {
|
|
4
5
|
if (family === 6) {
|
|
@@ -89,6 +90,8 @@ function assertNotBlocked(address, family, url) {
|
|
|
89
90
|
throw new SsrfError(reason, url);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
93
|
+
/** Names that only ever mean this machine or its local network. */
|
|
94
|
+
const LOCAL_NAME_RE = /(^|\.)(localhost|local|internal|lan|home\.arpa)$/i;
|
|
92
95
|
/**
|
|
93
96
|
* Validate a URL against SSRF rules and return the resolved IP address.
|
|
94
97
|
*
|
|
@@ -106,6 +109,10 @@ function assertNotBlocked(address, family, url) {
|
|
|
106
109
|
* - If `options.hasTorProxy` is true, returns `undefined` (route via SOCKS proxy; skip SSRF).
|
|
107
110
|
* - Otherwise throws `TransportUnavailableError`.
|
|
108
111
|
*
|
|
112
|
+
* With `options.remoteDns` (all traffic via SOCKS), nothing is resolved here:
|
|
113
|
+
* IP literals are checked against the blocked ranges, local-only names are
|
|
114
|
+
* refused, and `undefined` is returned so nothing is pinned.
|
|
115
|
+
*
|
|
109
116
|
* HNS fallback:
|
|
110
117
|
* - If standard DNS fails with NXDOMAIN (ENOTFOUND) and `options.resolveHns` is provided,
|
|
111
118
|
* it is tried as a fallback. The resolved IP still goes through blocked-range checks.
|
|
@@ -129,11 +136,20 @@ export async function validateUrl(url, allowPrivate = false, options = {}) {
|
|
|
129
136
|
// so the guard is self-contained rather than relying on upstream normalisation.
|
|
130
137
|
const hostname = parsed.hostname.replace(/^\[/, '').replace(/\]$/, '').split('%')[0];
|
|
131
138
|
// .onion: route via Tor SOCKS proxy — never attempt DNS resolution
|
|
132
|
-
|
|
139
|
+
const bareHost = hostname.replace(/\.$/, '');
|
|
140
|
+
if (bareHost.toLowerCase().endsWith('.onion')) {
|
|
133
141
|
if (options.hasTorProxy)
|
|
134
142
|
return undefined;
|
|
135
143
|
throw new TransportUnavailableError(url, 'Tor proxy required for .onion addresses');
|
|
136
144
|
}
|
|
145
|
+
if (options.remoteDns) {
|
|
146
|
+
const family = isIP(bareHost);
|
|
147
|
+
if (family)
|
|
148
|
+
assertNotBlocked(bareHost, family, url);
|
|
149
|
+
else if (LOCAL_NAME_RE.test(bareHost))
|
|
150
|
+
throw new SsrfError('local host name', url);
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
137
153
|
// Resolve ALL addresses to prevent multi-homed bypass where one A/AAAA
|
|
138
154
|
// record is public but another resolves to a private/blocked IP.
|
|
139
155
|
let results;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/fetch/ssrf-guard.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/fetch/ssrf-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ export interface TransportCapabilities {
|
|
|
6
6
|
*
|
|
7
7
|
* - .onion URLs are filtered out when `hasTorProxy` is false
|
|
8
8
|
* - URLs are sorted by `preference` order (lower index = higher priority)
|
|
9
|
+
* - A TLD that is neither familiar nor known to be Handshake sorts after https
|
|
9
10
|
* - URLs whose transport type is not in the preference list are placed last
|
|
10
11
|
* - Relative order is preserved within the same tier (stable sort)
|
|
11
12
|
*/
|
package/build/fetch/transport.js
CHANGED
|
@@ -15,49 +15,72 @@ const COMMON_TLDS = new Set([
|
|
|
15
15
|
// Country codes that see common non-country usage
|
|
16
16
|
'ly', 'gg', 'gg', 'sh', 'io',
|
|
17
17
|
]);
|
|
18
|
+
/**
|
|
19
|
+
* TLDs that are Handshake names and not ICANN ones. A TLD merely missing
|
|
20
|
+
* from COMMON_TLDS is far more often an ICANN TLD this list does not know
|
|
21
|
+
* (.pub, .fyi, and hundreds more) than a Handshake one.
|
|
22
|
+
*/
|
|
23
|
+
const KNOWN_HNS_TLDS = new Set(['hns']);
|
|
24
|
+
/** `guessed` marks an HNS classification made only because the TLD is unfamiliar. */
|
|
18
25
|
function classifyUrl(url) {
|
|
19
26
|
let parsed;
|
|
20
27
|
try {
|
|
21
28
|
parsed = new URL(url);
|
|
22
29
|
}
|
|
23
30
|
catch {
|
|
24
|
-
return 'http';
|
|
31
|
+
return { type: 'http', guessed: false };
|
|
25
32
|
}
|
|
26
33
|
const hostname = parsed.hostname.toLowerCase();
|
|
27
34
|
if (hostname.endsWith('.onion'))
|
|
28
|
-
return 'onion';
|
|
35
|
+
return { type: 'onion', guessed: false };
|
|
29
36
|
const tld = hostname.split('.').pop() ?? '';
|
|
37
|
+
if (KNOWN_HNS_TLDS.has(tld))
|
|
38
|
+
return { type: 'hns', guessed: false };
|
|
30
39
|
if (!COMMON_TLDS.has(tld))
|
|
31
|
-
return 'hns';
|
|
40
|
+
return { type: 'hns', guessed: true };
|
|
32
41
|
if (parsed.protocol === 'https:')
|
|
33
|
-
return 'https';
|
|
34
|
-
return 'http';
|
|
42
|
+
return { type: 'https', guessed: false };
|
|
43
|
+
return { type: 'http', guessed: false };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Where a URL sorts under `preference`. A guessed HNS name sorts just after
|
|
47
|
+
* both the hns and https tiers, so an unfamiliar ICANN TLD never jumps ahead
|
|
48
|
+
* of a service's ordinary HTTPS endpoint.
|
|
49
|
+
*/
|
|
50
|
+
function rank(url, preference) {
|
|
51
|
+
const { type, guessed } = classifyUrl(url);
|
|
52
|
+
const idx = preference.indexOf(type);
|
|
53
|
+
if (idx === -1)
|
|
54
|
+
return Infinity;
|
|
55
|
+
if (!guessed)
|
|
56
|
+
return idx;
|
|
57
|
+
const httpsIdx = preference.indexOf('https');
|
|
58
|
+
return Math.max(idx, httpsIdx) + 0.5;
|
|
35
59
|
}
|
|
36
60
|
/**
|
|
37
61
|
* Filter and sort URLs by client capabilities and preference order.
|
|
38
62
|
*
|
|
39
63
|
* - .onion URLs are filtered out when `hasTorProxy` is false
|
|
40
64
|
* - URLs are sorted by `preference` order (lower index = higher priority)
|
|
65
|
+
* - A TLD that is neither familiar nor known to be Handshake sorts after https
|
|
41
66
|
* - URLs whose transport type is not in the preference list are placed last
|
|
42
67
|
* - Relative order is preserved within the same tier (stable sort)
|
|
43
68
|
*/
|
|
44
69
|
export function selectTransports(urls, preference, capabilities) {
|
|
45
70
|
// Filter: remove .onion URLs when no Tor proxy is available
|
|
46
71
|
const filtered = urls.filter(url => {
|
|
47
|
-
const type = classifyUrl(url);
|
|
72
|
+
const { type } = classifyUrl(url);
|
|
48
73
|
if (type === 'onion' && !capabilities.hasTorProxy)
|
|
49
74
|
return false;
|
|
50
75
|
return true;
|
|
51
76
|
});
|
|
52
|
-
// Sort by preference
|
|
77
|
+
// Sort by preference rank (stable; Array.prototype.sort is stable in Node 18+).
|
|
78
|
+
// Not in the preference list → Infinity, placed at the end.
|
|
53
79
|
return filtered.slice().sort((a, b) => {
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Not in preference list → place at end (index = Infinity)
|
|
59
|
-
const posA = idxA === -1 ? Infinity : idxA;
|
|
60
|
-
const posB = idxB === -1 ? Infinity : idxB;
|
|
80
|
+
const posA = rank(a, preference);
|
|
81
|
+
const posB = rank(b, preference);
|
|
82
|
+
if (posA === posB)
|
|
83
|
+
return 0;
|
|
61
84
|
return posA - posB;
|
|
62
85
|
});
|
|
63
86
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/fetch/transport.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACrE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACtE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM;IACvE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;IACjD,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS;IAC5E,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;IAC1E,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU;IAC3E,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACzE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC1D,kDAAkD;IAClD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;CAC7B,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/fetch/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Host header values the HTTP transport accepts. The MCP SDK compares the
|
|
4
|
+
* whole header, port included, so a DNS-rebinding page served from another
|
|
5
|
+
* name cannot reach the server even from the user's own browser.
|
|
6
|
+
*
|
|
7
|
+
* A loopback bind accepts the usual loopback names. Any other bind accepts
|
|
8
|
+
* its own address. `extra` (HTTP_ALLOWED_HOSTS) adds names such as the one a
|
|
9
|
+
* reverse proxy forwards, written exactly as clients send them.
|
|
10
|
+
*/
|
|
11
|
+
export declare function allowedHostsFor(bindAddress: string, port: number, extra?: string[]): string[];
|
|
12
|
+
/** Express middleware requiring `Authorization: Bearer <token>`, compared in constant time. */
|
|
13
|
+
export declare function bearerAuth(token: string): (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
const LOOPBACK = new Set(['127.0.0.1', '::1', 'localhost']);
|
|
3
|
+
function hostWithPort(host, port) {
|
|
4
|
+
return host.includes(':') ? `[${host}]:${port}` : `${host}:${port}`;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Host header values the HTTP transport accepts. The MCP SDK compares the
|
|
8
|
+
* whole header, port included, so a DNS-rebinding page served from another
|
|
9
|
+
* name cannot reach the server even from the user's own browser.
|
|
10
|
+
*
|
|
11
|
+
* A loopback bind accepts the usual loopback names. Any other bind accepts
|
|
12
|
+
* its own address. `extra` (HTTP_ALLOWED_HOSTS) adds names such as the one a
|
|
13
|
+
* reverse proxy forwards, written exactly as clients send them.
|
|
14
|
+
*/
|
|
15
|
+
export function allowedHostsFor(bindAddress, port, extra = []) {
|
|
16
|
+
const hosts = LOOPBACK.has(bindAddress)
|
|
17
|
+
? ['localhost', '127.0.0.1', '::1'].map(h => hostWithPort(h, port))
|
|
18
|
+
: bindAddress === '0.0.0.0' || bindAddress === '::'
|
|
19
|
+
? []
|
|
20
|
+
: [hostWithPort(bindAddress, port)];
|
|
21
|
+
return [...new Set([...hosts, ...extra])];
|
|
22
|
+
}
|
|
23
|
+
/** Express middleware requiring `Authorization: Bearer <token>`, compared in constant time. */
|
|
24
|
+
export function bearerAuth(token) {
|
|
25
|
+
const expected = createHash('sha256').update(token).digest();
|
|
26
|
+
return (req, res, next) => {
|
|
27
|
+
const header = req.headers.authorization ?? '';
|
|
28
|
+
const match = /^Bearer (.+)$/.exec(header);
|
|
29
|
+
const presented = createHash('sha256').update(match ? match[1] : '').digest();
|
|
30
|
+
if (!match || !timingSafeEqual(presented, expected)) {
|
|
31
|
+
res.setHeader('WWW-Authenticate', 'Bearer');
|
|
32
|
+
res.status(401).json({ error: 'Unauthorised' });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
next();
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=http-security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-security.js","sourceRoot":"","sources":["../src/http-security.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAGzD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAA;AAE3D,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY;IAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAA;AACrE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,IAAY,EAAE,QAAkB,EAAE;IACrF,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;QACrC,CAAC,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACnE,CAAC,CAAC,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,IAAI;YACjD,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;AAC3C,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAA;IAC5D,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAQ,EAAE;QAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAA;QAC9C,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;QAC7E,IAAI,CAAC,KAAK,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAA;YAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;YAC/C,OAAM;QACR,CAAC;QACD,IAAI,EAAE,CAAA;IACR,CAAC,CAAA;AACH,CAAC"}
|