Repository navigation
Expand file tree
/
Copy pathnativeApprovalIdentity.ts
More file actions
29 lines (27 loc) · 1.77 KB
/
Copy pathnativeApprovalIdentity.ts
File metadata and controls
29 lines (27 loc) · 1.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { constants, openSync, closeSync, fstatSync, readSync } from "node:fs";
import { verifyTrackedSessionToken } from "../auth/authApi.js";
/** Read an existing authenticated session; never mint an identity or infer a role. The token is a live credential: keep it in memory only. */
export function readNativeApprovalSession(workspace: string, tokenFile: string) {
const fd = openSync(tokenFile, constants.O_RDONLY | constants.O_NONBLOCK);
let token: string;
try {
const stat = fstatSync(fd);
if (!stat.isFile()) throw new Error("Approval session token must be a regular file");
if (process.platform !== "win32" && (stat.mode & 0o077) !== 0) throw new Error("Approval session token file must be private to its owner (0600)");
const buffer = Buffer.alloc(16_385); let offset = 0;
while (offset < buffer.length) {
const count = readSync(fd, buffer, offset, buffer.length - offset, null);
if (!count) break; offset += count;
}
if (offset === 0 || offset > 16_384) throw new Error("Approval session token file is empty or exceeds its size limit");
token = new TextDecoder("utf-8", { fatal: true }).decode(buffer.subarray(0, offset)).trim();
buffer.fill(0);
} finally { closeSync(fd); }
const verified = verifyTrackedSessionToken({ workspace, token });
if (!verified.ok || verified.payload === null) throw new Error("An active tracked workspace login is required; the approval session is missing, expired, revoked or untrusted");
return { token, payload: verified.payload };
}
export function readNativeApprovalActor(workspace: string, tokenFile: string) {
const { payload } = readNativeApprovalSession(workspace, tokenFile);
return { userId: payload.userId, username: payload.username, roles: [...payload.roles], expiresTs: payload.expiresTs };
}