@songsid/agend 2.1.6-beta.1 → 2.1.6-beta.3
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/dist/apply-job.d.ts +114 -0
- package/dist/apply-job.js +214 -0
- package/dist/apply-job.js.map +1 -0
- package/dist/backend/codex.d.ts +24 -0
- package/dist/backend/codex.js +102 -0
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +159 -0
- package/dist/backend/credential-profile.js +340 -0
- package/dist/backend/credential-profile.js.map +1 -0
- package/dist/backend/kiro-auth-store.d.ts +25 -0
- package/dist/backend/kiro-auth-store.js +61 -0
- package/dist/backend/kiro-auth-store.js.map +1 -0
- package/dist/backend/kiro.d.ts +8 -0
- package/dist/backend/kiro.js +31 -2
- package/dist/backend/kiro.js.map +1 -1
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +21 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/daemon.d.ts +10 -0
- package/dist/daemon.js +27 -1
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-level-config.d.ts +42 -0
- package/dist/fleet-level-config.js +78 -0
- package/dist/fleet-level-config.js.map +1 -0
- package/dist/fleet-lock.d.ts +21 -0
- package/dist/fleet-lock.js +42 -8
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +122 -1
- package/dist/fleet-manager.js +537 -83
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +145 -0
- package/dist/instance-config-impact.d.ts +55 -0
- package/dist/instance-config-impact.js +152 -0
- package/dist/instance-config-impact.js.map +1 -0
- package/dist/locale.js +2 -0
- package/dist/locale.js.map +1 -1
- package/dist/outbound-handlers.d.ts +5 -1
- package/dist/outbound-handlers.js +199 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +6 -5
- package/dist/outbound-schemas.js +1 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/provider-probe.d.ts +45 -0
- package/dist/provider-probe.js +111 -0
- package/dist/provider-probe.js.map +1 -0
- package/dist/quickstart-api.d.ts +161 -0
- package/dist/quickstart-api.js +340 -0
- package/dist/quickstart-api.js.map +1 -0
- package/dist/quickstart.js +23 -50
- package/dist/quickstart.js.map +1 -1
- package/dist/self-restart-limit.d.ts +21 -0
- package/dist/self-restart-limit.js +129 -0
- package/dist/self-restart-limit.js.map +1 -0
- package/dist/settings-api.d.ts +15 -0
- package/dist/settings-api.js +126 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/setup-auth.d.ts +113 -0
- package/dist/setup-auth.js +181 -0
- package/dist/setup-auth.js.map +1 -0
- package/dist/setup-form.d.ts +18 -0
- package/dist/setup-form.js +315 -0
- package/dist/setup-form.js.map +1 -0
- package/dist/setup-host.d.ts +162 -0
- package/dist/setup-host.js +496 -0
- package/dist/setup-host.js.map +1 -0
- package/dist/setup-marker.d.ts +8 -0
- package/dist/setup-marker.js +39 -0
- package/dist/setup-marker.js.map +1 -0
- package/dist/setup-tunnel-consent.d.ts +53 -0
- package/dist/setup-tunnel-consent.js +82 -0
- package/dist/setup-tunnel-consent.js.map +1 -0
- package/dist/tips.js +1 -1
- package/dist/tips.js.map +1 -1
- package/dist/transcript-sources.d.ts +12 -1
- package/dist/transcript-sources.js +19 -3
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +71 -0
- package/dist/tunnel/cloudflared.js +447 -0
- package/dist/tunnel/cloudflared.js.map +1 -0
- package/dist/tunnel/lease.d.ts +75 -0
- package/dist/tunnel/lease.js +209 -0
- package/dist/tunnel/lease.js.map +1 -0
- package/dist/tunnel/manager.d.ts +56 -0
- package/dist/tunnel/manager.js +167 -0
- package/dist/tunnel/manager.js.map +1 -0
- package/dist/tunnel/types.d.ts +119 -0
- package/dist/tunnel/types.js +33 -0
- package/dist/tunnel/types.js.map +1 -0
- package/dist/ui/dashboard.html +4 -3
- package/dist/ui/settings.html +640 -153
- package/dist/usage/providers.d.ts +17 -14
- package/dist/usage/providers.js +87 -55
- package/dist/usage/providers.js.map +1 -1
- package/dist/web-api.js +6 -4
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +75 -0
- package/dist/web-auth.js +208 -2
- package/dist/web-auth.js.map +1 -1
- package/package.json +1 -1
package/dist/web-auth.d.ts
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
export declare const WEB_TOKEN_INVALID_MESSAGE = "Token expired or invalid \u2014 run /dashboard again";
|
|
2
|
+
/** No credential at all. Distinct from "wrong credential" so a browser that
|
|
3
|
+
* silently drops cookies is diagnosable instead of looking like a bad token. */
|
|
4
|
+
export declare const WEB_SESSION_REQUIRED_MESSAGE = "No session \u2014 open the dashboard link again (cookies must be enabled for this site)";
|
|
5
|
+
export declare const WEB_CROSS_SITE_MESSAGE = "Cross-site request rejected";
|
|
6
|
+
/** A URL token is redeemed for a session cookie on a GET; it is never a
|
|
7
|
+
* credential for a write, where it would also survive in history and logs. */
|
|
8
|
+
export declare const WEB_URL_TOKEN_WRITE_MESSAGE = "URL tokens are only redeemed on GET \u2014 send X-Agend-Token for API writes";
|
|
9
|
+
export declare const WEB_SESSION_COOKIE = "agend_session";
|
|
10
|
+
/** 12h. The old model was "valid forever"; the panel is an escape hatch, so the
|
|
11
|
+
* cookie outlives a working day and nothing more. `web-token rotate` kills every
|
|
12
|
+
* issued cookie immediately regardless of this. */
|
|
13
|
+
export declare const WEB_SESSION_MAX_AGE_SECONDS: number;
|
|
2
14
|
/**
|
|
3
15
|
* Load the fleet-wide web bearer token, creating it only when absent/invalid.
|
|
4
16
|
* A fleet restart must not revoke every previously issued /dashboard URL.
|
|
5
17
|
*/
|
|
6
18
|
export declare function loadOrCreateWebToken(dataDir: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* The token as it is on disk right now, without creating one.
|
|
21
|
+
*
|
|
22
|
+
* Deliberately unbuffered: `agend web-token rotate` writes the file from a
|
|
23
|
+
* separate process, and a cached copy would keep authorizing revoked sessions
|
|
24
|
+
* until the fleet restarted — which is the whole point of having rotation.
|
|
25
|
+
* mtime/size caching cannot be used either, since a rotation within the same
|
|
26
|
+
* millisecond produces a same-size file.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readWebToken(dataDir: string): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Replace the token with a fresh one. Every previously issued URL, header token
|
|
31
|
+
* and session cookie stops being accepted as soon as the next request is served.
|
|
32
|
+
*/
|
|
33
|
+
export declare function rotateWebToken(dataDir: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* The cookie carries a derivation of the token, never the token itself: a
|
|
36
|
+
* stolen cookie opens the panel but cannot be replayed as `?token=` /
|
|
37
|
+
* `X-Agend-Token` (which also authorize /view writes and the CLI). Rotating
|
|
38
|
+
* `web.token` changes the derivation, so every issued cookie dies with it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function webSessionCookieValue(token: string): string;
|
|
41
|
+
export declare function parseCookieHeader(header: string | undefined): Map<string, string>;
|
|
42
|
+
/** Minimal request shape — everything the gate reads, and nothing more, so the
|
|
43
|
+
* decision can be unit-tested without a socket. */
|
|
44
|
+
export interface WebGateRequest {
|
|
45
|
+
readonly method?: string | undefined;
|
|
46
|
+
readonly headers: NodeJS.Dict<string | string[]>;
|
|
47
|
+
}
|
|
48
|
+
export type WebGateDecision = {
|
|
49
|
+
readonly kind: "allow";
|
|
50
|
+
} | {
|
|
51
|
+
readonly kind: "exchange";
|
|
52
|
+
readonly setCookie: string;
|
|
53
|
+
readonly location: string;
|
|
54
|
+
} | {
|
|
55
|
+
readonly kind: "reject";
|
|
56
|
+
readonly status: 401 | 403;
|
|
57
|
+
readonly message: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* True when the request either carries no Origin (a CLI, or a top-level GET
|
|
61
|
+
* navigation, neither of which a cross-site attacker controls) or carries one
|
|
62
|
+
* that matches the Host it was sent to.
|
|
63
|
+
*
|
|
64
|
+
* Only a *mismatch* rejects: requiring Origin would break every non-browser
|
|
65
|
+
* caller, which is the same `X-Agend-Token` path the CLI uses.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isSameOriginRequest(req: WebGateRequest): boolean;
|
|
68
|
+
export declare function buildSessionCookie(token: string, secure: boolean): string;
|
|
69
|
+
export declare function hasValidSessionCookie(req: WebGateRequest, token: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The single authorization decision for every gated web route.
|
|
72
|
+
*
|
|
73
|
+
* Accepts, in order: a session cookie, an `X-Agend-Token` header (CLI and
|
|
74
|
+
* scripts), and — only to be redeemed for a cookie on a GET — a `?token=` in
|
|
75
|
+
* the URL. After the redemption the token is gone from the address bar, from
|
|
76
|
+
* browser history, and from anything that logs request URLs.
|
|
77
|
+
*/
|
|
78
|
+
export declare function decideWebGate(req: WebGateRequest, url: URL, token: string | null): WebGateDecision;
|
|
79
|
+
/** Defence in depth for handlers that run behind the gate: authorization only,
|
|
80
|
+
* no cookie issuing (the gate already did that). */
|
|
81
|
+
export declare function isWebRequestAuthorized(req: WebGateRequest, url: URL, token: string | null): boolean;
|
package/dist/web-auth.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import { chmodSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
export const WEB_TOKEN_INVALID_MESSAGE = "Token expired or invalid — run /dashboard again";
|
|
5
|
+
/** No credential at all. Distinct from "wrong credential" so a browser that
|
|
6
|
+
* silently drops cookies is diagnosable instead of looking like a bad token. */
|
|
7
|
+
export const WEB_SESSION_REQUIRED_MESSAGE = "No session — open the dashboard link again (cookies must be enabled for this site)";
|
|
8
|
+
export const WEB_CROSS_SITE_MESSAGE = "Cross-site request rejected";
|
|
9
|
+
/** A URL token is redeemed for a session cookie on a GET; it is never a
|
|
10
|
+
* credential for a write, where it would also survive in history and logs. */
|
|
11
|
+
export const WEB_URL_TOKEN_WRITE_MESSAGE = "URL tokens are only redeemed on GET — send X-Agend-Token for API writes";
|
|
5
12
|
const WEB_TOKEN_PATTERN = /^[0-9a-f]{48}$/i;
|
|
13
|
+
export const WEB_SESSION_COOKIE = "agend_session";
|
|
14
|
+
/** 12h. The old model was "valid forever"; the panel is an escape hatch, so the
|
|
15
|
+
* cookie outlives a working day and nothing more. `web-token rotate` kills every
|
|
16
|
+
* issued cookie immediately regardless of this. */
|
|
17
|
+
export const WEB_SESSION_MAX_AGE_SECONDS = 12 * 60 * 60;
|
|
6
18
|
function readValidToken(path) {
|
|
7
19
|
try {
|
|
8
20
|
const token = readFileSync(path, "utf8").trim();
|
|
@@ -28,13 +40,16 @@ function replaceTokenAtomically(path, token) {
|
|
|
28
40
|
throw err;
|
|
29
41
|
}
|
|
30
42
|
}
|
|
43
|
+
function tokenPath(dataDir) {
|
|
44
|
+
return join(dataDir, "web.token");
|
|
45
|
+
}
|
|
31
46
|
/**
|
|
32
47
|
* Load the fleet-wide web bearer token, creating it only when absent/invalid.
|
|
33
48
|
* A fleet restart must not revoke every previously issued /dashboard URL.
|
|
34
49
|
*/
|
|
35
50
|
export function loadOrCreateWebToken(dataDir) {
|
|
36
51
|
mkdirSync(dataDir, { recursive: true });
|
|
37
|
-
const path =
|
|
52
|
+
const path = tokenPath(dataDir);
|
|
38
53
|
const existing = readValidToken(path);
|
|
39
54
|
if (existing) {
|
|
40
55
|
try {
|
|
@@ -51,4 +66,195 @@ export function loadOrCreateWebToken(dataDir) {
|
|
|
51
66
|
catch { /* best effort */ }
|
|
52
67
|
return token;
|
|
53
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* The token as it is on disk right now, without creating one.
|
|
71
|
+
*
|
|
72
|
+
* Deliberately unbuffered: `agend web-token rotate` writes the file from a
|
|
73
|
+
* separate process, and a cached copy would keep authorizing revoked sessions
|
|
74
|
+
* until the fleet restarted — which is the whole point of having rotation.
|
|
75
|
+
* mtime/size caching cannot be used either, since a rotation within the same
|
|
76
|
+
* millisecond produces a same-size file.
|
|
77
|
+
*/
|
|
78
|
+
export function readWebToken(dataDir) {
|
|
79
|
+
try {
|
|
80
|
+
return readValidToken(tokenPath(dataDir));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// This runs inside the request handler. A permissions or I/O error must
|
|
84
|
+
// close the panel, not throw out of the HTTP callback.
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Replace the token with a fresh one. Every previously issued URL, header token
|
|
90
|
+
* and session cookie stops being accepted as soon as the next request is served.
|
|
91
|
+
*/
|
|
92
|
+
export function rotateWebToken(dataDir) {
|
|
93
|
+
mkdirSync(dataDir, { recursive: true });
|
|
94
|
+
const path = tokenPath(dataDir);
|
|
95
|
+
const token = randomBytes(24).toString("hex");
|
|
96
|
+
replaceTokenAtomically(path, token);
|
|
97
|
+
try {
|
|
98
|
+
chmodSync(path, 0o600);
|
|
99
|
+
}
|
|
100
|
+
catch { /* best effort */ }
|
|
101
|
+
return token;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The cookie carries a derivation of the token, never the token itself: a
|
|
105
|
+
* stolen cookie opens the panel but cannot be replayed as `?token=` /
|
|
106
|
+
* `X-Agend-Token` (which also authorize /view writes and the CLI). Rotating
|
|
107
|
+
* `web.token` changes the derivation, so every issued cookie dies with it.
|
|
108
|
+
*/
|
|
109
|
+
export function webSessionCookieValue(token) {
|
|
110
|
+
return createHash("sha256").update(`agend-web-session-v1:${token}`).digest("hex");
|
|
111
|
+
}
|
|
112
|
+
function constantTimeEquals(a, b) {
|
|
113
|
+
const left = Buffer.from(a, "utf8");
|
|
114
|
+
const right = Buffer.from(b, "utf8");
|
|
115
|
+
// timingSafeEqual throws on a length mismatch, which would itself leak length.
|
|
116
|
+
if (left.length !== right.length)
|
|
117
|
+
return false;
|
|
118
|
+
return timingSafeEqual(left, right);
|
|
119
|
+
}
|
|
120
|
+
export function parseCookieHeader(header) {
|
|
121
|
+
const jar = new Map();
|
|
122
|
+
if (!header)
|
|
123
|
+
return jar;
|
|
124
|
+
for (const part of header.split(";")) {
|
|
125
|
+
const eq = part.indexOf("=");
|
|
126
|
+
if (eq < 1)
|
|
127
|
+
continue;
|
|
128
|
+
const name = part.slice(0, eq).trim();
|
|
129
|
+
if (!name || jar.has(name))
|
|
130
|
+
continue;
|
|
131
|
+
jar.set(name, part.slice(eq + 1).trim());
|
|
132
|
+
}
|
|
133
|
+
return jar;
|
|
134
|
+
}
|
|
135
|
+
function headerValue(req, name) {
|
|
136
|
+
const raw = req.headers[name];
|
|
137
|
+
if (typeof raw === "string")
|
|
138
|
+
return raw;
|
|
139
|
+
if (Array.isArray(raw))
|
|
140
|
+
return raw[0] ?? null;
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* True when the request either carries no Origin (a CLI, or a top-level GET
|
|
145
|
+
* navigation, neither of which a cross-site attacker controls) or carries one
|
|
146
|
+
* that matches the Host it was sent to.
|
|
147
|
+
*
|
|
148
|
+
* Only a *mismatch* rejects: requiring Origin would break every non-browser
|
|
149
|
+
* caller, which is the same `X-Agend-Token` path the CLI uses.
|
|
150
|
+
*/
|
|
151
|
+
export function isSameOriginRequest(req) {
|
|
152
|
+
const origin = headerValue(req, "origin");
|
|
153
|
+
if (!origin)
|
|
154
|
+
return true;
|
|
155
|
+
const host = headerValue(req, "host");
|
|
156
|
+
if (!host)
|
|
157
|
+
return false;
|
|
158
|
+
try {
|
|
159
|
+
return new URL(origin).host === host;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Anything unparseable is cross-site, including the opaque `null` origin
|
|
163
|
+
// that sandboxed frames and some redirect chains send.
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** Whether the browser reached us over TLS, which decides the cookie's Secure
|
|
168
|
+
* attribute. The health server is always plain HTTP, so the only signal is the
|
|
169
|
+
* tunnel/proxy in front of it. A forged header can only make us set Secure on a
|
|
170
|
+
* plain-HTTP response, which costs the forger their own cookie and nothing else. */
|
|
171
|
+
function isSecureRequest(req) {
|
|
172
|
+
const proto = headerValue(req, "x-forwarded-proto");
|
|
173
|
+
if (!proto)
|
|
174
|
+
return false;
|
|
175
|
+
return proto.split(",")[0].trim().toLowerCase() === "https";
|
|
176
|
+
}
|
|
177
|
+
export function buildSessionCookie(token, secure) {
|
|
178
|
+
const attrs = [
|
|
179
|
+
`${WEB_SESSION_COOKIE}=${webSessionCookieValue(token)}`,
|
|
180
|
+
"Path=/",
|
|
181
|
+
"HttpOnly",
|
|
182
|
+
// Strict, not Lax: the panel can restart instances, so a cross-site
|
|
183
|
+
// navigation must not arrive already authenticated.
|
|
184
|
+
"SameSite=Strict",
|
|
185
|
+
`Max-Age=${WEB_SESSION_MAX_AGE_SECONDS}`,
|
|
186
|
+
];
|
|
187
|
+
if (secure)
|
|
188
|
+
attrs.push("Secure");
|
|
189
|
+
return attrs.join("; ");
|
|
190
|
+
}
|
|
191
|
+
export function hasValidSessionCookie(req, token) {
|
|
192
|
+
const cookie = parseCookieHeader(headerValue(req, "cookie") ?? undefined).get(WEB_SESSION_COOKIE);
|
|
193
|
+
return !!cookie && constantTimeEquals(cookie, webSessionCookieValue(token));
|
|
194
|
+
}
|
|
195
|
+
function hasValidHeaderToken(req, token) {
|
|
196
|
+
const provided = headerValue(req, "x-agend-token");
|
|
197
|
+
return !!provided && constantTimeEquals(provided, token);
|
|
198
|
+
}
|
|
199
|
+
/** Same-origin relative target with the token stripped and every other query
|
|
200
|
+
* parameter kept. Relative on purpose: an absolute Location built from
|
|
201
|
+
* attacker-supplied Host would be an open redirect. */
|
|
202
|
+
function locationWithoutToken(url) {
|
|
203
|
+
const stripped = new URL(url.href);
|
|
204
|
+
stripped.searchParams.delete("token");
|
|
205
|
+
return `${stripped.pathname}${stripped.search}`;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The single authorization decision for every gated web route.
|
|
209
|
+
*
|
|
210
|
+
* Accepts, in order: a session cookie, an `X-Agend-Token` header (CLI and
|
|
211
|
+
* scripts), and — only to be redeemed for a cookie on a GET — a `?token=` in
|
|
212
|
+
* the URL. After the redemption the token is gone from the address bar, from
|
|
213
|
+
* browser history, and from anything that logs request URLs.
|
|
214
|
+
*/
|
|
215
|
+
export function decideWebGate(req, url, token) {
|
|
216
|
+
// No token on disk means the panel is closed, not open to everyone. Without
|
|
217
|
+
// this, a null token compared against a missing credential authorizes.
|
|
218
|
+
if (!token)
|
|
219
|
+
return { kind: "reject", status: 401, message: WEB_TOKEN_INVALID_MESSAGE };
|
|
220
|
+
if (!isSameOriginRequest(req)) {
|
|
221
|
+
return { kind: "reject", status: 403, message: WEB_CROSS_SITE_MESSAGE };
|
|
222
|
+
}
|
|
223
|
+
if (hasValidSessionCookie(req, token))
|
|
224
|
+
return { kind: "allow" };
|
|
225
|
+
if (hasValidHeaderToken(req, token))
|
|
226
|
+
return { kind: "allow" };
|
|
227
|
+
const queryToken = url.searchParams.get("token");
|
|
228
|
+
if (queryToken && constantTimeEquals(queryToken, token)) {
|
|
229
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
230
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
231
|
+
return { kind: "reject", status: 401, message: WEB_URL_TOKEN_WRITE_MESSAGE };
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
kind: "exchange",
|
|
235
|
+
setCookie: buildSessionCookie(token, isSecureRequest(req)),
|
|
236
|
+
location: locationWithoutToken(url),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const presented = queryToken ?? headerValue(req, "x-agend-token") ?? headerValue(req, "cookie");
|
|
240
|
+
return {
|
|
241
|
+
kind: "reject",
|
|
242
|
+
status: 401,
|
|
243
|
+
message: presented ? WEB_TOKEN_INVALID_MESSAGE : WEB_SESSION_REQUIRED_MESSAGE,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/** Defence in depth for handlers that run behind the gate: authorization only,
|
|
247
|
+
* no cookie issuing (the gate already did that). */
|
|
248
|
+
export function isWebRequestAuthorized(req, url, token) {
|
|
249
|
+
if (!token)
|
|
250
|
+
return false;
|
|
251
|
+
if (!isSameOriginRequest(req))
|
|
252
|
+
return false;
|
|
253
|
+
if (hasValidSessionCookie(req, token))
|
|
254
|
+
return true;
|
|
255
|
+
if (hasValidHeaderToken(req, token))
|
|
256
|
+
return true;
|
|
257
|
+
const queryToken = url.searchParams.get("token");
|
|
258
|
+
return !!queryToken && constantTimeEquals(queryToken, token);
|
|
259
|
+
}
|
|
54
260
|
//# sourceMappingURL=web-auth.js.map
|
package/dist/web-auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-auth.js","sourceRoot":"","sources":["../src/web-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"web-auth.js","sourceRoot":"","sources":["../src/web-auth.ts"],"names":[],"mappings":"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"}
|