@rapidrest/service-core 2.2.0 → 2.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 +2 -0
- package/dist/lib/ApiErrors.js +4 -0
- package/dist/lib/ApiErrors.js.map +1 -1
- package/dist/lib/auth/JWTStrategy.js +16 -6
- package/dist/lib/auth/JWTStrategy.js.map +1 -1
- package/dist/lib/http/bun/BunAdapters.js +8 -0
- package/dist/lib/http/bun/BunAdapters.js.map +1 -1
- package/dist/lib/http/csrf/csrf.js +212 -0
- package/dist/lib/http/csrf/csrf.js.map +1 -0
- package/dist/lib/http/index.js +6 -0
- package/dist/lib/http/index.js.map +1 -1
- package/dist/lib/http/uWS/Adapters.js +82 -2
- package/dist/lib/http/uWS/Adapters.js.map +1 -1
- package/dist/lib/http/uWS/Router.js +6 -0
- package/dist/lib/http/uWS/Router.js.map +1 -1
- package/dist/lib/models/ModelUtils.js +91 -1
- package/dist/lib/models/ModelUtils.js.map +1 -1
- package/dist/lib/routes/RouteUtils.js +89 -3
- package/dist/lib/routes/RouteUtils.js.map +1 -1
- package/dist/lib/test/request.js +15 -0
- package/dist/lib/test/request.js.map +1 -1
- package/dist/types/ApiErrors.d.ts +6 -2
- package/dist/types/auth/AuthStrategy.d.ts +4 -0
- package/dist/types/auth/JWTStrategy.d.ts +1 -1
- package/dist/types/http/bun/BunAdapters.d.ts +7 -0
- package/dist/types/http/csrf/csrf.d.ts +117 -0
- package/dist/types/http/index.d.ts +2 -0
- package/dist/types/http/uWS/Adapters.d.ts +41 -1
- package/dist/types/models/ModelUtils.d.ts +39 -0
- package/dist/types/routes/RouteUtils.d.ts +30 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,8 @@ For complete documentation please visit [RapidREST.dev](https://rapidrest.dev).
|
|
|
40
40
|
- Server-side session management (in-memory or Redis-backed)
|
|
41
41
|
- Attempt-count rate limiting (`RateLimiter`) for brute-force/abuse defense, layered per-identifier
|
|
42
42
|
and per-source-IP (reverse-proxy aware), Redis-backed and atomic across instances
|
|
43
|
+
- CSRF (double-submit cookie) protection (`RouteUtils.checkCsrf()`), applied automatically to every
|
|
44
|
+
cookie-authenticated, state-changing request — never a bearer-token/API-key/query-token caller
|
|
43
45
|
|
|
44
46
|
**Real-time & Background Work**
|
|
45
47
|
|
package/dist/lib/ApiErrors.js
CHANGED
|
@@ -24,11 +24,13 @@ export var ApiErrors;
|
|
|
24
24
|
ApiErrors["SEARCH_OPERATOR_NOT_SUPPORTED"] = "api-020";
|
|
25
25
|
ApiErrors["BULK_CREATE_FAILURE"] = "api-021";
|
|
26
26
|
ApiErrors["BULK_UPDATE_FAILURE"] = "api-022";
|
|
27
|
+
ApiErrors["SEARCH_SCOPED_FIELD"] = "api-023";
|
|
27
28
|
ApiErrors["AUTH_REQUIRED"] = "api-100";
|
|
28
29
|
ApiErrors["AUTH_FAILED"] = "api-101";
|
|
29
30
|
ApiErrors["AUTH_PERMISSION_FAILURE"] = "api-102";
|
|
30
31
|
ApiErrors["AUTH_REQUIRES_TRUSTED_ROLE"] = "api-103";
|
|
31
32
|
ApiErrors["AUTH_REQUIRES_ELEVATION"] = "api-104";
|
|
33
|
+
ApiErrors["AUTH_CSRF_FAILURE"] = "api-105";
|
|
32
34
|
})(ApiErrors || (ApiErrors = {}));
|
|
33
35
|
/**
|
|
34
36
|
* Defines the default message of all common API errors.
|
|
@@ -52,10 +54,12 @@ export var ApiErrorMessages;
|
|
|
52
54
|
ApiErrorMessages["SEARCH_OPERATOR_NOT_SUPPORTED"] = "The '{{operator}}' operator is not supported by the configured datasource.";
|
|
53
55
|
ApiErrorMessages["BULK_CREATE_FAILURE"] = "Failed to create one or more objects.";
|
|
54
56
|
ApiErrorMessages["BULK_UPDATE_FAILURE"] = "Failed to update one or more objects.";
|
|
57
|
+
ApiErrorMessages["SEARCH_SCOPED_FIELD"] = "Cannot filter, sort or count by scoped field '{{field}}'.";
|
|
55
58
|
ApiErrorMessages["AUTH_REQUIRED"] = "Authorization is required to access this resource.";
|
|
56
59
|
ApiErrorMessages["AUTH_FAILED"] = "Invalid or missing authentication token.";
|
|
57
60
|
ApiErrorMessages["AUTH_PERMISSION_FAILURE"] = "User does not have permission to perform this action.";
|
|
58
61
|
ApiErrorMessages["AUTH_REQUIRES_TRUSTED_ROLE"] = "User does not have permission to perform this action.";
|
|
59
62
|
ApiErrorMessages["AUTH_REQUIRES_ELEVATION"] = "This operation requires elevation.";
|
|
63
|
+
ApiErrorMessages["AUTH_CSRF_FAILURE"] = "This request is missing a valid CSRF token.";
|
|
60
64
|
})(ApiErrorMessages || (ApiErrorMessages = {}));
|
|
61
65
|
//# sourceMappingURL=ApiErrors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiErrors.js","sourceRoot":"","sources":["../../src/ApiErrors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wEAAwE;AACxE,mCAAmC;AACnC,+EAA+E;AAC/E;;GAEG;AACH,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"ApiErrors.js","sourceRoot":"","sources":["../../src/ApiErrors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wEAAwE;AACxE,mCAAmC;AACnC,+EAA+E;AAC/E;;GAEG;AACH,MAAM,CAAN,IAAY,SAyBX;AAzBD,WAAY,SAAS;IACjB,gCAAmB,CAAA;IACnB,uCAA0B,CAAA;IAC1B,wCAA2B,CAAA;IAC3B,0CAA6B,CAAA;IAC7B,kCAAqB,CAAA;IACrB,0CAA6B,CAAA;IAC7B,+CAAkC,CAAA;IAClC,2CAA8B,CAAA;IAC9B,6CAAgC,CAAA;IAChC,oDAAuC,CAAA;IACvC,gDAAmC,CAAA;IACnC,oDAAuC,CAAA;IACvC,kDAAqC,CAAA;IACrC,iDAAoC,CAAA;IACpC,sDAAyC,CAAA;IACzC,4CAA+B,CAAA;IAC/B,4CAA+B,CAAA;IAC/B,4CAA+B,CAAA;IAC/B,sCAAyB,CAAA;IACzB,oCAAuB,CAAA;IACvB,gDAAmC,CAAA;IACnC,mDAAsC,CAAA;IACtC,gDAAmC,CAAA;IACnC,0CAA6B,CAAA;AACjC,CAAC,EAzBW,SAAS,KAAT,SAAS,QAyBpB;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,gBAyBX;AAzBD,WAAY,gBAAgB;IACxB,gFAA4D,CAAA;IAC5D,uGAAmF,CAAA;IACnF,mEAA+C,CAAA;IAC/C,4FAAwE,CAAA;IACxE,2FAAuE,CAAA;IACvE,yFAAqE,CAAA;IACrE,sGAAkF,CAAA;IAClF,mGAA+E,CAAA;IAC/E,mHAA+F,CAAA;IAC/F,sGAAkF,CAAA;IAClF,4JAAwI,CAAA;IACxI,yHAAqG,CAAA;IACrG,2FAAuE,CAAA;IACvE,kHAA8F,CAAA;IAC9F,gIAA4G,CAAA;IAC5G,iFAA6D,CAAA;IAC7D,iFAA6D,CAAA;IAC7D,qGAAiF,CAAA;IACjF,wFAAoE,CAAA;IACpE,4EAAwD,CAAA;IACxD,qGAAiF,CAAA;IACjF,wGAAoF,CAAA;IACpF,kFAA8D,CAAA;IAC9D,qFAAiE,CAAA;AACrE,CAAC,EAzBW,gBAAgB,KAAhB,gBAAgB,QAyB3B"}
|
|
@@ -89,7 +89,7 @@ export class JWTStrategy {
|
|
|
89
89
|
/**
|
|
90
90
|
* Scans the provided request object for an authentication token this strategy can process.
|
|
91
91
|
* @param req The request to scan for an auth token.
|
|
92
|
-
* @returns The auth token if found, otherwise `undefined`.
|
|
92
|
+
* @returns The auth token and which source it was found in, if found, otherwise `undefined`.
|
|
93
93
|
*/
|
|
94
94
|
getAuthToken(req) {
|
|
95
95
|
let authToken = undefined;
|
|
@@ -100,6 +100,9 @@ export class JWTStrategy {
|
|
|
100
100
|
req.query &&
|
|
101
101
|
this.options.queryKey in req.query) {
|
|
102
102
|
authToken = req.query[this.options.queryKey];
|
|
103
|
+
if (authToken) {
|
|
104
|
+
return { token: authToken, source: "query" };
|
|
105
|
+
}
|
|
103
106
|
}
|
|
104
107
|
// Next check the headers, but only if a higher-precedence source (the query parameter above)
|
|
105
108
|
// hasn't already supplied a token — a later-checked, lower-precedence source must never override
|
|
@@ -120,6 +123,9 @@ export class JWTStrategy {
|
|
|
120
123
|
authToken = parts[1];
|
|
121
124
|
break;
|
|
122
125
|
}
|
|
126
|
+
if (authToken) {
|
|
127
|
+
return { token: authToken, source: "header" };
|
|
128
|
+
}
|
|
123
129
|
}
|
|
124
130
|
// Check the cookie header — lowest precedence, so only consulted if neither the query parameter
|
|
125
131
|
// nor the header supplied a token above.
|
|
@@ -129,21 +135,22 @@ export class JWTStrategy {
|
|
|
129
135
|
if (!authToken && this.options.cookieSecure && this.options.cookieName && req.signedCookies) {
|
|
130
136
|
const cookieToken = req.signedCookies[this.options.cookieName];
|
|
131
137
|
if (cookieToken) {
|
|
132
|
-
|
|
138
|
+
return { token: cookieToken, source: "cookie" };
|
|
133
139
|
}
|
|
134
140
|
}
|
|
135
141
|
if (!authToken && !this.options.cookieSecure && this.options.cookieName && req.cookies) {
|
|
136
142
|
const cookieToken = req.cookies[this.options.cookieName];
|
|
137
143
|
if (cookieToken) {
|
|
138
|
-
|
|
144
|
+
return { token: cookieToken, source: "cookie" };
|
|
139
145
|
}
|
|
140
146
|
}
|
|
141
|
-
return
|
|
147
|
+
return undefined;
|
|
142
148
|
}
|
|
143
149
|
async authenticate(req, res) {
|
|
144
150
|
let user = undefined;
|
|
145
151
|
let authPayload = undefined;
|
|
146
|
-
|
|
152
|
+
const found = this.getAuthToken(req);
|
|
153
|
+
const authToken = found?.token;
|
|
147
154
|
// If the token has been found, verify it.
|
|
148
155
|
if (authToken && authToken.length > 0) {
|
|
149
156
|
const payload = await JWTUtils.decodeToken(this.config, authToken);
|
|
@@ -168,6 +175,7 @@ export class JWTStrategy {
|
|
|
168
175
|
method: this.name,
|
|
169
176
|
payload: authPayload,
|
|
170
177
|
tokenFound: authToken !== undefined,
|
|
178
|
+
source: found?.source,
|
|
171
179
|
user,
|
|
172
180
|
};
|
|
173
181
|
}
|
|
@@ -177,7 +185,8 @@ export class JWTStrategy {
|
|
|
177
185
|
authenticateSync(req, res) {
|
|
178
186
|
let user = undefined;
|
|
179
187
|
let authPayload = undefined;
|
|
180
|
-
|
|
188
|
+
const found = this.getAuthToken(req);
|
|
189
|
+
const authToken = found?.token;
|
|
181
190
|
// If the token has been found, verify it.
|
|
182
191
|
if (authToken && authToken.length > 0) {
|
|
183
192
|
const payload = JWTUtils.decodeTokenSync(this.config, authToken);
|
|
@@ -202,6 +211,7 @@ export class JWTStrategy {
|
|
|
202
211
|
method: this.name,
|
|
203
212
|
payload: authPayload,
|
|
204
213
|
tokenFound: authToken !== undefined,
|
|
214
|
+
source: found?.source,
|
|
205
215
|
user,
|
|
206
216
|
};
|
|
207
217
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JWTStrategy.js","sourceRoot":"","sources":["../../../src/auth/JWTStrategy.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"JWTStrategy.js","sourceRoot":"","sources":["../../../src/auth/JWTStrategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -338,11 +338,19 @@ export async function readBunBody(req, rawRequest, maxBodySize = DEFAULT_MAX_BOD
|
|
|
338
338
|
* Destroys the returned stream if the client disconnects mid-upload, via the request's own
|
|
339
339
|
* `AbortSignal` — mirroring `makeBodyStream()`'s uWS `onAborted`-driven cleanup — so a handler
|
|
340
340
|
* consuming it via `for await` sees a thrown error instead of hanging forever.
|
|
341
|
+
*
|
|
342
|
+
* A route that never reads the returned stream at all can still trigger that destroy() (the request
|
|
343
|
+
* simply gets aborted independently, e.g. the client navigating away), so a permanent no-op `error`
|
|
344
|
+
* listener is attached — a `Readable` with no active consumer still emits `error` on `destroy(err)`,
|
|
345
|
+
* and Node treats a zero-listener `error` event as fatal (crashes the process). This doesn't swallow
|
|
346
|
+
* anything from a real consumer: EventEmitter calls every registered listener, not just the first, so
|
|
347
|
+
* `for await`/`.pipe()`/an explicit `.on("error")` still see the same event independently.
|
|
341
348
|
*/
|
|
342
349
|
export function makeBunBodyStream(rawRequest) {
|
|
343
350
|
if (!rawRequest.body)
|
|
344
351
|
return undefined;
|
|
345
352
|
const stream = Readable.fromWeb(rawRequest.body);
|
|
353
|
+
stream.on("error", () => undefined);
|
|
346
354
|
rawRequest.signal?.addEventListener("abort", () => {
|
|
347
355
|
if (!stream.destroyed) {
|
|
348
356
|
stream.destroy(new Error("Request aborted before the body stream was fully read."));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BunAdapters.js","sourceRoot":"","sources":["../../../../src/http/bun/BunAdapters.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BunAdapters.js","sourceRoot":"","sources":["../../../../src/http/bun/BunAdapters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import * as crypto from "crypto";
|
|
6
|
+
import { ApiError } from "@rapidrest/core";
|
|
7
|
+
import { ApiErrorMessages, ApiErrors } from "../../ApiErrors.js";
|
|
8
|
+
/**
|
|
9
|
+
* Double-submit CSRF protection for the `jwt` cookie that `@rapidrest/auth`'s `TokenUtils` issues (see
|
|
10
|
+
* that library's `CsrfUtils`, which rotates this same cookie at login/elevation/logout). This module is
|
|
11
|
+
* the shared, framework-agnostic core: `RouteUtils.checkCsrf()` wires it into every route's middleware
|
|
12
|
+
* chain automatically, and `createCsrfMiddleware()` below offers the same check as a standalone global
|
|
13
|
+
* middleware for a service that doesn't go through `RouteUtils` (or wants it registered once instead of
|
|
14
|
+
* per-route). `auth`'s route handlers that read `req.session` directly instead of going through the
|
|
15
|
+
* `jwt`-cookie auth path (e.g. the OAuth `/authorize/consent` route) call `verifyCsrfRequest()` by hand —
|
|
16
|
+
* see that route's own doc comment for why it can't rely on the automatic, `req.auth`-keyed gate.
|
|
17
|
+
*
|
|
18
|
+
* ## Why this is a host-only cookie, not a naive double-submit
|
|
19
|
+
*
|
|
20
|
+
* The `jwt`/`refresh` cookies `TokenUtils` issues are commonly configured with a wildcard `Domain`
|
|
21
|
+
* (e.g. `.example.com`) so a single sign-in is shared across sibling subdomains (`mail.example.com`,
|
|
22
|
+
* `auth.example.com`, ...) — that's the whole point of a shared SSO cookie. A *naive* double-submit CSRF
|
|
23
|
+
* cookie sharing that same wildcard `Domain` would defeat itself: `document.cookie` on *any* sibling
|
|
24
|
+
* subdomain can read a wildcard-domain cookie, so a same-site page that isn't the app itself (a
|
|
25
|
+
* compromised or merely less-trusted subdomain, a multi-tenant customer subdomain, ...) could read the
|
|
26
|
+
* "secret" double-submit value and echo it right back — exactly the value this scheme exists to keep
|
|
27
|
+
* out of an attacker's hands. `SameSite=Lax` doesn't help here either: it blocks genuine cross-*site*
|
|
28
|
+
* forgery, but `auth.example.com` and `mail.example.com` are cross-*origin*, same-*site* — Lax cookies
|
|
29
|
+
* are still attached.
|
|
30
|
+
*
|
|
31
|
+
* `buildCsrfCookie()` below therefore never emits a `Domain` attribute: the cookie this module issues is
|
|
32
|
+
* always host-only, readable only by script running on the exact host that set it. That closes the
|
|
33
|
+
* sibling-subdomain-reads-the-cookie hole, but it also means a *legitimately* cross-origin caller (e.g.
|
|
34
|
+
* `react-shared`'s `authApiFetch()`, used by an admin console on `mail.example.com` to drive
|
|
35
|
+
* impersonation on `auth.example.com`) can never read this cookie either — there is no way for it to
|
|
36
|
+
* supply a matching header. `verifyCsrfRequest()` handles that case by falling back to an Origin/Referer
|
|
37
|
+
* allow-list check for any request whose Origin doesn't match the host it arrived on: the browser only
|
|
38
|
+
* ever sends such a request in the first place because the target's CORS policy already named that exact
|
|
39
|
+
* origin as trusted (see `Server.ts`'s CORS middleware, which reflects `Access-Control-Allow-Origin` only
|
|
40
|
+
* for an exact, explicitly configured match — never a wildcard-with-credentials), so re-checking the same
|
|
41
|
+
* allow-list server-side is a legitimate, independent proof for a cross-origin request in a way that
|
|
42
|
+
* would not exist for a same-origin one.
|
|
43
|
+
*/
|
|
44
|
+
/** Default name of the double-submit CSRF cookie. */
|
|
45
|
+
export const DEFAULT_CSRF_COOKIE_NAME = "csrf";
|
|
46
|
+
/** Default name of the request header a caller echoes the CSRF cookie's value back on. */
|
|
47
|
+
export const DEFAULT_CSRF_HEADER_NAME = "x-csrf-token";
|
|
48
|
+
/** HTTP methods exempt from CSRF checks — by definition never supposed to mutate state. */
|
|
49
|
+
const SAFE_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
|
|
50
|
+
/** Generates a new, cryptographically random CSRF token, matching `OIDCStrategy`'s own `state`-token style. */
|
|
51
|
+
export function generateCsrfToken() {
|
|
52
|
+
return crypto.randomBytes(32).toString("base64url");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Builds the `Set-Cookie` header value for the CSRF cookie. Pass an empty string for `token` to build a
|
|
56
|
+
* header that immediately clears the cookie instead (mirrors `TokenUtils.buildCookie()`'s own clearing
|
|
57
|
+
* convention in `@rapidrest/auth`).
|
|
58
|
+
*
|
|
59
|
+
* Deliberately never emits a `Domain` attribute, even though the sibling `jwt`/`refresh` cookies often do
|
|
60
|
+
* — see this module's doc comment for why a wide-open `Domain` here would defeat the whole scheme.
|
|
61
|
+
* Deliberately never emits `HttpOnly` either: browser JavaScript reading this cookie and echoing it back
|
|
62
|
+
* as a header is the entire mechanism.
|
|
63
|
+
*/
|
|
64
|
+
export function buildCsrfCookie(token, options = {}) {
|
|
65
|
+
const clearing = token === "";
|
|
66
|
+
const parts = [`${options.name ?? DEFAULT_CSRF_COOKIE_NAME}=${token}`, `Path=${options.path ?? "/"}`];
|
|
67
|
+
parts.push(`SameSite=${options.sameSite ?? "Lax"}`);
|
|
68
|
+
if (clearing) {
|
|
69
|
+
parts.push("Max-Age=0");
|
|
70
|
+
}
|
|
71
|
+
else if (options.maxAge !== undefined) {
|
|
72
|
+
parts.push(`Max-Age=${options.maxAge}`);
|
|
73
|
+
}
|
|
74
|
+
if (options.secure !== false) {
|
|
75
|
+
parts.push("Secure");
|
|
76
|
+
}
|
|
77
|
+
return parts.join("; ");
|
|
78
|
+
}
|
|
79
|
+
/** Constant-time string comparison. Rejects a length mismatch up front — `crypto.timingSafeEqual()` throws on one
|
|
80
|
+
* rather than returning `false`, and comparing lengths first is itself safe (a token's length isn't a secret). */
|
|
81
|
+
function timingSafeEqualStr(a, b) {
|
|
82
|
+
const bufA = Buffer.from(a);
|
|
83
|
+
const bufB = Buffer.from(b);
|
|
84
|
+
return bufA.length > 0 && bufA.length === bufB.length && crypto.timingSafeEqual(bufA, bufB);
|
|
85
|
+
}
|
|
86
|
+
function firstHeaderValue(value) {
|
|
87
|
+
return Array.isArray(value) ? value[0] : value;
|
|
88
|
+
}
|
|
89
|
+
/** Extracts `scheme://host` from a full URL string (e.g. a `Referer` header), or `undefined` if unparseable. */
|
|
90
|
+
function originOf(url) {
|
|
91
|
+
if (!url) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const parsed = new URL(url);
|
|
96
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Extracts just the `host` (hostname[:port], no scheme) portion of an origin string, or `undefined` if unparseable. */
|
|
103
|
+
function hostOf(origin) {
|
|
104
|
+
if (!origin) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return new URL(origin).host;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Ensures the caller holds a CSRF cookie, issuing one via `Set-Cookie` if it doesn't already have a valid
|
|
116
|
+
* one — the standard "set on first visit" double-submit pattern (matches Django/Rails), and what lets a
|
|
117
|
+
* service that never itself issues auth cookies (e.g. `server`/`restapi`, which only ever verify a `jwt`
|
|
118
|
+
* cookie someone else set) still adopt this mechanism on its own. Returns the (possibly freshly-generated)
|
|
119
|
+
* token value.
|
|
120
|
+
*/
|
|
121
|
+
export function ensureCsrfCookie(req, res, options = {}) {
|
|
122
|
+
const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE_NAME;
|
|
123
|
+
const existing = req.cookies?.[cookieName];
|
|
124
|
+
if (existing) {
|
|
125
|
+
return existing;
|
|
126
|
+
}
|
|
127
|
+
const token = generateCsrfToken();
|
|
128
|
+
res.appendHeader("Set-Cookie", buildCsrfCookie(token, { name: cookieName, maxAge: options.maxAge, secure: options.secure }));
|
|
129
|
+
return token;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Verifies `req` against the double-submit CSRF cookie plus Origin/Referer allow-list, per the scheme
|
|
133
|
+
* documented at the top of this module. Throws an `ApiError` (`AUTH_CSRF_FAILURE`, 403) on failure. A safe
|
|
134
|
+
* method (`GET`/`HEAD`/`OPTIONS`) or `options.enabled === false` always passes without throwing.
|
|
135
|
+
*
|
|
136
|
+
* This does *not* check `req.auth?.source` — that gate belongs to the caller (see `RouteUtils.checkCsrf()`,
|
|
137
|
+
* which only calls this when `req.auth?.source === "cookie"`). A caller like `BaseOAuthAuthorizeRoute`'s
|
|
138
|
+
* `decideConsent()`, which authenticates via `req.session` instead of a JWT, calls this unconditionally
|
|
139
|
+
* for exactly that reason.
|
|
140
|
+
*/
|
|
141
|
+
export function verifyCsrfRequest(req, options = {}) {
|
|
142
|
+
if (options.enabled === false) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const method = (req.method || "GET").toUpperCase();
|
|
146
|
+
if (SAFE_METHODS.has(method)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const cookieName = options.cookieName ?? DEFAULT_CSRF_COOKIE_NAME;
|
|
150
|
+
const headerName = (options.headerName ?? DEFAULT_CSRF_HEADER_NAME).toLowerCase();
|
|
151
|
+
const allowedOrigins = options.allowedOrigins ?? [];
|
|
152
|
+
const originHeader = firstHeaderValue(req.headers["origin"]);
|
|
153
|
+
const refererHeader = firstHeaderValue(req.headers["referer"] ?? req.headers["referrer"]);
|
|
154
|
+
const effectiveOrigin = originHeader ?? originOf(refererHeader);
|
|
155
|
+
const hostHeader = firstHeaderValue(req.headers["host"]);
|
|
156
|
+
const originHost = hostOf(effectiveOrigin);
|
|
157
|
+
// Scheme is deliberately not part of this comparison: a TLS-terminating proxy commonly forwards a
|
|
158
|
+
// plain-HTTP request to this process for an origin the browser saw as `https://`, and that mismatch
|
|
159
|
+
// alone must never be treated as cross-origin.
|
|
160
|
+
const crossOrigin = !!originHost && !!hostHeader && originHost !== hostHeader;
|
|
161
|
+
// Defense in depth, checked regardless of same/cross-origin whenever an Origin (or Referer fallback)
|
|
162
|
+
// is present and an allow-list is configured: a same-origin request forging its own Origin header is
|
|
163
|
+
// not something a browser lets a page do, so this mainly guards against a misconfigured proxy or a
|
|
164
|
+
// non-browser replay of a stolen cookie pair.
|
|
165
|
+
if (effectiveOrigin && allowedOrigins.length > 0 && !allowedOrigins.includes(effectiveOrigin)) {
|
|
166
|
+
options.logger?.warn?.(`[CSRF] Rejected ${method} ${req.path} — origin '${effectiveOrigin}' is not allow-listed.`);
|
|
167
|
+
throw new ApiError(ApiErrors.AUTH_CSRF_FAILURE, 403, ApiErrorMessages.AUTH_CSRF_FAILURE);
|
|
168
|
+
}
|
|
169
|
+
if (crossOrigin) {
|
|
170
|
+
// A cross-origin caller's own JavaScript cannot read this host's host-only CSRF cookie (see this
|
|
171
|
+
// module's doc comment), so the double-submit check below is structurally unsatisfiable for it —
|
|
172
|
+
// the Origin allow-list check above is this request's only available CSRF defense. Fail closed if
|
|
173
|
+
// there's no allow-list configured at all: nothing here proved the request legitimate.
|
|
174
|
+
if (allowedOrigins.length === 0) {
|
|
175
|
+
options.logger?.warn?.(`[CSRF] Rejected cross-origin ${method} ${req.path} — no CSRF allow-list configured.`);
|
|
176
|
+
throw new ApiError(ApiErrors.AUTH_CSRF_FAILURE, 403, ApiErrorMessages.AUTH_CSRF_FAILURE);
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const cookieToken = req.cookies?.[cookieName];
|
|
181
|
+
const headerToken = firstHeaderValue(req.headers[headerName]);
|
|
182
|
+
if (!cookieToken || !headerToken || !timingSafeEqualStr(cookieToken, headerToken)) {
|
|
183
|
+
options.logger?.warn?.(`[CSRF] Rejected ${method} ${req.path} — missing or mismatched '${headerName}' header.`);
|
|
184
|
+
throw new ApiError(ApiErrors.AUTH_CSRF_FAILURE, 403, ApiErrorMessages.AUTH_CSRF_FAILURE);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Standalone global-middleware form of the same check `RouteUtils.checkCsrf()` installs automatically on
|
|
189
|
+
* every route. Useful for a service that registers its own middleware chain directly instead of going
|
|
190
|
+
* through `RouteUtils` (or that wants a single global registration instead of a per-route one). Always
|
|
191
|
+
* lazily issues the cookie first (see `ensureCsrfCookie()`), then enforces the check only when
|
|
192
|
+
* `req.auth?.source === "cookie"` — the same gate `RouteUtils.checkCsrf()` uses.
|
|
193
|
+
*/
|
|
194
|
+
export function createCsrfMiddleware(options = {}) {
|
|
195
|
+
return (req, res, next) => {
|
|
196
|
+
if (options.enabled !== false) {
|
|
197
|
+
ensureCsrfCookie(req, res, options);
|
|
198
|
+
}
|
|
199
|
+
if (req.auth?.source !== "cookie") {
|
|
200
|
+
next();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
verifyCsrfRequest(req, options);
|
|
205
|
+
next();
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
next(err);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=csrf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.js","sourceRoot":"","sources":["../../../../src/http/csrf/csrf.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/http/index.js
CHANGED
|
@@ -4,6 +4,12 @@ export { extractParamNames, makeWsStubResponse, runChain, splitRouteArgs } from
|
|
|
4
4
|
export { RedisSessionStore } from "./session/RedisSessionStore.js";
|
|
5
5
|
export { SessionManager } from "./session/SessionManager.js";
|
|
6
6
|
export { createSessionMiddleware } from "./session/sessionMiddleware.js";
|
|
7
|
+
// CSRF support — double-submit cookie protection for the `jwt` cookie `@rapidrest/auth`'s `TokenUtils`
|
|
8
|
+
// issues. `RouteUtils.checkCsrf()` wires the check into every registered route automatically; the pieces
|
|
9
|
+
// below are exported for a route that must check by hand (session-only auth, not the `jwt` cookie — see
|
|
10
|
+
// `BaseOAuthAuthorizeRoute.decideConsent()` in `@rapidrest/auth`) or a service that registers its own
|
|
11
|
+
// middleware chain outside of `RouteUtils`.
|
|
12
|
+
export { DEFAULT_CSRF_COOKIE_NAME, DEFAULT_CSRF_HEADER_NAME, buildCsrfCookie, createCsrfMiddleware, ensureCsrfCookie, generateCsrfToken, verifyCsrfRequest, } from "./csrf/csrf.js";
|
|
7
13
|
// uWS-backed adapter. `HttpRouter` is exported as a type only — the class itself value-imports
|
|
8
14
|
// `uWebSockets.js` at module load, which does not work under Bun. Consumers that only annotate with
|
|
9
15
|
// the type stay safe on every runtime; constructing one is done internally by Server.ts via a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAMvG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,+FAA+F;AAC/F,oGAAoG;AACpG,8FAA8F;AAC9F,4CAA4C;AAC5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGtF,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,kGAAkG;AAClG,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAMvG,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,uGAAuG;AACvG,yGAAyG;AACzG,wGAAwG;AACxG,sGAAsG;AACtG,4CAA4C;AAC5C,OAAO,EACH,wBAAwB,EACxB,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GACpB,MAAM,gBAAgB,CAAC;AAGxB,+FAA+F;AAC/F,oGAAoG;AACpG,8FAA8F;AAC9F,4CAA4C;AAC5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGtF,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,kGAAkG;AAClG,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -166,6 +166,16 @@ export class UWSResponse {
|
|
|
166
166
|
this._fireFinish();
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Associates this response with a streaming-body route's `req.bodyStream`, so `end()` can detect
|
|
171
|
+
* a response finalizing before uWS has received the whole declared request body and force the
|
|
172
|
+
* connection closed instead of hanging it — see `isBodyStreamFullyReceived()`'s doc comment for
|
|
173
|
+
* the full rationale. Called once, by the router, right after `makeBodyStream()` creates the
|
|
174
|
+
* stream (`HttpRouteOptions.streamingBody` routes only — never called otherwise).
|
|
175
|
+
*/
|
|
176
|
+
attachBodyStream(stream) {
|
|
177
|
+
this._bodyStream = stream;
|
|
178
|
+
}
|
|
169
179
|
get statusCode() {
|
|
170
180
|
return this._statusCode;
|
|
171
181
|
}
|
|
@@ -220,6 +230,27 @@ export class UWSResponse {
|
|
|
220
230
|
return;
|
|
221
231
|
this._writableEnded = true;
|
|
222
232
|
this._fireFinish();
|
|
233
|
+
if (this._bodyStream && !isBodyStreamFullyReceived(this._bodyStream)) {
|
|
234
|
+
// This is a streaming-body route finalizing its response before uWS has received the
|
|
235
|
+
// whole declared request body — whether because the handler responded without draining
|
|
236
|
+
// req.bodyStream (an auth/validation failure, typically), a slow-but-legitimate client
|
|
237
|
+
// hasn't finished sending yet, or (the exploit this specifically defends against) the
|
|
238
|
+
// client declared a huge Content-Length and never intends to send it. A graceful
|
|
239
|
+
// uwsRes.end() here would leave the connection sitting in uWS's keep-alive machinery
|
|
240
|
+
// waiting for bytes that may never arrive — indefinitely, for the cost of a single
|
|
241
|
+
// request's worth of headers. Force the connection closed instead: uWS won't accept
|
|
242
|
+
// further writes/reads on it either way once this response is finalizing, so there's
|
|
243
|
+
// nothing lost by not attempting a graceful end() here that keep-alive could have reused.
|
|
244
|
+
// uwsRes.close() also fires the onAborted callback already registered in the constructor,
|
|
245
|
+
// which destroys req.bodyStream (via makeBodyStream()'s res.onAbort() hookup) for us.
|
|
246
|
+
try {
|
|
247
|
+
this.uwsRes.close();
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// Already invalid/closed — nothing left to do.
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
223
254
|
this.uwsRes.cork(() => {
|
|
224
255
|
// Write status line (uWS expects "200 OK" format)
|
|
225
256
|
if (!this._headersSent) {
|
|
@@ -447,6 +478,36 @@ export function readBody(uwsRes, req, maxBodySize = DEFAULT_MAX_BODY_SIZE, res)
|
|
|
447
478
|
* plenty of headroom before the network is throttled.
|
|
448
479
|
*/
|
|
449
480
|
export const STREAMING_BODY_HIGH_WATER_MARK = 1024 * 1024;
|
|
481
|
+
/**
|
|
482
|
+
* Internal marker set on every `Readable` returned by `makeBodyStream()`, tracking whether uWS has
|
|
483
|
+
* delivered the final chunk of the request body (`onData`'s `isLast`) yet. Deliberately independent
|
|
484
|
+
* of the stream's own `readableEnded` — Node only flips `readableEnded` once a consumer has actually
|
|
485
|
+
* read all the way to the end, so a stream nobody ever reads from (e.g. a route that rejects the
|
|
486
|
+
* request before touching `req.bodyStream` at all) would stay `readableEnded === false` forever even
|
|
487
|
+
* for a request with an already-fully-arrived, zero-byte body. `isBodyStreamFullyReceived()` reads
|
|
488
|
+
* this marker instead — see its own doc comment and `UWSResponse.end()`, which uses it to decide
|
|
489
|
+
* between a graceful `end()` and a forced `close()`.
|
|
490
|
+
*/
|
|
491
|
+
const FULLY_RECEIVED = Symbol("uwsBodyStreamFullyReceived");
|
|
492
|
+
/**
|
|
493
|
+
* Returns `true` once uWS has delivered the final chunk of `stream`'s request body — i.e. it is safe
|
|
494
|
+
* to let the underlying connection return to uWS's keep-alive pool — regardless of whether anything
|
|
495
|
+
* has actually consumed the stream. Returns `true` for `undefined` (nothing to wait for) so callers
|
|
496
|
+
* can pass `req.bodyStream` directly without an existence check first.
|
|
497
|
+
*
|
|
498
|
+
* See `UWSResponse.end()`: a streaming route's handler can legitimately respond (an auth failure, a
|
|
499
|
+
* validation error, anything) without ever reading `req.bodyStream`. If the client declared a large
|
|
500
|
+
* `Content-Length` and hasn't actually sent it all yet — or, in the malicious case, never intends to
|
|
501
|
+
* — a plain `uwsRes.end()` at that point leaves the keep-alive connection open indefinitely: uWS
|
|
502
|
+
* won't consider it clean for reuse until it has received every byte of the declared body, and nothing
|
|
503
|
+
* in that scenario ever makes that happen. `end()` uses this check to force the connection closed
|
|
504
|
+
* instead whenever it would otherwise leave that promise unfulfilled.
|
|
505
|
+
*/
|
|
506
|
+
export function isBodyStreamFullyReceived(stream) {
|
|
507
|
+
if (!stream)
|
|
508
|
+
return true;
|
|
509
|
+
return stream[FULLY_RECEIVED] === true;
|
|
510
|
+
}
|
|
450
511
|
/**
|
|
451
512
|
* Exposes a uWS request body as a Node `Readable` stream instead of buffering it into memory, for a
|
|
452
513
|
* route registered with `{ streamingBody: true }` (see `HttpRouteOptions`). Does NOT populate
|
|
@@ -466,12 +527,23 @@ export const STREAMING_BODY_HIGH_WATER_MARK = 1024 * 1024;
|
|
|
466
527
|
* pause/resume pairing uWS expects. A slow consumer (a route piping to a slow disk, or one simply
|
|
467
528
|
* not reading yet) still throttles how fast bytes are pulled off the client connection rather than
|
|
468
529
|
* piling up unbounded data in process memory — the failure mode this whole feature exists to avoid.
|
|
530
|
+
* The same pairing discipline also applies to the final chunk: when a chunk that overflows the
|
|
531
|
+
* buffer also happens to be the last one (`isLast`), `pause()` is skipped entirely — the stream is
|
|
532
|
+
* about to signal EOF via `push(null)` regardless, so Node's `Readable` never calls `_read()` again
|
|
533
|
+
* to issue the matching `resume()`, which would otherwise leave uWS's connection paused forever with
|
|
534
|
+
* nothing left in this function to ever un-pause it.
|
|
469
535
|
*
|
|
470
536
|
* The stream is destroyed with an error if the client disconnects mid-upload (wired through the
|
|
471
537
|
* existing single `onAborted` fan-out via `res.onAbort()`, matching `readBody()`'s own abort
|
|
472
538
|
* handling) so a handler awaiting `for await (const chunk of req.bodyStream)` sees a thrown error
|
|
473
539
|
* instead of hanging forever, and can clean up (e.g. delete a partial temp file) in its own
|
|
474
|
-
* `catch`/`finally`.
|
|
540
|
+
* `catch`/`finally`. A route that never reads `req.bodyStream` at all can still hit this path — e.g.
|
|
541
|
+
* `UWSResponse.end()` itself calls `uwsRes.close()` (which fires `onAborted`) when finalizing a
|
|
542
|
+
* response before the body was fully received — so a permanent no-op `error` listener is attached
|
|
543
|
+
* below as well: a `Readable` with no active consumer still emits `error` on `destroy(err)`, and
|
|
544
|
+
* Node treats an `error` event with zero listeners as fatal (crashes the process). This listener
|
|
545
|
+
* doesn't swallow anything from a real consumer — `for await`/`.pipe()`/an explicit `.on("error")`
|
|
546
|
+
* all still see the same event; EventEmitter calls every registered listener, not just the first.
|
|
475
547
|
*
|
|
476
548
|
* Must be called synchronously, before any `await`, in the same tick as request handling begins —
|
|
477
549
|
* uWS requires `onData`/`onAborted` to be registered before any asynchronous operation, matching the
|
|
@@ -501,6 +573,11 @@ export function makeBodyStream(uwsRes, res) {
|
|
|
501
573
|
callback(err);
|
|
502
574
|
},
|
|
503
575
|
});
|
|
576
|
+
stream[FULLY_RECEIVED] = false;
|
|
577
|
+
// Safety net against an unhandled 'error' event crashing the process when nobody ever consumes
|
|
578
|
+
// this stream — see the doc comment above for the full rationale. A real consumer (for await,
|
|
579
|
+
// .pipe(), or its own .on("error")) still observes the same event independently of this listener.
|
|
580
|
+
stream.on("error", () => undefined);
|
|
504
581
|
res.onAbort(() => {
|
|
505
582
|
if (stream.destroyed)
|
|
506
583
|
return;
|
|
@@ -517,12 +594,15 @@ export function makeBodyStream(uwsRes, res) {
|
|
|
517
594
|
// `chunk` is a raw ArrayBuffer uWS reuses/detaches once this callback returns — see the
|
|
518
595
|
// identical, more detailed comment in readBody() above for why `.slice(0)` is required.
|
|
519
596
|
const ok = stream.push(Buffer.from(chunk.slice(0)));
|
|
520
|
-
|
|
597
|
+
// Never pause on the final chunk — see the doc comment above for why that would leave
|
|
598
|
+
// the connection paused with no matching resume() ever coming.
|
|
599
|
+
if (!ok && !isLast) {
|
|
521
600
|
paused = true;
|
|
522
601
|
uwsRes.pause();
|
|
523
602
|
}
|
|
524
603
|
}
|
|
525
604
|
if (isLast) {
|
|
605
|
+
stream[FULLY_RECEIVED] = true;
|
|
526
606
|
stream.push(null);
|
|
527
607
|
}
|
|
528
608
|
});
|