@provartesting/provardx-cli 1.5.0-beta.3 → 1.5.0-beta.4
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 +101 -1
- package/lib/commands/provar/auth/clear.d.ts +7 -0
- package/lib/commands/provar/auth/clear.js +36 -0
- package/lib/commands/provar/auth/clear.js.map +1 -0
- package/lib/commands/provar/auth/login.d.ts +10 -0
- package/lib/commands/provar/auth/login.js +88 -0
- package/lib/commands/provar/auth/login.js.map +1 -0
- package/lib/commands/provar/auth/rotate.d.ts +7 -0
- package/lib/commands/provar/auth/rotate.js +42 -0
- package/lib/commands/provar/auth/rotate.js.map +1 -0
- package/lib/commands/provar/auth/status.d.ts +7 -0
- package/lib/commands/provar/auth/status.js +89 -0
- package/lib/commands/provar/auth/status.js.map +1 -0
- package/lib/mcp/tools/testCaseValidate.d.ts +4 -0
- package/lib/mcp/tools/testCaseValidate.js +98 -17
- package/lib/mcp/tools/testCaseValidate.js.map +1 -1
- package/lib/services/auth/credentials.d.ts +18 -0
- package/lib/services/auth/credentials.js +71 -0
- package/lib/services/auth/credentials.js.map +1 -0
- package/lib/services/auth/loginFlow.d.ts +61 -0
- package/lib/services/auth/loginFlow.js +183 -0
- package/lib/services/auth/loginFlow.js.map +1 -0
- package/lib/services/qualityHub/client.d.ts +131 -0
- package/lib/services/qualityHub/client.js +196 -0
- package/lib/services/qualityHub/client.js.map +1 -0
- package/messages/sf.provar.auth.clear.md +13 -0
- package/messages/sf.provar.auth.login.md +31 -0
- package/messages/sf.provar.auth.rotate.md +23 -0
- package/messages/sf.provar.auth.status.md +13 -0
- package/oclif.manifest.json +327 -114
- package/package.json +5 -2
|
@@ -12,13 +12,24 @@ import { XMLParser } from 'fast-xml-parser';
|
|
|
12
12
|
import { assertPathAllowed, PathPolicyError } from '../security/pathPolicy.js';
|
|
13
13
|
import { makeError, makeRequestId } from '../schemas/common.js';
|
|
14
14
|
import { log } from '../logging/logger.js';
|
|
15
|
+
import { resolveApiKey } from '../../services/auth/credentials.js';
|
|
16
|
+
import { qualityHubClient, getQualityHubBaseUrl, QualityHubAuthError, QualityHubRateLimitError, REQUEST_ACCESS_URL, } from '../../services/qualityHub/client.js';
|
|
15
17
|
import { runBestPractices } from './bestPracticesEngine.js';
|
|
18
|
+
const ONBOARDING_MESSAGE = 'Quality Hub validation unavailable — running local validation only (structural rules, no quality scoring).\n' +
|
|
19
|
+
'To enable Quality Hub (170 rules): run sf provar auth login\n' +
|
|
20
|
+
'For CI/CD: set the PROVAR_API_KEY environment variable.\n' +
|
|
21
|
+
`No account? Request access at: ${REQUEST_ACCESS_URL}`;
|
|
22
|
+
const AUTH_WARNING = 'Quality Hub API key is invalid or expired. Running local validation only.\n' +
|
|
23
|
+
`Run sf provar auth login to get a new key, or request access at: ${REQUEST_ACCESS_URL}`;
|
|
24
|
+
const RATE_LIMIT_WARNING = 'Quality Hub API rate limit reached. Running local validation only. Try again shortly.';
|
|
25
|
+
const UNREACHABLE_WARNING = 'Quality Hub API unreachable. Running local validation only (structural rules, no quality scoring).\n' +
|
|
26
|
+
'For CI/CD: set PROVAR_QUALITY_HUB_URL and PROVAR_API_KEY environment variables.';
|
|
16
27
|
export function registerTestCaseValidate(server, config) {
|
|
17
|
-
server.tool('provar.testcase.validate', 'Validate a Provar XML test case for structural correctness and quality. Checks XML declaration, root element, required attributes (guid UUID v4, testItemId integer), <steps> presence, and applies best-practice rules (
|
|
28
|
+
server.tool('provar.testcase.validate', 'Validate a Provar XML test case for structural correctness and quality. Checks XML declaration, root element, required attributes (guid UUID v4, testItemId integer), <steps> presence, and applies best-practice rules. When a Provar API key is configured (via sf provar auth login or PROVAR_API_KEY env var), calls the Quality Hub API for full 170-rule scoring. Falls back to local validation if no key is set or the API is unavailable. Returns validity_score (schema compliance), quality_score (best practices, 0–100), and validation_source indicating which ruleset was applied.', {
|
|
18
29
|
content: z.string().optional().describe('XML content to validate directly (alias: xml)'),
|
|
19
30
|
xml: z.string().optional().describe('XML content to validate — API-compatible alias for content'),
|
|
20
31
|
file_path: z.string().optional().describe('Path to .xml test case file'),
|
|
21
|
-
}, ({ content, xml, file_path }) => {
|
|
32
|
+
}, async ({ content, xml, file_path }) => {
|
|
22
33
|
const requestId = makeRequestId();
|
|
23
34
|
log('info', 'provar.testcase.validate', { requestId, has_content: !!(content ?? xml), file_path });
|
|
24
35
|
try {
|
|
@@ -37,8 +48,62 @@ export function registerTestCaseValidate(server, config) {
|
|
|
37
48
|
const err = makeError('MISSING_INPUT', 'Provide either content or file_path.', requestId);
|
|
38
49
|
return { isError: true, content: [{ type: 'text', text: JSON.stringify(err) }] };
|
|
39
50
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
51
|
+
const apiKey = resolveApiKey();
|
|
52
|
+
if (apiKey) {
|
|
53
|
+
const baseUrl = getQualityHubBaseUrl();
|
|
54
|
+
try {
|
|
55
|
+
const apiResult = await qualityHubClient.validateTestCaseViaApi(source, apiKey, baseUrl);
|
|
56
|
+
const localMeta = validateTestCase(source);
|
|
57
|
+
const result = {
|
|
58
|
+
requestId,
|
|
59
|
+
...apiResult,
|
|
60
|
+
step_count: localMeta.step_count,
|
|
61
|
+
error_count: apiResult.issues.filter((i) => i.severity === 'ERROR').length,
|
|
62
|
+
warning_count: apiResult.issues.filter((i) => i.severity === 'WARNING').length,
|
|
63
|
+
test_case_id: localMeta.test_case_id,
|
|
64
|
+
test_case_name: localMeta.test_case_name,
|
|
65
|
+
validation_source: 'quality_hub',
|
|
66
|
+
};
|
|
67
|
+
log('info', 'provar.testcase.validate: quality_hub', { requestId });
|
|
68
|
+
return {
|
|
69
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
70
|
+
structuredContent: result,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (apiErr) {
|
|
74
|
+
// API failed — determine the warning and fall through to local validation
|
|
75
|
+
let warning;
|
|
76
|
+
if (apiErr instanceof QualityHubAuthError) {
|
|
77
|
+
warning = AUTH_WARNING;
|
|
78
|
+
log('warn', 'provar.testcase.validate: auth error, falling back', { requestId });
|
|
79
|
+
}
|
|
80
|
+
else if (apiErr instanceof QualityHubRateLimitError) {
|
|
81
|
+
warning = RATE_LIMIT_WARNING;
|
|
82
|
+
log('warn', 'provar.testcase.validate: rate limited, falling back', { requestId });
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
warning = UNREACHABLE_WARNING;
|
|
86
|
+
log('warn', 'provar.testcase.validate: api unreachable, falling back', { requestId });
|
|
87
|
+
}
|
|
88
|
+
const localResult = {
|
|
89
|
+
requestId,
|
|
90
|
+
...validateTestCase(source),
|
|
91
|
+
validation_source: 'local_fallback',
|
|
92
|
+
validation_warning: warning,
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
content: [{ type: 'text', text: JSON.stringify(localResult) }],
|
|
96
|
+
structuredContent: localResult,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// No API key configured — run local validation with onboarding message
|
|
101
|
+
const result = {
|
|
102
|
+
requestId,
|
|
103
|
+
...validateTestCase(source),
|
|
104
|
+
validation_source: 'local',
|
|
105
|
+
validation_warning: ONBOARDING_MESSAGE,
|
|
106
|
+
};
|
|
42
107
|
return {
|
|
43
108
|
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
44
109
|
structuredContent: result,
|
|
@@ -60,7 +125,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
60
125
|
// TC_001: XML declaration
|
|
61
126
|
if (!xmlContent.trimStart().startsWith('<?xml')) {
|
|
62
127
|
issues.push({
|
|
63
|
-
rule_id: 'TC_001',
|
|
128
|
+
rule_id: 'TC_001',
|
|
129
|
+
severity: 'ERROR',
|
|
64
130
|
message: 'Missing XML declaration. File must start with <?xml version="1.0" encoding="UTF-8"?>.',
|
|
65
131
|
applies_to: 'document',
|
|
66
132
|
suggestion: 'Add XML declaration as the first line.',
|
|
@@ -79,7 +145,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
79
145
|
catch (e) {
|
|
80
146
|
const parseError = e;
|
|
81
147
|
issues.push({
|
|
82
|
-
rule_id: 'TC_002',
|
|
148
|
+
rule_id: 'TC_002',
|
|
149
|
+
severity: 'ERROR',
|
|
83
150
|
message: `XML parse error: ${parseError.message}`,
|
|
84
151
|
applies_to: 'document',
|
|
85
152
|
suggestion: 'Fix XML syntax errors.',
|
|
@@ -89,7 +156,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
89
156
|
// TC_003: Root element
|
|
90
157
|
if (!('testCase' in parsed)) {
|
|
91
158
|
issues.push({
|
|
92
|
-
rule_id: 'TC_003',
|
|
159
|
+
rule_id: 'TC_003',
|
|
160
|
+
severity: 'ERROR',
|
|
93
161
|
message: 'Root element must be <testCase>.',
|
|
94
162
|
applies_to: 'document',
|
|
95
163
|
suggestion: 'Ensure root element is <testCase>.',
|
|
@@ -105,7 +173,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
105
173
|
const tcGuid = tc['@_guid'];
|
|
106
174
|
if (!tcId) {
|
|
107
175
|
issues.push({
|
|
108
|
-
rule_id: 'TC_010',
|
|
176
|
+
rule_id: 'TC_010',
|
|
177
|
+
severity: 'ERROR',
|
|
109
178
|
message: 'testCase missing required id attribute.',
|
|
110
179
|
applies_to: 'testCase',
|
|
111
180
|
suggestion: 'Add id attribute to testCase element.',
|
|
@@ -113,7 +182,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
113
182
|
}
|
|
114
183
|
if (!tcGuid) {
|
|
115
184
|
issues.push({
|
|
116
|
-
rule_id: 'TC_011',
|
|
185
|
+
rule_id: 'TC_011',
|
|
186
|
+
severity: 'ERROR',
|
|
117
187
|
message: 'testCase missing required guid attribute.',
|
|
118
188
|
applies_to: 'testCase',
|
|
119
189
|
suggestion: 'Add guid attribute (UUID v4) to testCase element.',
|
|
@@ -121,7 +191,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
121
191
|
}
|
|
122
192
|
else if (!UUID_V4_RE.test(tcGuid)) {
|
|
123
193
|
issues.push({
|
|
124
|
-
rule_id: 'TC_012',
|
|
194
|
+
rule_id: 'TC_012',
|
|
195
|
+
severity: 'ERROR',
|
|
125
196
|
message: `testCase guid "${tcGuid}" is not a valid UUID v4.`,
|
|
126
197
|
applies_to: 'testCase',
|
|
127
198
|
suggestion: 'Generate a proper UUID v4 for the guid attribute.',
|
|
@@ -134,7 +205,8 @@ export function validateTestCase(xmlContent, testName) {
|
|
|
134
205
|
// TC_020: <steps> element
|
|
135
206
|
if (!('steps' in tc)) {
|
|
136
207
|
issues.push({
|
|
137
|
-
rule_id: 'TC_020',
|
|
208
|
+
rule_id: 'TC_020',
|
|
209
|
+
severity: 'ERROR',
|
|
138
210
|
message: 'testCase missing <steps> element.',
|
|
139
211
|
applies_to: 'testCase',
|
|
140
212
|
suggestion: 'Wrap all step elements in a <steps> element.',
|
|
@@ -161,7 +233,8 @@ function validateApiCall(call, issues) {
|
|
|
161
233
|
const label = apiId ? ` "${apiId}"` : '';
|
|
162
234
|
if (!callGuid) {
|
|
163
235
|
issues.push({
|
|
164
|
-
rule_id: 'TC_030',
|
|
236
|
+
rule_id: 'TC_030',
|
|
237
|
+
severity: 'ERROR',
|
|
165
238
|
message: `apiCall${label} missing guid attribute.`,
|
|
166
239
|
applies_to: 'apiCall',
|
|
167
240
|
suggestion: 'Add a UUID v4 guid to each apiCall.',
|
|
@@ -169,7 +242,8 @@ function validateApiCall(call, issues) {
|
|
|
169
242
|
}
|
|
170
243
|
else if (!UUID_V4_RE.test(callGuid)) {
|
|
171
244
|
issues.push({
|
|
172
|
-
rule_id: 'TC_031',
|
|
245
|
+
rule_id: 'TC_031',
|
|
246
|
+
severity: 'ERROR',
|
|
173
247
|
message: `apiCall${label} guid "${callGuid}" is not a valid UUID v4.`,
|
|
174
248
|
applies_to: 'apiCall',
|
|
175
249
|
suggestion: 'Use proper UUID v4 format.',
|
|
@@ -177,7 +251,8 @@ function validateApiCall(call, issues) {
|
|
|
177
251
|
}
|
|
178
252
|
if (!apiId) {
|
|
179
253
|
issues.push({
|
|
180
|
-
rule_id: 'TC_032',
|
|
254
|
+
rule_id: 'TC_032',
|
|
255
|
+
severity: 'ERROR',
|
|
181
256
|
message: 'apiCall missing apiId attribute.',
|
|
182
257
|
applies_to: 'apiCall',
|
|
183
258
|
suggestion: 'Add apiId attribute (e.g., UiConnect, ApexSoqlQuery).',
|
|
@@ -185,7 +260,8 @@ function validateApiCall(call, issues) {
|
|
|
185
260
|
}
|
|
186
261
|
if (!name) {
|
|
187
262
|
issues.push({
|
|
188
|
-
rule_id: 'TC_033',
|
|
263
|
+
rule_id: 'TC_033',
|
|
264
|
+
severity: 'WARNING',
|
|
189
265
|
message: `apiCall${label} missing name attribute.`,
|
|
190
266
|
applies_to: 'apiCall',
|
|
191
267
|
suggestion: 'Add a descriptive name attribute.',
|
|
@@ -193,7 +269,8 @@ function validateApiCall(call, issues) {
|
|
|
193
269
|
}
|
|
194
270
|
if (!testItemId) {
|
|
195
271
|
issues.push({
|
|
196
|
-
rule_id: 'TC_034',
|
|
272
|
+
rule_id: 'TC_034',
|
|
273
|
+
severity: 'ERROR',
|
|
197
274
|
message: `apiCall${label} missing testItemId attribute.`,
|
|
198
275
|
applies_to: 'apiCall',
|
|
199
276
|
suggestion: 'Add sequential testItemId (1, 2, 3...).',
|
|
@@ -201,7 +278,8 @@ function validateApiCall(call, issues) {
|
|
|
201
278
|
}
|
|
202
279
|
else if (!/^\d+$/.test(testItemId)) {
|
|
203
280
|
issues.push({
|
|
204
|
-
rule_id: 'TC_035',
|
|
281
|
+
rule_id: 'TC_035',
|
|
282
|
+
severity: 'ERROR',
|
|
205
283
|
message: `apiCall${label} testItemId "${testItemId}" must be a whole number.`,
|
|
206
284
|
applies_to: 'apiCall',
|
|
207
285
|
suggestion: 'Use sequential integers for testItemId.',
|
|
@@ -227,6 +305,9 @@ function finalize(issues, testCaseId, testCaseName, stepCount, xmlContent, testN
|
|
|
227
305
|
issues,
|
|
228
306
|
best_practices_violations: bp.violations,
|
|
229
307
|
best_practices_rules_evaluated: bp.rules_evaluated,
|
|
308
|
+
// validation_source is set by the caller (MCP tool handler or direct callers).
|
|
309
|
+
// Default to 'local' here so the pure validateTestCase() function is self-contained.
|
|
310
|
+
validation_source: 'local',
|
|
230
311
|
};
|
|
231
312
|
}
|
|
232
313
|
//# sourceMappingURL=testCaseValidate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testCaseValidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/testCaseValidate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"testCaseValidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/testCaseValidate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface StoredCredentials {
|
|
2
|
+
api_key: string;
|
|
3
|
+
prefix: string;
|
|
4
|
+
set_at: string;
|
|
5
|
+
source: 'manual' | 'cognito' | 'salesforce';
|
|
6
|
+
username?: string;
|
|
7
|
+
tier?: string;
|
|
8
|
+
expires_at?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function getCredentialsPath(): string;
|
|
11
|
+
export declare function readStoredCredentials(): StoredCredentials | null;
|
|
12
|
+
export declare function writeCredentials(key: string, prefix: string, source: StoredCredentials['source'], extra?: {
|
|
13
|
+
username?: string;
|
|
14
|
+
tier?: string;
|
|
15
|
+
expires_at?: string;
|
|
16
|
+
}): void;
|
|
17
|
+
export declare function clearCredentials(): void;
|
|
18
|
+
export declare function resolveApiKey(): string | null;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Provar Limited.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
/* eslint-disable camelcase */
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import os from 'node:os';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
const KEY_PREFIX = 'pv_k_';
|
|
12
|
+
export function getCredentialsPath() {
|
|
13
|
+
return path.join(os.homedir(), '.provar', 'credentials.json');
|
|
14
|
+
}
|
|
15
|
+
export function readStoredCredentials() {
|
|
16
|
+
try {
|
|
17
|
+
const p = getCredentialsPath();
|
|
18
|
+
if (!fs.existsSync(p))
|
|
19
|
+
return null;
|
|
20
|
+
const raw = fs.readFileSync(p, 'utf-8');
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function writeCredentials(key, prefix, source, extra) {
|
|
28
|
+
if (!key.startsWith(KEY_PREFIX)) {
|
|
29
|
+
throw new Error(`Invalid API key format. Keys must start with "${KEY_PREFIX}".`);
|
|
30
|
+
}
|
|
31
|
+
const p = getCredentialsPath();
|
|
32
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
33
|
+
const data = {
|
|
34
|
+
api_key: key,
|
|
35
|
+
prefix,
|
|
36
|
+
set_at: new Date().toISOString(),
|
|
37
|
+
source,
|
|
38
|
+
...(extra?.username ? { username: extra.username } : {}),
|
|
39
|
+
...(extra?.tier ? { tier: extra.tier } : {}),
|
|
40
|
+
...(extra?.expires_at ? { expires_at: extra.expires_at } : {}),
|
|
41
|
+
};
|
|
42
|
+
// mode: 0o600 sets permissions atomically on file creation (POSIX).
|
|
43
|
+
// chmodSync handles re-runs on existing files. Both are no-ops on Windows.
|
|
44
|
+
fs.writeFileSync(p, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
45
|
+
try {
|
|
46
|
+
fs.chmodSync(p, 0o600);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
/* Windows: no file permission model */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function clearCredentials() {
|
|
53
|
+
const p = getCredentialsPath();
|
|
54
|
+
try {
|
|
55
|
+
fs.rmSync(p);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const e = err;
|
|
59
|
+
if (e.code !== 'ENOENT')
|
|
60
|
+
throw err;
|
|
61
|
+
// file did not exist — nothing to clear, not an error
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function resolveApiKey() {
|
|
65
|
+
const envKey = process.env.PROVAR_API_KEY?.trim();
|
|
66
|
+
if (envKey?.startsWith(KEY_PREFIX))
|
|
67
|
+
return envKey;
|
|
68
|
+
const stored = readStoredCredentials();
|
|
69
|
+
return stored?.api_key ?? null;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/services/auth/credentials.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8BAA8B;AAC9B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAa7B,MAAM,UAAU,GAAG,OAAO,CAAC;AAE3B,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,GAAW,EACX,MAAc,EACd,MAAmC,EACnC,KAAiE;IAEjE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,iDAAiD,UAAU,IAAI,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;IAC/B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,IAAI,GAAsB;QAC9B,OAAO,EAAE,GAAG;QACZ,MAAM;QACN,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAChC,MAAM;QACN,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAC;IACF,oEAAoE;IACpE,2EAA2E;IAC3E,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvF,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,GAAG,kBAAkB,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAA4B,CAAC;QACvC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAC;QACnC,sDAAsD;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC;IAClD,IAAI,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,MAAM,CAAC;IAClD,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,OAAO,MAAM,EAAE,OAAO,IAAI,IAAI,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export declare const CALLBACK_PORTS: number[];
|
|
2
|
+
/**
|
|
3
|
+
* Generate a PKCE code_verifier / code_challenge pair (S256 method, as required by Cognito).
|
|
4
|
+
*/
|
|
5
|
+
export declare function generatePkce(): {
|
|
6
|
+
verifier: string;
|
|
7
|
+
challenge: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Generate a random nonce for OIDC replay-attack prevention.
|
|
11
|
+
* Required by the OpenID Connect spec when requesting an id_token.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateNonce(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Generate a random state value for CSRF protection.
|
|
16
|
+
* Required by Cognito Managed Login even though it is optional per the OAuth 2.0 spec.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateState(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Try each registered callback port in order; return the first that is free.
|
|
21
|
+
*/
|
|
22
|
+
export declare function findAvailablePort(): Promise<number>;
|
|
23
|
+
/**
|
|
24
|
+
* Open a URL in the system browser. The URL is passed as an argument — not
|
|
25
|
+
* interpolated into a shell string — to avoid command injection.
|
|
26
|
+
*/
|
|
27
|
+
export declare function openBrowser(url: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Spin up a temporary localhost HTTP server that accepts exactly one callback
|
|
30
|
+
* from Cognito's Hosted UI, extracts the auth code, and shuts down.
|
|
31
|
+
*/
|
|
32
|
+
export declare function listenForCallback(port: number, expectedState?: string): Promise<string>;
|
|
33
|
+
export interface CognitoTokens {
|
|
34
|
+
access_token: string;
|
|
35
|
+
id_token: string;
|
|
36
|
+
token_type: string;
|
|
37
|
+
expires_in: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Exchange a PKCE auth code for Cognito tokens via the standard token endpoint.
|
|
41
|
+
* Uses the Authorization Code + PKCE grant — no client secret required.
|
|
42
|
+
*/
|
|
43
|
+
export declare function exchangeCodeForTokens(opts: {
|
|
44
|
+
code: string;
|
|
45
|
+
redirectUri: string;
|
|
46
|
+
clientId: string;
|
|
47
|
+
verifier: string;
|
|
48
|
+
tokenEndpoint: string;
|
|
49
|
+
}): Promise<CognitoTokens>;
|
|
50
|
+
/**
|
|
51
|
+
* The login command calls loginFlowClient.X() so tests can replace properties with stubs.
|
|
52
|
+
*/
|
|
53
|
+
export declare const loginFlowClient: {
|
|
54
|
+
generatePkce: typeof generatePkce;
|
|
55
|
+
generateNonce: typeof generateNonce;
|
|
56
|
+
generateState: typeof generateState;
|
|
57
|
+
findAvailablePort: typeof findAvailablePort;
|
|
58
|
+
openBrowser: typeof openBrowser;
|
|
59
|
+
listenForCallback: (port: number, expectedState?: string) => Promise<string>;
|
|
60
|
+
exchangeCodeForTokens: typeof exchangeCodeForTokens;
|
|
61
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Provar Limited.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
/* eslint-disable camelcase */
|
|
8
|
+
import crypto from 'node:crypto';
|
|
9
|
+
import http from 'node:http';
|
|
10
|
+
import https from 'node:https';
|
|
11
|
+
import { execFile } from 'node:child_process';
|
|
12
|
+
import { URL } from 'node:url';
|
|
13
|
+
// All three ports must be pre-registered in the Cognito App Client.
|
|
14
|
+
// Cognito requires redirect_uri to exactly match a registered callback URL — no wildcards.
|
|
15
|
+
export const CALLBACK_PORTS = [1717, 7890, 8080];
|
|
16
|
+
// ── PKCE ─────────────────────────────────────────────────────────────────────
|
|
17
|
+
/**
|
|
18
|
+
* Generate a PKCE code_verifier / code_challenge pair (S256 method, as required by Cognito).
|
|
19
|
+
*/
|
|
20
|
+
export function generatePkce() {
|
|
21
|
+
const verifier = crypto.randomBytes(32).toString('base64url');
|
|
22
|
+
const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
|
|
23
|
+
return { verifier, challenge };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a random nonce for OIDC replay-attack prevention.
|
|
27
|
+
* Required by the OpenID Connect spec when requesting an id_token.
|
|
28
|
+
*/
|
|
29
|
+
export function generateNonce() {
|
|
30
|
+
return crypto.randomBytes(16).toString('base64url');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Generate a random state value for CSRF protection.
|
|
34
|
+
* Required by Cognito Managed Login even though it is optional per the OAuth 2.0 spec.
|
|
35
|
+
*/
|
|
36
|
+
export function generateState() {
|
|
37
|
+
return crypto.randomBytes(16).toString('base64url');
|
|
38
|
+
}
|
|
39
|
+
// ── Port selection ────────────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Try each registered callback port in order; return the first that is free.
|
|
42
|
+
*/
|
|
43
|
+
export async function findAvailablePort() {
|
|
44
|
+
for (const port of CALLBACK_PORTS) {
|
|
45
|
+
// Sequential by design — we need the first free registered port, not all of them.
|
|
46
|
+
// eslint-disable-next-line no-await-in-loop
|
|
47
|
+
if (await isPortFree(port))
|
|
48
|
+
return port;
|
|
49
|
+
}
|
|
50
|
+
throw new Error('Could not bind to any registered callback port (1717, 7890, 8080). ' +
|
|
51
|
+
'Check that no other process is using these ports and try again.');
|
|
52
|
+
}
|
|
53
|
+
function isPortFree(port) {
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const probe = http.createServer();
|
|
56
|
+
probe.once('error', () => resolve(false));
|
|
57
|
+
probe.listen(port, '127.0.0.1', () => {
|
|
58
|
+
probe.close(() => resolve(true));
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// ── Browser open ──────────────────────────────────────────────────────────────
|
|
63
|
+
/**
|
|
64
|
+
* Open a URL in the system browser. The URL is passed as an argument — not
|
|
65
|
+
* interpolated into a shell string — to avoid command injection.
|
|
66
|
+
*/
|
|
67
|
+
export function openBrowser(url) {
|
|
68
|
+
switch (process.platform) {
|
|
69
|
+
case 'darwin':
|
|
70
|
+
execFile('open', [url]);
|
|
71
|
+
break;
|
|
72
|
+
case 'win32':
|
|
73
|
+
// Pass the URL via $args[0] so it is never interpolated into the -Command
|
|
74
|
+
// string — avoids quote-breaking and injection risk from special characters.
|
|
75
|
+
execFile('powershell.exe', ['-NoProfile', '-Command', 'Start-Process $args[0]', '-args', url]);
|
|
76
|
+
break;
|
|
77
|
+
default:
|
|
78
|
+
execFile('xdg-open', [url]);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ── Localhost callback server ─────────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Spin up a temporary localhost HTTP server that accepts exactly one callback
|
|
84
|
+
* from Cognito's Hosted UI, extracts the auth code, and shuts down.
|
|
85
|
+
*/
|
|
86
|
+
export function listenForCallback(port, expectedState) {
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
const server = http.createServer((req, res) => {
|
|
89
|
+
const parsed = new URL(req.url ?? '/', `http://localhost:${port}`);
|
|
90
|
+
const code = parsed.searchParams.get('code');
|
|
91
|
+
const error = parsed.searchParams.get('error');
|
|
92
|
+
const description = parsed.searchParams.get('error_description');
|
|
93
|
+
const callbackState = parsed.searchParams.get('state');
|
|
94
|
+
if (expectedState && callbackState !== expectedState) {
|
|
95
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
96
|
+
res.end('<html><body style="font-family:sans-serif;padding:2rem;max-width:480px">' +
|
|
97
|
+
'<h2 style="color:#c23934">Authentication failed</h2>' +
|
|
98
|
+
'<p>Invalid state parameter — possible CSRF attack. Please try again.</p>' +
|
|
99
|
+
'</body></html>');
|
|
100
|
+
server.close();
|
|
101
|
+
reject(new Error('OAuth callback state mismatch — possible CSRF. Try again.'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
105
|
+
res.end('<html><body style="font-family:sans-serif;padding:2rem;max-width:480px">' +
|
|
106
|
+
'<h2 style="color:#0070d2">Authentication complete</h2>' +
|
|
107
|
+
'<p>You can close this tab and return to the terminal.</p>' +
|
|
108
|
+
'</body></html>');
|
|
109
|
+
server.close();
|
|
110
|
+
if (code) {
|
|
111
|
+
resolve(code);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
reject(new Error(description ?? error ?? 'No authorisation code received from Cognito'));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
server.listen(port, '127.0.0.1');
|
|
118
|
+
server.on('error', (err) => reject(err));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Exchange a PKCE auth code for Cognito tokens via the standard token endpoint.
|
|
123
|
+
* Uses the Authorization Code + PKCE grant — no client secret required.
|
|
124
|
+
*/
|
|
125
|
+
export async function exchangeCodeForTokens(opts) {
|
|
126
|
+
const body = new URLSearchParams({
|
|
127
|
+
grant_type: 'authorization_code',
|
|
128
|
+
code: opts.code,
|
|
129
|
+
redirect_uri: opts.redirectUri,
|
|
130
|
+
client_id: opts.clientId,
|
|
131
|
+
code_verifier: opts.verifier,
|
|
132
|
+
}).toString();
|
|
133
|
+
const { status, responseBody } = await httpsPost(opts.tokenEndpoint, body, {
|
|
134
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
135
|
+
});
|
|
136
|
+
if (status !== 200) {
|
|
137
|
+
throw new Error(`Cognito token exchange failed (${status}): ${responseBody}`);
|
|
138
|
+
}
|
|
139
|
+
return JSON.parse(responseBody);
|
|
140
|
+
}
|
|
141
|
+
// ── Internal HTTPS helper ─────────────────────────────────────────────────────
|
|
142
|
+
const REQUEST_TIMEOUT_MS = 30000;
|
|
143
|
+
function httpsPost(url, body, headers) {
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
const parsed = new URL(url);
|
|
146
|
+
const req = https.request({
|
|
147
|
+
hostname: parsed.hostname,
|
|
148
|
+
port: parsed.port || undefined,
|
|
149
|
+
path: parsed.pathname + parsed.search,
|
|
150
|
+
method: 'POST',
|
|
151
|
+
headers: {
|
|
152
|
+
...headers,
|
|
153
|
+
'Content-Length': Buffer.byteLength(body).toString(),
|
|
154
|
+
},
|
|
155
|
+
}, (res) => {
|
|
156
|
+
let data = '';
|
|
157
|
+
res.on('data', (chunk) => {
|
|
158
|
+
data += chunk.toString('utf-8');
|
|
159
|
+
});
|
|
160
|
+
res.on('end', () => resolve({ status: res.statusCode ?? 0, responseBody: data }));
|
|
161
|
+
});
|
|
162
|
+
req.setTimeout(REQUEST_TIMEOUT_MS, () => {
|
|
163
|
+
req.destroy(new Error(`Cognito token exchange timed out after ${REQUEST_TIMEOUT_MS / 1000}s`));
|
|
164
|
+
});
|
|
165
|
+
req.on('error', reject);
|
|
166
|
+
req.write(body);
|
|
167
|
+
req.end();
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// ── Indirection object (sinon-stubbable) ──────────────────────────────────────
|
|
171
|
+
/**
|
|
172
|
+
* The login command calls loginFlowClient.X() so tests can replace properties with stubs.
|
|
173
|
+
*/
|
|
174
|
+
export const loginFlowClient = {
|
|
175
|
+
generatePkce,
|
|
176
|
+
generateNonce,
|
|
177
|
+
generateState,
|
|
178
|
+
findAvailablePort,
|
|
179
|
+
openBrowser,
|
|
180
|
+
listenForCallback: listenForCallback,
|
|
181
|
+
exchangeCodeForTokens,
|
|
182
|
+
};
|
|
183
|
+
//# sourceMappingURL=loginFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loginFlow.js","sourceRoot":"","sources":["../../../src/services/auth/loginFlow.ts"],"names":[],"mappings":"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"}
|