vigthoria-cli 1.13.23 → 1.13.24
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/commands/auth.js +55 -12
- package/package.json +1 -1
package/dist/commands/auth.js
CHANGED
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import readline from 'readline';
|
|
3
3
|
import { Config } from '../utils/config.js';
|
|
4
4
|
import { clearGatewayPreflightCache } from '../utils/cli-state.js';
|
|
5
|
-
import { AuthSessionService } from '../utils/auth-session.js';
|
|
5
|
+
import { AuthSessionService, validateTokenStructure } from '../utils/auth-session.js';
|
|
6
6
|
import { assertTrustedEndpoint, guardedFetch } from '../utils/network-policy.js';
|
|
7
7
|
import { CliCommandError, commandFailure } from '../utils/command-contract.js';
|
|
8
8
|
const DEFAULT_API_URL = 'https://coder.vigthoria.io';
|
|
@@ -228,13 +228,17 @@ export async function login(email, password) {
|
|
|
228
228
|
}
|
|
229
229
|
const authBases = getAuthBaseCandidates(getApiUrl());
|
|
230
230
|
const endpointVariants = [
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
// `/api/login` is the public Coder credential exchange. Older routes are
|
|
232
|
+
// compatibility fallbacks and may only be tried when a route is absent;
|
|
233
|
+
// retrying a decisive auth response consumes rate-limit budget and can
|
|
234
|
+
// turn an authorization or server-contract failure into a false
|
|
235
|
+
// "invalid password" report.
|
|
234
236
|
{ path: '/api/login', body: { email: resolvedEmail, password: resolvedPassword } },
|
|
237
|
+
{ path: '/api/login-json', body: { identifier: resolvedEmail, password: resolvedPassword } },
|
|
238
|
+
{ path: '/api/auth/login', body: { email: resolvedEmail, password: resolvedPassword } },
|
|
239
|
+
{ path: '/auth/login', body: { email: resolvedEmail, password: resolvedPassword } },
|
|
235
240
|
];
|
|
236
241
|
const attempted = [];
|
|
237
|
-
const failures = [];
|
|
238
242
|
for (const base of authBases) {
|
|
239
243
|
for (const variant of endpointVariants) {
|
|
240
244
|
const endpoint = `${trimTrailingSlash(base)}${variant.path}`;
|
|
@@ -246,19 +250,32 @@ export async function login(email, password) {
|
|
|
246
250
|
});
|
|
247
251
|
const token = extractAuthToken(result);
|
|
248
252
|
if (!token) {
|
|
249
|
-
|
|
250
|
-
|
|
253
|
+
throw new CliCommandError('The Vigthoria login service accepted the request but did not issue an access token.', {
|
|
254
|
+
code: 'LOGIN_TOKEN_MISSING', category: 'authentication', status: 502,
|
|
255
|
+
});
|
|
251
256
|
}
|
|
252
257
|
const normalizedBase = trimTrailingSlash(base);
|
|
253
|
-
|
|
258
|
+
try {
|
|
259
|
+
validateTokenStructure(token, normalizedBase);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
throw new CliCommandError(`The Vigthoria login service issued a token that the CLI cannot safely accept: ${humanMessage(error)}`, {
|
|
263
|
+
code: 'LOGIN_TOKEN_INVALID', category: 'authentication', status: 502, cause: error,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
254
266
|
const identity = extractAuthUser(result, resolvedEmail);
|
|
255
267
|
const refreshToken = result.tokens?.refresh_token || undefined;
|
|
256
268
|
await new AuthSessionService(new Config()).validateAndPersistToken(token, {
|
|
257
269
|
apiUrl: normalizedBase,
|
|
258
270
|
refreshToken,
|
|
259
271
|
identity: { userId: identity?.id, email: identity?.email },
|
|
260
|
-
v3ServiceKey:
|
|
272
|
+
v3ServiceKey: null,
|
|
261
273
|
});
|
|
274
|
+
// Only present the newly issued token to secondary authenticated
|
|
275
|
+
// endpoints after its structure and Coder acceptance are proven.
|
|
276
|
+
const v3ServiceKey = await fetchV3ServiceKey(normalizedBase, token);
|
|
277
|
+
if (v3ServiceKey)
|
|
278
|
+
new Config().setAuth({ token, v3ServiceKey });
|
|
262
279
|
const config = {
|
|
263
280
|
apiUrl: normalizedBase,
|
|
264
281
|
token,
|
|
@@ -270,15 +287,41 @@ export async function login(email, password) {
|
|
|
270
287
|
return config;
|
|
271
288
|
}
|
|
272
289
|
catch (error) {
|
|
290
|
+
if (error instanceof CliCommandError)
|
|
291
|
+
throw error;
|
|
273
292
|
if (error instanceof HttpError && error.code === 'SUBSCRIPTION_REQUIRED') {
|
|
274
293
|
throw error;
|
|
275
294
|
}
|
|
276
|
-
|
|
277
|
-
|
|
295
|
+
if (error instanceof HttpError && (error.status === 404 || error.status === 405)) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (error instanceof HttpError && error.status === 401) {
|
|
299
|
+
throw new CliCommandError('Invalid email or password. Please check your credentials and try again.', {
|
|
300
|
+
code: error.code || 'LOGIN_FAILED', category: 'authentication', status: error.status, cause: error,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
if (error instanceof HttpError && error.status === 403) {
|
|
304
|
+
throw new CliCommandError(humanMessage(error), {
|
|
305
|
+
code: error.code || 'LOGIN_FORBIDDEN', category: 'authorization', status: error.status, cause: error,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
if (error instanceof HttpError && error.status === 429) {
|
|
309
|
+
throw new CliCommandError('Too many login attempts. Wait for the authentication rate limit to reset, then try once.', {
|
|
310
|
+
code: 'LOGIN_RATE_LIMITED', category: 'authentication', status: error.status, cause: error,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (error instanceof HttpError && error.status >= 500) {
|
|
314
|
+
throw new CliCommandError(`Vigthoria authentication is temporarily unavailable: ${humanMessage(error)}`, {
|
|
315
|
+
code: error.code || 'LOGIN_SERVICE_UNAVAILABLE', category: 'network', status: error.status, cause: error,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
throw error;
|
|
278
319
|
}
|
|
279
320
|
}
|
|
280
321
|
}
|
|
281
|
-
throw new
|
|
322
|
+
throw new CliCommandError(`No supported login route is available on the configured Vigthoria endpoint. Tried ${attempted.join(', ')}.`, {
|
|
323
|
+
code: 'LOGIN_ROUTE_UNAVAILABLE', category: 'configuration', status: 404,
|
|
324
|
+
});
|
|
282
325
|
}
|
|
283
326
|
catch (error) {
|
|
284
327
|
const message = humanMessage(error);
|