@server/next 0.48.0 → 0.48.2
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/index.js +53 -4
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1021,6 +1021,16 @@ function seconds(expires) {
|
|
|
1021
1021
|
if (!ms) throw new Error(`Invalid \`expires\`: "${expires}"`);
|
|
1022
1022
|
return Math.round(ms / 1e3);
|
|
1023
1023
|
}
|
|
1024
|
+
var looksLikeOurs = (token) => {
|
|
1025
|
+
const parts = token.split(".");
|
|
1026
|
+
if (parts.length !== 3) return false;
|
|
1027
|
+
try {
|
|
1028
|
+
const header = JSON.parse(atob(parts[0].replace(/-/g, "+").replace(/_/g, "/")));
|
|
1029
|
+
return header?.alg === "HS256";
|
|
1030
|
+
} catch {
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1024
1034
|
var bearer = (ctx) => {
|
|
1025
1035
|
const header = ctx.headers.authorization;
|
|
1026
1036
|
if (!header) return;
|
|
@@ -1034,8 +1044,13 @@ async function read(ctx, strategy) {
|
|
|
1034
1044
|
if (!token) return;
|
|
1035
1045
|
const payload = await verifyJwt(token, ctx.options.secrets);
|
|
1036
1046
|
if (!payload) {
|
|
1037
|
-
if (inCookie(strategy))
|
|
1038
|
-
|
|
1047
|
+
if (!inCookie(strategy)) throw ServerError_default.AUTH_INVALID_TOKEN();
|
|
1048
|
+
ctx.clearCookie = NAME;
|
|
1049
|
+
ctx.options.log?.message(
|
|
1050
|
+
"auth",
|
|
1051
|
+
looksLikeOurs(token) ? "discarded a session cookie signed with a key that is not in SECRETS. If you rotated it, keep the previous value: secrets: [current, previous]" : "discarded a session cookie that was not issued by this app"
|
|
1052
|
+
);
|
|
1053
|
+
return;
|
|
1039
1054
|
}
|
|
1040
1055
|
return payload;
|
|
1041
1056
|
}
|
|
@@ -1592,8 +1607,13 @@ function entry2(options) {
|
|
|
1592
1607
|
try {
|
|
1593
1608
|
claims2 = await check(token, issuer, allowed, claimNames);
|
|
1594
1609
|
} catch (error) {
|
|
1595
|
-
if (options.cookie)
|
|
1596
|
-
|
|
1610
|
+
if (!options.cookie) throw error;
|
|
1611
|
+
ctx.clearCookie = options.cookie;
|
|
1612
|
+
ctx.options.log?.message(
|
|
1613
|
+
"auth",
|
|
1614
|
+
`discarded a ${options.cookie} cookie that ${issuer} did not sign, or that has expired`
|
|
1615
|
+
);
|
|
1616
|
+
return;
|
|
1597
1617
|
}
|
|
1598
1618
|
ctx.auth = {
|
|
1599
1619
|
issuedAt: new Date((claims2.iat ?? 0) * 1e3),
|
|
@@ -2090,6 +2110,27 @@ function applyCors(res, ctx) {
|
|
|
2090
2110
|
}
|
|
2091
2111
|
}
|
|
2092
2112
|
|
|
2113
|
+
// src/helpers/forwarded.ts
|
|
2114
|
+
var first2 = (value) => {
|
|
2115
|
+
const one = Array.isArray(value) ? value[0] : value;
|
|
2116
|
+
return one?.split(",")[0].trim() || void 0;
|
|
2117
|
+
};
|
|
2118
|
+
function forwarded(url, headers2, trustProxy) {
|
|
2119
|
+
if (!trustProxy) return;
|
|
2120
|
+
const proto = first2(headers2["x-forwarded-proto"]);
|
|
2121
|
+
if (proto === "http" || proto === "https") url.protocol = `${proto}:`;
|
|
2122
|
+
const host = first2(headers2["x-forwarded-host"]);
|
|
2123
|
+
const port = first2(headers2["x-forwarded-port"]);
|
|
2124
|
+
if (host?.includes(":")) {
|
|
2125
|
+
url.host = host;
|
|
2126
|
+
} else if (host) {
|
|
2127
|
+
url.hostname = host;
|
|
2128
|
+
url.port = port ?? "";
|
|
2129
|
+
} else if (port) {
|
|
2130
|
+
url.port = port;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2093
2134
|
// src/helpers/createWebsocket.ts
|
|
2094
2135
|
function createWebsocket(sockets, handlers) {
|
|
2095
2136
|
const run2 = (event, socket, body) => {
|
|
@@ -2170,6 +2211,12 @@ async function parseResponse(out, ctx) {
|
|
|
2170
2211
|
applyCors(out, ctx);
|
|
2171
2212
|
applySecurity(out, ctx);
|
|
2172
2213
|
out = await applyCache(out, ctx);
|
|
2214
|
+
if (ctx.clearCookie) {
|
|
2215
|
+
out.headers.append(
|
|
2216
|
+
"set-cookie",
|
|
2217
|
+
`${ctx.clearCookie}=; Path=/; Max-Age=0; HttpOnly`
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2173
2220
|
if (ctx.time?.times?.length > 1) {
|
|
2174
2221
|
out.headers.set("Server-Timing", ctx.time.headers());
|
|
2175
2222
|
}
|
|
@@ -2880,6 +2927,7 @@ async function createNode(req, app, signal = new AbortController().signal) {
|
|
|
2880
2927
|
const path = (req.url || "/").replace(/\/$/, "") || "/";
|
|
2881
2928
|
const baseUrl = `${scheme}://${host}`;
|
|
2882
2929
|
const url = new URL(path, baseUrl);
|
|
2930
|
+
forwarded(url, headers2, app.settings.security.trustProxy);
|
|
2883
2931
|
define(
|
|
2884
2932
|
url,
|
|
2885
2933
|
"query",
|
|
@@ -2923,6 +2971,7 @@ async function createWinter(req, app, server2) {
|
|
|
2923
2971
|
const cookies2 = parseCookies(headers2.cookie);
|
|
2924
2972
|
const baseUrl = req.url.replace(/\/$/, "") || "/";
|
|
2925
2973
|
const url = new URL(baseUrl);
|
|
2974
|
+
forwarded(url, headers2, app.settings.security.trustProxy);
|
|
2926
2975
|
define(
|
|
2927
2976
|
url,
|
|
2928
2977
|
"query",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@server/next",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.2",
|
|
4
4
|
"description": "A fully-fledged web server with routing, file uploads, sessions, static files, schema validation, websockets, testing, etc.",
|
|
5
5
|
"homepage": "https://server-js.com/",
|
|
6
6
|
"repository": "github:franciscop/server-next",
|