latchkey 2.7.3 → 2.9.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 +55 -5
- package/dist/scripts/cryptFile.js +2 -2
- package/dist/scripts/cryptFile.js.map +1 -1
- package/dist/scripts/recordBrowserSession.js +3 -2
- package/dist/scripts/recordBrowserSession.js.map +1 -1
- package/dist/src/cli.js +5 -4
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts +1 -1
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +44 -6
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/config.d.ts +34 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +53 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/curlInjection.d.ts +1 -1
- package/dist/src/curlInjection.d.ts.map +1 -1
- package/dist/src/curlInjection.js +16 -1
- package/dist/src/curlInjection.js.map +1 -1
- package/dist/src/encryptedStorage.d.ts +9 -25
- package/dist/src/encryptedStorage.d.ts.map +1 -1
- package/dist/src/encryptedStorage.js +9 -52
- package/dist/src/encryptedStorage.js.map +1 -1
- package/dist/src/encryption.d.ts +45 -0
- package/dist/src/encryption.d.ts.map +1 -1
- package/dist/src/encryption.js +69 -0
- package/dist/src/encryption.js.map +1 -1
- package/dist/src/gateway/client.d.ts +12 -2
- package/dist/src/gateway/client.d.ts.map +1 -1
- package/dist/src/gateway/client.js +31 -4
- package/dist/src/gateway/client.js.map +1 -1
- package/dist/src/gateway/extensions.d.ts +59 -0
- package/dist/src/gateway/extensions.d.ts.map +1 -0
- package/dist/src/gateway/extensions.js +170 -0
- package/dist/src/gateway/extensions.js.map +1 -0
- package/dist/src/gateway/gatewayEndpoint.d.ts +22 -1
- package/dist/src/gateway/gatewayEndpoint.d.ts.map +1 -1
- package/dist/src/gateway/gatewayEndpoint.js +52 -15
- package/dist/src/gateway/gatewayEndpoint.js.map +1 -1
- package/dist/src/gateway/password.d.ts +16 -0
- package/dist/src/gateway/password.d.ts.map +1 -0
- package/dist/src/gateway/password.js +24 -0
- package/dist/src/gateway/password.js.map +1 -0
- package/dist/src/gateway/permissionsOverride.d.ts +65 -0
- package/dist/src/gateway/permissionsOverride.d.ts.map +1 -0
- package/dist/src/gateway/permissionsOverride.js +171 -0
- package/dist/src/gateway/permissionsOverride.js.map +1 -0
- package/dist/src/gateway/server.d.ts.map +1 -1
- package/dist/src/gateway/server.js +100 -15
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/oauthUtils.d.ts +11 -2
- package/dist/src/oauthUtils.d.ts.map +1 -1
- package/dist/src/oauthUtils.js +25 -4
- package/dist/src/oauthUtils.js.map +1 -1
- package/dist/src/permissions.d.ts +3 -6
- package/dist/src/permissions.d.ts.map +1 -1
- package/dist/src/permissions.js +6 -13
- package/dist/src/permissions.js.map +1 -1
- package/dist/src/serviceRegistry.d.ts.map +1 -1
- package/dist/src/serviceRegistry.js +2 -1
- package/dist/src/serviceRegistry.js.map +1 -1
- package/dist/src/services/index.d.ts +1 -0
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +1 -0
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/notion-mcp.d.ts +29 -0
- package/dist/src/services/notion-mcp.d.ts.map +1 -0
- package/dist/src/services/notion-mcp.js +156 -0
- package/dist/src/services/notion-mcp.js.map +1 -0
- package/dist/src/services/notion.d.ts.map +1 -1
- package/dist/src/services/notion.js +3 -2
- package/dist/src/services/notion.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tests/apiCredentialStore.test.js +2 -2
- package/dist/tests/apiCredentialStore.test.js.map +1 -1
- package/dist/tests/cli.test.js +98 -53
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/config.test.js +37 -0
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/encryptedStorage.test.js +19 -39
- package/dist/tests/encryptedStorage.test.js.map +1 -1
- package/dist/tests/gateway.test.js +184 -7
- package/dist/tests/gateway.test.js.map +1 -1
- package/dist/tests/gatewayClient.test.js +74 -0
- package/dist/tests/gatewayClient.test.js.map +1 -1
- package/dist/tests/gatewayExtensions.test.d.ts +2 -0
- package/dist/tests/gatewayExtensions.test.d.ts.map +1 -0
- package/dist/tests/gatewayExtensions.test.js +398 -0
- package/dist/tests/gatewayExtensions.test.js.map +1 -0
- package/dist/tests/latchkeyEndpoint.test.js +7 -6
- package/dist/tests/latchkeyEndpoint.test.js.map +1 -1
- package/dist/tests/migrations.test.js +2 -2
- package/dist/tests/migrations.test.js.map +1 -1
- package/dist/tests/oauthUtils.test.d.ts +2 -0
- package/dist/tests/oauthUtils.test.d.ts.map +1 -0
- package/dist/tests/oauthUtils.test.js +63 -0
- package/dist/tests/oauthUtils.test.js.map +1 -0
- package/dist/tests/permissions.test.js +14 -10
- package/dist/tests/permissions.test.js.map +1 -1
- package/dist/tests/permissionsOverride.test.d.ts +2 -0
- package/dist/tests/permissionsOverride.test.d.ts.map +1 -0
- package/dist/tests/permissionsOverride.test.js +136 -0
- package/dist/tests/permissionsOverride.test.js.map +1 -0
- package/dist/tests/resolveEncryptionKey.test.d.ts +2 -0
- package/dist/tests/resolveEncryptionKey.test.d.ts.map +1 -0
- package/dist/tests/resolveEncryptionKey.test.js +26 -0
- package/dist/tests/resolveEncryptionKey.test.js.map +1 -0
- package/dist/tests/sharedOperations.test.js +34 -50
- package/dist/tests/sharedOperations.test.js.map +1 -1
- package/package.json +2 -2
- package/dist/tests/encryptedStorageKeyGeneration.test.d.ts +0 -2
- package/dist/tests/encryptedStorageKeyGeneration.test.d.ts.map +0 -1
- package/dist/tests/encryptedStorageKeyGeneration.test.js +0 -22
- package/dist/tests/encryptedStorageKeyGeneration.test.js.map +0 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional `x-latchkey-gateway-permissions-override` header support.
|
|
3
|
+
*
|
|
4
|
+
* The header carries a minimal HS256 JWT whose only payload field is
|
|
5
|
+
* `permissionsConfig`, an absolute path to a `permissions.json` file.
|
|
6
|
+
* When the gateway receives such a header on a `/gateway/...` request and
|
|
7
|
+
* the JWT is valid, it uses the referenced permissions config instead of
|
|
8
|
+
* the default one for that single request.
|
|
9
|
+
*
|
|
10
|
+
* The signing key is derived from the Latchkey encryption key via HKDF-like
|
|
11
|
+
* HMAC-SHA256 with a domain-separation label, so the encryption key itself
|
|
12
|
+
* is never used to sign or verify these JWTs directly.
|
|
13
|
+
*/
|
|
14
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
15
|
+
import { existsSync, statSync } from 'node:fs';
|
|
16
|
+
import { isAbsolute } from 'node:path';
|
|
17
|
+
/**
|
|
18
|
+
* HTTP header used to carry the permissions-override JWT. Lowercased to match
|
|
19
|
+
* how Node's `http.IncomingMessage.headers` exposes header names.
|
|
20
|
+
*/
|
|
21
|
+
export const PERMISSIONS_OVERRIDE_HEADER = 'x-latchkey-gateway-permissions-override';
|
|
22
|
+
/**
|
|
23
|
+
* Domain-separation label mixed into the HMAC that derives the JWT signing
|
|
24
|
+
* key from the Latchkey encryption key. Changing this value invalidates all
|
|
25
|
+
* previously issued tokens.
|
|
26
|
+
*/
|
|
27
|
+
const SIGNING_KEY_DERIVATION_LABEL = 'latchkey:gateway:permissions-override:v1';
|
|
28
|
+
const JWT_HEADER = { alg: 'HS256', typ: 'JWT' };
|
|
29
|
+
const JWT_HEADER_ENCODED = Buffer.from(JSON.stringify(JWT_HEADER), 'utf-8').toString('base64url');
|
|
30
|
+
export class InvalidPermissionsOverrideError extends Error {
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(`Latchkey: ${message}`);
|
|
33
|
+
this.name = 'InvalidPermissionsOverrideError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class PermissionsOverrideFileMissingError extends Error {
|
|
37
|
+
constructor(filePath) {
|
|
38
|
+
super(`Permissions override references missing or invalid file: ${filePath}`);
|
|
39
|
+
this.name = 'PermissionsOverrideFileMissingError';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Derive the HS256 signing key used for permissions-override JWTs from the
|
|
44
|
+
* Latchkey encryption key. The encryption key is base64-encoded; the
|
|
45
|
+
* derived key is the raw HMAC-SHA256 output (32 bytes).
|
|
46
|
+
*/
|
|
47
|
+
export function derivePermissionsOverrideSigningKey(encryptionKeyBase64) {
|
|
48
|
+
const masterKey = Buffer.from(encryptionKeyBase64, 'base64');
|
|
49
|
+
return createHmac('sha256', masterKey).update(SIGNING_KEY_DERIVATION_LABEL).digest();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a permissions-override JWT for the given absolute path. The path is
|
|
53
|
+
* not validated here; callers that want to ensure the file exists must do
|
|
54
|
+
* so before calling this function.
|
|
55
|
+
*/
|
|
56
|
+
export function createPermissionsOverrideJwt(permissionsConfigPath, signingKey) {
|
|
57
|
+
if (!isAbsolute(permissionsConfigPath)) {
|
|
58
|
+
throw new InvalidPermissionsOverrideError(`permissionsConfig path must be absolute: ${permissionsConfigPath}`);
|
|
59
|
+
}
|
|
60
|
+
const payload = { permissionsConfig: permissionsConfigPath };
|
|
61
|
+
const payloadEncoded = Buffer.from(JSON.stringify(payload), 'utf-8').toString('base64url');
|
|
62
|
+
const signingInput = `${JWT_HEADER_ENCODED}.${payloadEncoded}`;
|
|
63
|
+
const signature = createHmac('sha256', signingKey).update(signingInput).digest('base64url');
|
|
64
|
+
return `${signingInput}.${signature}`;
|
|
65
|
+
}
|
|
66
|
+
function parsePayload(payloadEncoded) {
|
|
67
|
+
let payloadJson;
|
|
68
|
+
try {
|
|
69
|
+
payloadJson = Buffer.from(payloadEncoded, 'base64url').toString('utf-8');
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
throw new InvalidPermissionsOverrideError('Permissions override payload is not valid base64url.');
|
|
73
|
+
}
|
|
74
|
+
let payload;
|
|
75
|
+
try {
|
|
76
|
+
payload = JSON.parse(payloadJson);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new InvalidPermissionsOverrideError('Permissions override payload is not valid JSON.');
|
|
80
|
+
}
|
|
81
|
+
if (typeof payload !== 'object' ||
|
|
82
|
+
payload === null ||
|
|
83
|
+
!('permissionsConfig' in payload) ||
|
|
84
|
+
typeof payload.permissionsConfig !== 'string') {
|
|
85
|
+
throw new InvalidPermissionsOverrideError("Permissions override payload must contain a string 'permissionsConfig' field.");
|
|
86
|
+
}
|
|
87
|
+
const permissionsConfig = payload.permissionsConfig;
|
|
88
|
+
if (!isAbsolute(permissionsConfig)) {
|
|
89
|
+
throw new InvalidPermissionsOverrideError(`Permissions override 'permissionsConfig' must be an absolute path: ${permissionsConfig}`);
|
|
90
|
+
}
|
|
91
|
+
return { permissionsConfig };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Verify a permissions-override JWT and return its payload. Throws
|
|
95
|
+
* `InvalidPermissionsOverrideError` on any structural, signature, or content
|
|
96
|
+
* issue (i.e. anything that should be reported as "the JWT is invalid").
|
|
97
|
+
*
|
|
98
|
+
* This intentionally does not check that the referenced file exists; that
|
|
99
|
+
* concern is handled by `resolvePermissionsOverride` so that file-system
|
|
100
|
+
* errors can be reported separately from JWT errors.
|
|
101
|
+
*/
|
|
102
|
+
export function verifyPermissionsOverrideJwt(token, signingKey) {
|
|
103
|
+
const segments = token.split('.');
|
|
104
|
+
if (segments.length !== 3) {
|
|
105
|
+
throw new InvalidPermissionsOverrideError('Permissions override JWT must have three dot-separated segments.');
|
|
106
|
+
}
|
|
107
|
+
const headerEncoded = segments[0];
|
|
108
|
+
const payloadEncoded = segments[1];
|
|
109
|
+
const signatureEncoded = segments[2];
|
|
110
|
+
let headerJson;
|
|
111
|
+
try {
|
|
112
|
+
headerJson = Buffer.from(headerEncoded, 'base64url').toString('utf-8');
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new InvalidPermissionsOverrideError('Permissions override header is not valid base64url.');
|
|
116
|
+
}
|
|
117
|
+
let header;
|
|
118
|
+
try {
|
|
119
|
+
header = JSON.parse(headerJson);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
throw new InvalidPermissionsOverrideError('Permissions override header is not valid JSON.');
|
|
123
|
+
}
|
|
124
|
+
if (typeof header !== 'object' ||
|
|
125
|
+
header === null ||
|
|
126
|
+
header.alg !== 'HS256' ||
|
|
127
|
+
header.typ !== 'JWT') {
|
|
128
|
+
throw new InvalidPermissionsOverrideError("Permissions override header must declare alg='HS256' and typ='JWT'.");
|
|
129
|
+
}
|
|
130
|
+
let providedSignature;
|
|
131
|
+
try {
|
|
132
|
+
providedSignature = Buffer.from(signatureEncoded, 'base64url');
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
throw new InvalidPermissionsOverrideError('Permissions override signature is not valid base64url.');
|
|
136
|
+
}
|
|
137
|
+
const expectedSignature = createHmac('sha256', signingKey)
|
|
138
|
+
.update(`${headerEncoded}.${payloadEncoded}`)
|
|
139
|
+
.digest();
|
|
140
|
+
if (providedSignature.length !== expectedSignature.length ||
|
|
141
|
+
!timingSafeEqual(providedSignature, expectedSignature)) {
|
|
142
|
+
throw new InvalidPermissionsOverrideError('Permissions override signature is invalid.');
|
|
143
|
+
}
|
|
144
|
+
return parsePayload(payloadEncoded);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Verify a permissions-override JWT and additionally require the referenced
|
|
148
|
+
* file to exist as a regular file. Returns the absolute path on success.
|
|
149
|
+
*/
|
|
150
|
+
export function resolvePermissionsOverride(token, signingKey) {
|
|
151
|
+
const { permissionsConfig } = verifyPermissionsOverrideJwt(token, signingKey);
|
|
152
|
+
if (!existsSync(permissionsConfig) || !statSync(permissionsConfig).isFile()) {
|
|
153
|
+
throw new PermissionsOverrideFileMissingError(permissionsConfig);
|
|
154
|
+
}
|
|
155
|
+
return permissionsConfig;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Apply the optional `X-Latchkey-Gateway-Permissions-Override` header to a
|
|
159
|
+
* request: when absent, return the default config path; when present,
|
|
160
|
+
* validate the JWT and return the referenced path. Throws
|
|
161
|
+
* `InvalidPermissionsOverrideError` (=> 401) or
|
|
162
|
+
* `PermissionsOverrideFileMissingError` (=> 400) on invalid input.
|
|
163
|
+
*/
|
|
164
|
+
export function resolveRequestPermissionsConfig(headers, defaultConfigPath, signingKey) {
|
|
165
|
+
const headerValue = headers[PERMISSIONS_OVERRIDE_HEADER];
|
|
166
|
+
const token = typeof headerValue === 'string' ? headerValue : undefined;
|
|
167
|
+
if (token === undefined)
|
|
168
|
+
return defaultConfigPath;
|
|
169
|
+
return resolvePermissionsOverride(token, signingKey);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=permissionsOverride.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionsOverride.js","sourceRoot":"","sources":["../../../src/gateway/permissionsOverride.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/gateway/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/gateway/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAoD9B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAkDD;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,eAAe,EACrB,kBAAkB,EAAE,kBAAkB,EACtC,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA+HxB"}
|
|
@@ -8,19 +8,89 @@ import * as http from 'node:http';
|
|
|
8
8
|
import { ErrorMessages } from '../errorMessages.js';
|
|
9
9
|
import { extractTargetUrl, GATEWAY_PATH_PREFIX, handleGatewayRequest, } from './gatewayEndpoint.js';
|
|
10
10
|
import { handleLatchkeyRequest } from './latchkeyEndpoint.js';
|
|
11
|
+
import { GATEWAY_PASSWORD_HEADER, passwordsMatch } from './password.js';
|
|
12
|
+
import { dispatchExtensionRequest, loadExtensions } from './extensions.js';
|
|
13
|
+
import { InvalidPermissionsOverrideError, PermissionsOverrideFileMissingError, resolveRequestPermissionsConfig, } from './permissionsOverride.js';
|
|
11
14
|
function sendErrorResponse(response, statusCode, message) {
|
|
12
15
|
response.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
13
16
|
response.end(JSON.stringify({ error: message }));
|
|
14
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Read a single header value, treating arrays (which Node returns for some
|
|
20
|
+
* headers) as missing because the password header is not allowed to repeat.
|
|
21
|
+
*/
|
|
22
|
+
function readSingleHeader(request, headerName) {
|
|
23
|
+
const value = request.headers[headerName];
|
|
24
|
+
if (typeof value === 'string')
|
|
25
|
+
return value;
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* If a password is configured, verify that the request presents it in the
|
|
30
|
+
* expected header. Returns true when the request should be allowed to
|
|
31
|
+
* proceed, and writes a 401 response and returns false otherwise.
|
|
32
|
+
*/
|
|
33
|
+
function enforcePassword(request, response, expectedPassword, deps) {
|
|
34
|
+
if (expectedPassword === null)
|
|
35
|
+
return true;
|
|
36
|
+
const provided = readSingleHeader(request, GATEWAY_PASSWORD_HEADER);
|
|
37
|
+
if (provided !== undefined && passwordsMatch(expectedPassword, provided)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const method = request.method ?? 'UNKNOWN';
|
|
41
|
+
const path = request.url ?? '';
|
|
42
|
+
deps.log(`${method} ${path} -> 401 (password)`);
|
|
43
|
+
sendErrorResponse(response, 401, 'Unauthorized: invalid or missing Latchkey gateway password.');
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run an inbound request through the loaded extensions. Resolves to true when
|
|
48
|
+
* the request has been handled in some way and false if not.
|
|
49
|
+
*/
|
|
50
|
+
function runExtensions(request, response, extensions, deps, options) {
|
|
51
|
+
if (extensions.length === 0)
|
|
52
|
+
return Promise.resolve(false);
|
|
53
|
+
const rawUrl = request.url ?? '';
|
|
54
|
+
const method = (request.method ?? 'GET').toUpperCase();
|
|
55
|
+
let permissionsConfigPath;
|
|
56
|
+
try {
|
|
57
|
+
permissionsConfigPath = resolveRequestPermissionsConfig(request.headers, deps.config.permissionsConfigPath, options.permissionsOverrideSigningKey);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error instanceof InvalidPermissionsOverrideError) {
|
|
61
|
+
deps.log(`${method} ${rawUrl} -> 401 (extension)`);
|
|
62
|
+
sendErrorResponse(response, 401, error.message);
|
|
63
|
+
return Promise.resolve(true);
|
|
64
|
+
}
|
|
65
|
+
if (error instanceof PermissionsOverrideFileMissingError) {
|
|
66
|
+
deps.log(`${method} ${rawUrl} -> 400 (extension)`);
|
|
67
|
+
sendErrorResponse(response, 400, error.message);
|
|
68
|
+
return Promise.resolve(true);
|
|
69
|
+
}
|
|
70
|
+
// resolveRequestPermissionsConfig only throws the two known error
|
|
71
|
+
// types, so this branch is just defensive: an http.Server request
|
|
72
|
+
// listener is sync, and rethrowing here would crash the process.
|
|
73
|
+
deps.errorLog(`Unexpected error resolving permissions override for ${method} ${rawUrl}: ` +
|
|
74
|
+
(error instanceof Error ? error.message : String(error)));
|
|
75
|
+
sendErrorResponse(response, 500, 'Internal error');
|
|
76
|
+
return Promise.resolve(true);
|
|
77
|
+
}
|
|
78
|
+
return dispatchExtensionRequest(request, response, extensions, deps, permissionsConfigPath);
|
|
79
|
+
}
|
|
15
80
|
/**
|
|
16
81
|
* Start the gateway HTTP server.
|
|
17
82
|
*/
|
|
18
|
-
export function startGateway(deps, apiCredentialStore, encryptedStorage, options) {
|
|
83
|
+
export async function startGateway(deps, apiCredentialStore, encryptedStorage, options) {
|
|
19
84
|
const inFlightRequests = new Set();
|
|
85
|
+
const extensions = await loadExtensions(deps.config.extensionsDirectoryPath);
|
|
20
86
|
const server = http.createServer((request, response) => {
|
|
21
87
|
const rawUrl = request.url ?? '';
|
|
88
|
+
const method = request.method ?? 'UNKNOWN';
|
|
89
|
+
if (!enforcePassword(request, response, options.password, deps)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
22
92
|
// Health endpoint
|
|
23
|
-
if (rawUrl === '/' &&
|
|
93
|
+
if (rawUrl === '/' && method === 'GET') {
|
|
24
94
|
response.writeHead(200, { 'Content-Type': 'application/json' });
|
|
25
95
|
response.end(JSON.stringify({ status: 'ok', version: deps.version }));
|
|
26
96
|
return;
|
|
@@ -39,25 +109,39 @@ export function startGateway(deps, apiCredentialStore, encryptedStorage, options
|
|
|
39
109
|
});
|
|
40
110
|
return;
|
|
41
111
|
}
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
const method = request.method ?? 'UNKNOWN';
|
|
112
|
+
// Gateway proxy endpoint
|
|
113
|
+
if (rawUrl.startsWith(GATEWAY_PATH_PREFIX)) {
|
|
114
|
+
const targetUrl = extractTargetUrl(rawUrl);
|
|
115
|
+
if (targetUrl === null) {
|
|
47
116
|
deps.log(`${method} ${rawUrl.slice(GATEWAY_PATH_PREFIX.length)} -> 400`);
|
|
48
117
|
sendErrorResponse(response, 400, ErrorMessages.couldNotExtractUrl);
|
|
118
|
+
return;
|
|
49
119
|
}
|
|
50
|
-
|
|
120
|
+
const requestPromise = handleGatewayRequest(request, response, targetUrl, deps, apiCredentialStore, options).catch((error) => {
|
|
121
|
+
deps.errorLog(`Unexpected error handling ${method} ${targetUrl}: ${error instanceof Error ? error.message : String(error)}`);
|
|
122
|
+
if (!response.headersSent) {
|
|
123
|
+
sendErrorResponse(response, 502, ErrorMessages.upstreamRequestFailed);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
inFlightRequests.add(requestPromise);
|
|
127
|
+
void requestPromise.finally(() => {
|
|
128
|
+
inFlightRequests.delete(requestPromise);
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// Finally, try extensions (if any).
|
|
133
|
+
const requestPromise = runExtensions(request, response, extensions, deps, options)
|
|
134
|
+
.then((handled) => {
|
|
135
|
+
if (!handled && !response.headersSent) {
|
|
51
136
|
response.writeHead(404);
|
|
52
137
|
response.end();
|
|
53
138
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
deps.errorLog(`Unexpected error handling ${method} ${targetUrl}: ${error instanceof Error ? error.message : String(error)}`);
|
|
139
|
+
})
|
|
140
|
+
.catch((error) => {
|
|
141
|
+
deps.errorLog(`Unexpected error handling extension request ${method} ${rawUrl}: ` +
|
|
142
|
+
(error instanceof Error ? error.message : String(error)));
|
|
59
143
|
if (!response.headersSent) {
|
|
60
|
-
sendErrorResponse(response,
|
|
144
|
+
sendErrorResponse(response, 500, 'Internal error');
|
|
61
145
|
}
|
|
62
146
|
});
|
|
63
147
|
inFlightRequests.add(requestPromise);
|
|
@@ -82,7 +166,8 @@ export function startGateway(deps, apiCredentialStore, encryptedStorage, options
|
|
|
82
166
|
return new Promise((resolve, reject) => {
|
|
83
167
|
server.on('error', reject);
|
|
84
168
|
server.listen(options.port, options.host, () => {
|
|
85
|
-
|
|
169
|
+
const passwordNote = options.password === null ? '' : ' (password authentication enabled)';
|
|
170
|
+
deps.log(`Latchkey gateway listening on ${options.host}:${String(options.port)}${passwordNote}`);
|
|
86
171
|
resolve({ server, close });
|
|
87
172
|
});
|
|
88
173
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/gateway/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/gateway/server.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ export { deserializeCredentials, serializeCredentials } from './apiCredentials/s
|
|
|
6
6
|
export { SlackApiCredentials } from './services/slack.js';
|
|
7
7
|
export { ApiCredentialStore, ApiCredentialStoreError } from './apiCredentials/store.js';
|
|
8
8
|
export { Config, CONFIG, InsecureFilePermissionsError } from './config.js';
|
|
9
|
-
export { encrypt, decrypt, generateKey, EncryptionError, DecryptionError } from './encryption.js';
|
|
10
|
-
export { EncryptedStorage, EncryptedStorageError
|
|
9
|
+
export { encrypt, decrypt, generateKey, resolveEncryptionKey, EncryptionError, DecryptionError, EncryptionKeyError, EncryptionKeyLostError, EncryptionKeyUnavailableError, } from './encryption.js';
|
|
10
|
+
export { EncryptedStorage, EncryptedStorageError } from './encryptedStorage.js';
|
|
11
11
|
export { storeInKeychain, retrieveFromKeychain, deleteFromKeychain, KeychainError, KeychainNotAvailableError, KeychainTimeoutError, } from './keychain.js';
|
|
12
12
|
export { run as runCurl, runCaptured as runCurlCaptured, setSubprocessRunner, resetSubprocessRunner, setCapturingSubprocessRunner, resetCapturingSubprocessRunner, } from './curl.js';
|
|
13
13
|
export { typeLikeHuman, BrowserDisabledError, BrowserFlowsNotSupportedError, } from './playwrightUtils.js';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAExF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAExF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EACL,OAAO,EACP,OAAO,EACP,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,GAAG,IAAI,OAAO,EACd,WAAW,IAAI,eAAe,EAC9B,mBAAmB,EACnB,qBAAqB,EACrB,4BAA4B,EAC5B,8BAA8B,GAC/B,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,OAAO,EACP,cAAc,EACd,oBAAoB,EACpB,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,EACL,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,GACP,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -7,8 +7,8 @@ export { deserializeCredentials, serializeCredentials } from './apiCredentials/s
|
|
|
7
7
|
export { SlackApiCredentials } from './services/slack.js';
|
|
8
8
|
export { ApiCredentialStore, ApiCredentialStoreError } from './apiCredentials/store.js';
|
|
9
9
|
export { Config, CONFIG, InsecureFilePermissionsError } from './config.js';
|
|
10
|
-
export { encrypt, decrypt, generateKey, EncryptionError, DecryptionError } from './encryption.js';
|
|
11
|
-
export { EncryptedStorage, EncryptedStorageError
|
|
10
|
+
export { encrypt, decrypt, generateKey, resolveEncryptionKey, EncryptionError, DecryptionError, EncryptionKeyError, EncryptionKeyLostError, EncryptionKeyUnavailableError, } from './encryption.js';
|
|
11
|
+
export { EncryptedStorage, EncryptedStorageError } from './encryptedStorage.js';
|
|
12
12
|
export { storeInKeychain, retrieveFromKeychain, deleteFromKeychain, KeychainError, KeychainNotAvailableError, KeychainTimeoutError, } from './keychain.js';
|
|
13
13
|
export { run as runCurl, runCaptured as runCurlCaptured, setSubprocessRunner, resetSubprocessRunner, setCapturingSubprocessRunner, resetCapturingSubprocessRunner, } from './curl.js';
|
|
14
14
|
export { typeLikeHuman, BrowserDisabledError, BrowserFlowsNotSupportedError, } from './playwrightUtils.js';
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2BAA2B;AAC3B,OAAO,EAEL,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAExF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2BAA2B;AAC3B,OAAO,EAEL,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAExF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EACL,OAAO,EACP,OAAO,EACP,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,GAAG,IAAI,OAAO,EACd,WAAW,IAAI,eAAe,EAC9B,mBAAmB,EACnB,qBAAqB,EACrB,4BAA4B,EAC5B,8BAA8B,GAC/B,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC;AAE9B,WAAW;AACX,OAAO,EACL,OAAO,EACP,cAAc,EACd,oBAAoB,EACpB,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,EACL,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,MAAM,GACP,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/src/oauthUtils.d.ts
CHANGED
|
@@ -31,15 +31,24 @@ export interface OAuthCallbackServer {
|
|
|
31
31
|
* @param callbackPath - Path to listen for OAuth callback (default: '/oauth2callback')
|
|
32
32
|
*/
|
|
33
33
|
export declare function startOAuthCallbackServer(timeoutMs: number, signal?: AbortSignal, callbackPath?: string): Promise<OAuthCallbackServer>;
|
|
34
|
+
/**
|
|
35
|
+
* Generate a PKCE code verifier (RFC 7636).
|
|
36
|
+
*/
|
|
37
|
+
export declare function generateCodeVerifier(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Generate a PKCE code challenge from a verifier using S256.
|
|
40
|
+
*/
|
|
41
|
+
export declare function generateCodeChallenge(verifier: string): string;
|
|
34
42
|
/**
|
|
35
43
|
* Exchange authorization code for access and refresh tokens.
|
|
36
44
|
* @param tokenEndpoint - The OAuth token endpoint URL
|
|
37
45
|
* @param code - The authorization code received from the OAuth callback
|
|
38
46
|
* @param clientId - The OAuth client ID
|
|
39
|
-
* @param clientSecret - The OAuth client secret
|
|
47
|
+
* @param clientSecret - The OAuth client secret (empty string for public clients)
|
|
40
48
|
* @param redirectUri - The redirect URI used in the authorization request
|
|
49
|
+
* @param codeVerifier - Optional PKCE code verifier
|
|
41
50
|
*/
|
|
42
|
-
export declare function exchangeCodeForTokens(tokenEndpoint: string, code: string, clientId: string, clientSecret: string, redirectUri: string): OAuthTokenExchangeResponse;
|
|
51
|
+
export declare function exchangeCodeForTokens(tokenEndpoint: string, code: string, clientId: string, clientSecret: string, redirectUri: string, codeVerifier?: string): OAuthTokenExchangeResponse;
|
|
43
52
|
/**
|
|
44
53
|
* Refresh OAuth access token using the refresh token.
|
|
45
54
|
* @param tokenEndpoint - The OAuth token endpoint URL
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthUtils.d.ts","sourceRoot":"","sources":["../../src/oauthUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"oauthUtils.d.ts","sourceRoot":"","sources":["../../src/oauthUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,+BAAgC,SAAQ,KAAK;;CAKzD;AAED,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,EACpB,YAAY,SAAoB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAmF9B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,0BAA0B,CAgD5B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,kBAAkB,GAAG,IAAI,CAqC3B"}
|
package/dist/src/oauthUtils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generic OAuth utilities for localhost callback server and token exchange.
|
|
3
3
|
*/
|
|
4
|
+
import * as crypto from 'node:crypto';
|
|
4
5
|
import * as http from 'node:http';
|
|
5
6
|
import { runCaptured } from './curl.js';
|
|
6
7
|
import { LoginCancelledError, LoginFailedError } from './services/core/base.js';
|
|
@@ -98,22 +99,40 @@ export function startOAuthCallbackServer(timeoutMs, signal, callbackPath = '/oau
|
|
|
98
99
|
});
|
|
99
100
|
});
|
|
100
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Generate a PKCE code verifier (RFC 7636).
|
|
104
|
+
*/
|
|
105
|
+
export function generateCodeVerifier() {
|
|
106
|
+
return crypto.randomBytes(32).toString('base64url');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Generate a PKCE code challenge from a verifier using S256.
|
|
110
|
+
*/
|
|
111
|
+
export function generateCodeChallenge(verifier) {
|
|
112
|
+
return crypto.createHash('sha256').update(verifier).digest('base64url');
|
|
113
|
+
}
|
|
101
114
|
/**
|
|
102
115
|
* Exchange authorization code for access and refresh tokens.
|
|
103
116
|
* @param tokenEndpoint - The OAuth token endpoint URL
|
|
104
117
|
* @param code - The authorization code received from the OAuth callback
|
|
105
118
|
* @param clientId - The OAuth client ID
|
|
106
|
-
* @param clientSecret - The OAuth client secret
|
|
119
|
+
* @param clientSecret - The OAuth client secret (empty string for public clients)
|
|
107
120
|
* @param redirectUri - The redirect URI used in the authorization request
|
|
121
|
+
* @param codeVerifier - Optional PKCE code verifier
|
|
108
122
|
*/
|
|
109
|
-
export function exchangeCodeForTokens(tokenEndpoint, code, clientId, clientSecret, redirectUri) {
|
|
123
|
+
export function exchangeCodeForTokens(tokenEndpoint, code, clientId, clientSecret, redirectUri, codeVerifier) {
|
|
110
124
|
const body = new URLSearchParams({
|
|
111
125
|
code,
|
|
112
126
|
client_id: clientId,
|
|
113
|
-
client_secret: clientSecret,
|
|
114
127
|
redirect_uri: redirectUri,
|
|
115
128
|
grant_type: 'authorization_code',
|
|
116
129
|
});
|
|
130
|
+
if (clientSecret) {
|
|
131
|
+
body.set('client_secret', clientSecret);
|
|
132
|
+
}
|
|
133
|
+
if (codeVerifier) {
|
|
134
|
+
body.set('code_verifier', codeVerifier);
|
|
135
|
+
}
|
|
117
136
|
const result = runCaptured([
|
|
118
137
|
'-s',
|
|
119
138
|
'-X',
|
|
@@ -153,9 +172,11 @@ export function refreshAccessToken(tokenEndpoint, refreshToken, clientId, client
|
|
|
153
172
|
const body = new URLSearchParams({
|
|
154
173
|
refresh_token: refreshToken,
|
|
155
174
|
client_id: clientId,
|
|
156
|
-
client_secret: clientSecret,
|
|
157
175
|
grant_type: 'refresh_token',
|
|
158
176
|
});
|
|
177
|
+
if (clientSecret) {
|
|
178
|
+
body.set('client_secret', clientSecret);
|
|
179
|
+
}
|
|
159
180
|
const result = runCaptured([
|
|
160
181
|
'-s',
|
|
161
182
|
'-X',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthUtils.js","sourceRoot":"","sources":["../../src/oauthUtils.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"oauthUtils.js","sourceRoot":"","sources":["../../src/oauthUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Permission checking for outgoing HTTP requests based on the
|
|
3
3
|
* Detent library.
|
|
4
|
-
*
|
|
5
|
-
* When a permissions config file exists, outgoing curl requests are checked
|
|
6
|
-
* against the user's permission rules before being sent.
|
|
7
4
|
*/
|
|
8
5
|
export declare class PermissionCheckError extends Error {
|
|
9
6
|
constructor(message: string);
|
|
10
7
|
}
|
|
11
8
|
/**
|
|
12
|
-
* Check whether a
|
|
9
|
+
* Check whether a request is allowed by permission rules.
|
|
13
10
|
*
|
|
14
11
|
* When no permissions config file is present at the given path, the check is
|
|
15
12
|
* skipped (returns true). When a config exists, the request is validated
|
|
16
13
|
* against its rules.
|
|
17
14
|
*
|
|
18
|
-
* @param
|
|
15
|
+
* @param request - The request to check.
|
|
19
16
|
* @param configPath - Path to the permissions config file.
|
|
20
17
|
* @param doNotUseBuiltinSchemas - When true, detent's built-in schemas are not used.
|
|
21
18
|
* @returns true if the request is allowed (or no config exists), false if denied.
|
|
22
19
|
* @throws PermissionCheckError if parsing or checking fails unexpectedly.
|
|
23
20
|
*/
|
|
24
|
-
export declare function checkPermission(
|
|
21
|
+
export declare function checkPermission(request: Request, configPath: string, doNotUseBuiltinSchemas?: boolean): Promise<boolean>;
|
|
25
22
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/permissions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/permissions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,EAClB,sBAAsB,UAAQ,GAC7B,OAAO,CAAC,OAAO,CAAC,CAalB"}
|
package/dist/src/permissions.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Permission checking for outgoing HTTP requests based on the
|
|
3
3
|
* Detent library.
|
|
4
|
-
*
|
|
5
|
-
* When a permissions config file exists, outgoing curl requests are checked
|
|
6
|
-
* against the user's permission rules before being sent.
|
|
7
4
|
*/
|
|
8
5
|
import { existsSync } from 'node:fs';
|
|
9
|
-
import { check,
|
|
6
|
+
import { check, ConfigError, RequestSchemaError } from '@imbue-ai/detent';
|
|
10
7
|
export class PermissionCheckError extends Error {
|
|
11
8
|
constructor(message) {
|
|
12
9
|
super(message);
|
|
@@ -14,31 +11,27 @@ export class PermissionCheckError extends Error {
|
|
|
14
11
|
}
|
|
15
12
|
}
|
|
16
13
|
/**
|
|
17
|
-
* Check whether a
|
|
14
|
+
* Check whether a request is allowed by permission rules.
|
|
18
15
|
*
|
|
19
16
|
* When no permissions config file is present at the given path, the check is
|
|
20
17
|
* skipped (returns true). When a config exists, the request is validated
|
|
21
18
|
* against its rules.
|
|
22
19
|
*
|
|
23
|
-
* @param
|
|
20
|
+
* @param request - The request to check.
|
|
24
21
|
* @param configPath - Path to the permissions config file.
|
|
25
22
|
* @param doNotUseBuiltinSchemas - When true, detent's built-in schemas are not used.
|
|
26
23
|
* @returns true if the request is allowed (or no config exists), false if denied.
|
|
27
24
|
* @throws PermissionCheckError if parsing or checking fails unexpectedly.
|
|
28
25
|
*/
|
|
29
|
-
export async function checkPermission(
|
|
26
|
+
export async function checkPermission(request, configPath, doNotUseBuiltinSchemas = false) {
|
|
30
27
|
if (!existsSync(configPath)) {
|
|
31
28
|
return true;
|
|
32
29
|
}
|
|
33
30
|
try {
|
|
34
|
-
|
|
35
|
-
const useBuiltinSchemas = !doNotUseBuiltinSchemas;
|
|
36
|
-
return await check(request, configPath, useBuiltinSchemas);
|
|
31
|
+
return await check(request, configPath, !doNotUseBuiltinSchemas);
|
|
37
32
|
}
|
|
38
33
|
catch (error) {
|
|
39
|
-
if (error instanceof
|
|
40
|
-
error instanceof ConfigError ||
|
|
41
|
-
error instanceof RequestSchemaError) {
|
|
34
|
+
if (error instanceof ConfigError || error instanceof RequestSchemaError) {
|
|
42
35
|
throw new PermissionCheckError(`Permission check failed: ${error.message}`);
|
|
43
36
|
}
|
|
44
37
|
throw error;
|