@torrow/sdk-auth 0.9.1 → 0.10.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/dist/index.js +331 -124
- package/dist/index.js.map +1 -1
- package/dist/node.js +6 -2
- package/dist/node.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -9,13 +9,16 @@ function resolveAppCredentials(input) {
|
|
|
9
9
|
function appCredentialsToAuthIdentityBasic(appCredentials) {
|
|
10
10
|
const clientId = appCredentials?.clientId?.trim();
|
|
11
11
|
const clientSecret = appCredentials?.clientSecret?.trim();
|
|
12
|
-
if (!clientId || !clientSecret)
|
|
12
|
+
if (!clientId || !clientSecret) {
|
|
13
|
+
return void 0;
|
|
14
|
+
}
|
|
13
15
|
return { username: clientId, password: clientSecret };
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
// ../../src/auth-session/otp-errors.ts
|
|
17
19
|
import {
|
|
18
20
|
OtpErrorReason,
|
|
21
|
+
ApiErrorNameValues,
|
|
19
22
|
TorrowSdkError,
|
|
20
23
|
TorrowSdkErrorCategory,
|
|
21
24
|
TorrowSdkErrorDomain,
|
|
@@ -44,32 +47,54 @@ function otpFailure(kind, cleanup, cause) {
|
|
|
44
47
|
default:
|
|
45
48
|
category = kind;
|
|
46
49
|
}
|
|
47
|
-
return new TorrowSdkError({
|
|
50
|
+
return new TorrowSdkError({
|
|
51
|
+
category,
|
|
52
|
+
detail: { domain: TorrowSdkErrorDomain.Otp, ...reason ? { reason } : {} },
|
|
53
|
+
sensitive: { cleanup, cause }
|
|
54
|
+
});
|
|
48
55
|
}
|
|
49
56
|
function otpHttpFailure(error) {
|
|
50
|
-
if (!(error instanceof TorrowSdkError))
|
|
57
|
+
if (!(error instanceof TorrowSdkError)) {
|
|
58
|
+
return error;
|
|
59
|
+
}
|
|
51
60
|
const body = error.getSensitiveDetails().body;
|
|
52
|
-
if (body === null || typeof body !== "object")
|
|
61
|
+
if (body === null || typeof body !== "object") {
|
|
62
|
+
return error;
|
|
63
|
+
}
|
|
53
64
|
const value = body;
|
|
54
|
-
if (value.name ===
|
|
55
|
-
return error.withContext({
|
|
65
|
+
if (value.name === ApiErrorNameValues.AuthHeaderMissing) {
|
|
66
|
+
return error.withContext({
|
|
67
|
+
category: TorrowSdkErrorCategory.AuthenticationRequired,
|
|
68
|
+
detail: { domain: TorrowSdkErrorDomain.Otp, reason: OtpErrorReason.AuthHeaderMissing }
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (value.name !== ApiErrorNameValues.CodeRequestLimit) {
|
|
72
|
+
return error;
|
|
56
73
|
}
|
|
57
|
-
if (value.name !== "CODE_REQUEST_LIMIT_EXCEEDED" /* CodeRequestLimitExceeded */) return error;
|
|
58
74
|
const minutes = duration(value.parameters?.minutes);
|
|
59
75
|
const seconds = duration(value.parameters?.seconds);
|
|
60
76
|
const wait = minutes === void 0 && seconds === void 0 ? void 0 : (minutes ?? 0) * 60 + (seconds ?? 0);
|
|
61
|
-
return error.withContext({
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
return error.withContext({
|
|
78
|
+
category: TorrowSdkErrorCategory.RateLimited,
|
|
79
|
+
detail: {
|
|
80
|
+
domain: TorrowSdkErrorDomain.Otp,
|
|
81
|
+
reason: OtpErrorReason.CodeRequestLimitExceeded,
|
|
82
|
+
...wait !== void 0 && Number.isFinite(wait) ? { retryAfterSeconds: wait } : {}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
66
85
|
}
|
|
67
86
|
function duration(value) {
|
|
68
87
|
const number = typeof value === "number" ? value : typeof value === "string" && /^\d+(?:\.\d+)?$/.test(value) ? Number(value) : void 0;
|
|
69
88
|
return number !== void 0 && Number.isFinite(number) && number >= 0 ? number : void 0;
|
|
70
89
|
}
|
|
71
90
|
function throwIfOtpAborted(signal) {
|
|
72
|
-
if (signal?.aborted)
|
|
91
|
+
if (signal?.aborted) {
|
|
92
|
+
throw new TorrowSdkError({
|
|
93
|
+
category: TorrowSdkErrorCategory.Cancelled,
|
|
94
|
+
request: TorrowSdkRequestState.NotStarted,
|
|
95
|
+
sensitive: { cause: signal.reason }
|
|
96
|
+
});
|
|
97
|
+
}
|
|
73
98
|
}
|
|
74
99
|
|
|
75
100
|
// ../../src/auth-session/otp-flow.ts
|
|
@@ -87,9 +112,7 @@ import {
|
|
|
87
112
|
// ../../src/auth-session/identity-client.ts
|
|
88
113
|
import { TorrowClient } from "@torrow/sdk-client";
|
|
89
114
|
function createIdentityClient(options) {
|
|
90
|
-
const authIdentityBasic = appCredentialsToAuthIdentityBasic(
|
|
91
|
-
resolveAppCredentials(options.appCredentials)
|
|
92
|
-
);
|
|
115
|
+
const authIdentityBasic = appCredentialsToAuthIdentityBasic(resolveAppCredentials(options.appCredentials));
|
|
93
116
|
if (!authIdentityBasic) {
|
|
94
117
|
throw new Error(
|
|
95
118
|
"TokenSession: \u043D\u0435\u043F\u043E\u043B\u043D\u0430\u044F appCredentials (\u043D\u0443\u0436\u043D\u044B \u043D\u0435\u043F\u0443\u0441\u0442\u044B\u0435 clientId \u0438 clientSecret). \u0411\u0435\u0437 \u043E\u043F\u0446\u0438\u0438 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F DEFAULT_APP_CREDENTIALS."
|
|
@@ -112,7 +135,9 @@ import {
|
|
|
112
135
|
} from "@torrow/sdk-client";
|
|
113
136
|
function buildOtpSendRequest(input) {
|
|
114
137
|
const accountName = input.accountName.trim();
|
|
115
|
-
if (!accountName)
|
|
138
|
+
if (!accountName) {
|
|
139
|
+
throw new Error("runOtpLogin: accountName is empty");
|
|
140
|
+
}
|
|
116
141
|
return {
|
|
117
142
|
accountName,
|
|
118
143
|
type: input.type,
|
|
@@ -141,7 +166,9 @@ function requestAuthToken(client, input, signal) {
|
|
|
141
166
|
);
|
|
142
167
|
}
|
|
143
168
|
function tokenTransition(status, legacy = false) {
|
|
144
|
-
if (legacy && status == null)
|
|
169
|
+
if (legacy && status == null) {
|
|
170
|
+
return TokenStatusValues.TokenReady;
|
|
171
|
+
}
|
|
145
172
|
return typeof status === "string" && isTokenStatus(status) ? status : void 0;
|
|
146
173
|
}
|
|
147
174
|
function tokenResponseFields(o) {
|
|
@@ -160,10 +187,9 @@ var OtpPhaseValues = /* @__PURE__ */ ((OtpPhaseValues2) => {
|
|
|
160
187
|
return OtpPhaseValues2;
|
|
161
188
|
})(OtpPhaseValues || {});
|
|
162
189
|
function createOtpFlow(options) {
|
|
163
|
-
if (!isRecord(options) || !isRecord(options.deviceInfo) || typeof options.deviceInfo.deviceId !== "string" || !options.deviceInfo.deviceId.trim() || typeof options.deviceInfo.deviceType !== "string" || !isDeviceType(options.deviceInfo.deviceType) || options.scopes !== void 0 && (!Array.isArray(options.scopes) || !options.scopes.every(
|
|
164
|
-
(scope) => typeof scope === "string" && scope.trim()
|
|
165
|
-
)) || options.splitTokens !== void 0 && typeof options.splitTokens !== "boolean")
|
|
190
|
+
if (!isRecord(options) || !isRecord(options.deviceInfo) || typeof options.deviceInfo.deviceId !== "string" || !options.deviceInfo.deviceId.trim() || typeof options.deviceInfo.deviceType !== "string" || !isDeviceType(options.deviceInfo.deviceType) || options.scopes !== void 0 && (!Array.isArray(options.scopes) || !options.scopes.every((scope) => typeof scope === "string" && scope.trim())) || options.splitTokens !== void 0 && typeof options.splitTokens !== "boolean") {
|
|
166
191
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidInput);
|
|
192
|
+
}
|
|
167
193
|
let client;
|
|
168
194
|
try {
|
|
169
195
|
client = createIdentityClient(options);
|
|
@@ -189,15 +215,20 @@ function createOtpFlow(options) {
|
|
|
189
215
|
).catch((error) => {
|
|
190
216
|
throw otpHttpFailure(error);
|
|
191
217
|
});
|
|
192
|
-
if (!isRecord(response) || typeof response.sessionId !== "string" || !response.sessionId.trim())
|
|
218
|
+
if (!isRecord(response) || typeof response.sessionId !== "string" || !response.sessionId.trim()) {
|
|
193
219
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidResponse);
|
|
194
|
-
|
|
220
|
+
}
|
|
221
|
+
if (!supportedMethod(response.usedMethod, input.account.accountType)) {
|
|
195
222
|
throw otpFailure(OtpErrorReason2.UnsupportedMethod);
|
|
223
|
+
}
|
|
196
224
|
const ttl = response.sessionLifeTimeInSeconds ?? 180;
|
|
197
|
-
if (!positive(ttl))
|
|
225
|
+
if (!positive(ttl)) {
|
|
226
|
+
throw otpFailure(TorrowSdkErrorCategory2.InvalidResponse);
|
|
227
|
+
}
|
|
198
228
|
const expiresAtMs = startedAt + ttl * 1e3;
|
|
199
|
-
if (!timestamp(expiresAtMs) || expiresAtMs <= Date.now())
|
|
229
|
+
if (!timestamp(expiresAtMs) || expiresAtMs <= Date.now()) {
|
|
200
230
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidResponse);
|
|
231
|
+
}
|
|
201
232
|
const mobile = response.usedMethod === VerificationMethodValues.MtsMobileId;
|
|
202
233
|
const nextSendAtMs = response.nextAvailableUsageTime instanceof Date ? response.nextAvailableUsageTime.getTime() : typeof response.nextAvailableUsageTime === "string" ? Date.parse(response.nextAvailableUsageTime) : void 0;
|
|
203
234
|
return {
|
|
@@ -216,11 +247,14 @@ function createOtpFlow(options) {
|
|
|
216
247
|
};
|
|
217
248
|
},
|
|
218
249
|
async complete(input, requestOptions) {
|
|
219
|
-
if (!isRecord(input))
|
|
250
|
+
if (!isRecord(input)) {
|
|
251
|
+
throw otpFailure(TorrowSdkErrorCategory2.InvalidInput);
|
|
252
|
+
}
|
|
220
253
|
throwIfOtpAborted(requestOptions?.signal);
|
|
221
254
|
const continuation = validateChallenge(input.challenge);
|
|
222
|
-
if (continuation.phase === "Pending" /* Pending */ && input.code !== void 0 || continuation.phase === "AwaitingCode" /* AwaitingCode */ && (typeof input.code !== "string" || !input.code.trim()))
|
|
255
|
+
if (continuation.phase === "Pending" /* Pending */ && input.code !== void 0 || continuation.phase === "AwaitingCode" /* AwaitingCode */ && (typeof input.code !== "string" || !input.code.trim())) {
|
|
223
256
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidInput);
|
|
257
|
+
}
|
|
224
258
|
const raw = await requestAuthToken(
|
|
225
259
|
client,
|
|
226
260
|
{
|
|
@@ -234,16 +268,17 @@ function createOtpFlow(options) {
|
|
|
234
268
|
).catch((error) => {
|
|
235
269
|
throw otpHttpFailure(error);
|
|
236
270
|
});
|
|
237
|
-
if (!isRecord(raw))
|
|
271
|
+
if (!isRecord(raw)) {
|
|
272
|
+
throw otpFailure(TorrowSdkErrorCategory2.InvalidResponse);
|
|
273
|
+
}
|
|
238
274
|
const fields = tokenResponseFields(raw);
|
|
239
275
|
const refreshToken = typeof fields.refresh === "string" && fields.refresh.trim() ? fields.refresh.trim() : void 0;
|
|
240
276
|
const cleanup = refreshToken ? { refreshToken } : void 0;
|
|
241
|
-
const status = tokenTransition(
|
|
242
|
-
|
|
243
|
-
);
|
|
244
|
-
if (!status || fields.access != null && typeof fields.access !== "string" || fields.refresh != null && typeof fields.refresh !== "string" || fields.expiration != null && (typeof fields.expiration !== "number" || !Number.isFinite(fields.expiration) || fields.expiration < 0))
|
|
277
|
+
const status = tokenTransition(typeof fields.status === "string" ? fields.status.trim() : fields.status);
|
|
278
|
+
if (!status || fields.access != null && typeof fields.access !== "string" || fields.refresh != null && typeof fields.refresh !== "string" || fields.expiration != null && (typeof fields.expiration !== "number" || !Number.isFinite(fields.expiration) || fields.expiration < 0)) {
|
|
245
279
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidResponse, cleanup);
|
|
246
|
-
|
|
280
|
+
}
|
|
281
|
+
if (status === TokenStatusValues2.Pending) {
|
|
247
282
|
return {
|
|
248
283
|
status,
|
|
249
284
|
cleanup,
|
|
@@ -254,6 +289,7 @@ function createOtpFlow(options) {
|
|
|
254
289
|
pollIntervalSeconds: continuation.pollIntervalSeconds ?? 3
|
|
255
290
|
}
|
|
256
291
|
};
|
|
292
|
+
}
|
|
257
293
|
if (status === TokenStatusValues2.AwaitingSmsCode) {
|
|
258
294
|
const { pollIntervalSeconds: _interval, ...challenge } = continuation;
|
|
259
295
|
return {
|
|
@@ -267,9 +303,12 @@ function createOtpFlow(options) {
|
|
|
267
303
|
}
|
|
268
304
|
};
|
|
269
305
|
}
|
|
270
|
-
if (status === TokenStatusValues2.Failed)
|
|
271
|
-
|
|
306
|
+
if (status === TokenStatusValues2.Failed) {
|
|
307
|
+
return { status, cleanup };
|
|
308
|
+
}
|
|
309
|
+
if (typeof fields.access !== "string" || !fields.access.trim()) {
|
|
272
310
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidResponse, cleanup);
|
|
311
|
+
}
|
|
273
312
|
return {
|
|
274
313
|
status,
|
|
275
314
|
tokens: {
|
|
@@ -298,28 +337,31 @@ function timestamp(value) {
|
|
|
298
337
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= 864e13;
|
|
299
338
|
}
|
|
300
339
|
function methods(value) {
|
|
301
|
-
return Array.isArray(value) && value.every(
|
|
302
|
-
(method) => typeof method === "string" && isVerificationMethod(method)
|
|
303
|
-
);
|
|
340
|
+
return Array.isArray(value) && value.every((method) => typeof method === "string" && isVerificationMethod(method));
|
|
304
341
|
}
|
|
305
342
|
function supportedMethod(value, accountType) {
|
|
306
343
|
return typeof value === "string" && isVerificationMethod(value) && (value !== VerificationMethodValues.UnknownMethod || accountType === "Email");
|
|
307
344
|
}
|
|
308
345
|
function validateStartInput(input) {
|
|
309
|
-
if (!isRecord(input) || !isRecord(input.account) || typeof input.account.accountType !== "string" || !isSendCodeAccountType(input.account.accountType) || typeof input.account.accountName !== "string" || !input.account.accountName.trim())
|
|
346
|
+
if (!isRecord(input) || !isRecord(input.account) || typeof input.account.accountType !== "string" || !isSendCodeAccountType(input.account.accountType) || typeof input.account.accountName !== "string" || !input.account.accountName.trim()) {
|
|
310
347
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidInput);
|
|
348
|
+
}
|
|
311
349
|
for (const field of ["language", "captcha", "inviteSessionId"]) {
|
|
312
|
-
if (input[field] !== void 0 && typeof input[field] !== "string")
|
|
350
|
+
if (input[field] !== void 0 && typeof input[field] !== "string") {
|
|
313
351
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidInput);
|
|
352
|
+
}
|
|
314
353
|
}
|
|
315
|
-
if (input.regionStorageId !== void 0 && !attempts(input.regionStorageId) || input.captchaType !== void 0 && (typeof input.captchaType !== "string" || !isAuthCaptchaType(input.captchaType)) || input.preferredMethod !== void 0 && (typeof input.preferredMethod !== "string" || !isVerificationMethod(input.preferredMethod)) || input.supportedMethods !== void 0 && !methods(input.supportedMethods))
|
|
354
|
+
if (input.regionStorageId !== void 0 && !attempts(input.regionStorageId) || input.captchaType !== void 0 && (typeof input.captchaType !== "string" || !isAuthCaptchaType(input.captchaType)) || input.preferredMethod !== void 0 && (typeof input.preferredMethod !== "string" || !isVerificationMethod(input.preferredMethod)) || input.supportedMethods !== void 0 && !methods(input.supportedMethods)) {
|
|
316
355
|
throw otpFailure(TorrowSdkErrorCategory2.InvalidInput);
|
|
356
|
+
}
|
|
317
357
|
}
|
|
318
358
|
function validateChallenge(value) {
|
|
319
|
-
if (!isRecord(value) || typeof value.sessionId !== "string" || !value.sessionId.trim() || typeof value.accountType !== "string" || !isSendCodeAccountType(value.accountType) || !supportedMethod(value.usedMethod, value.accountType) || value.phase !== "Pending" /* Pending */ && value.phase !== "AwaitingCode" /* AwaitingCode */ || !timestamp(value.expiresAtMs) || value.expiresAtMs <= Date.now() || value.phase === "Pending" /* Pending */ !== (value.usedMethod === VerificationMethodValues.MtsMobileId))
|
|
359
|
+
if (!isRecord(value) || typeof value.sessionId !== "string" || !value.sessionId.trim() || typeof value.accountType !== "string" || !isSendCodeAccountType(value.accountType) || !supportedMethod(value.usedMethod, value.accountType) || value.phase !== "Pending" /* Pending */ && value.phase !== "AwaitingCode" /* AwaitingCode */ || !timestamp(value.expiresAtMs) || value.expiresAtMs <= Date.now() || value.phase === "Pending" /* Pending */ !== (value.usedMethod === VerificationMethodValues.MtsMobileId)) {
|
|
320
360
|
throw otpFailure(OtpErrorReason2.InvalidChallenge);
|
|
321
|
-
|
|
361
|
+
}
|
|
362
|
+
if (value.codeLength !== void 0 && !codeLength(value.codeLength) || value.pollIntervalSeconds !== void 0 && !positive(value.pollIntervalSeconds) || value.attemptsRemaining !== void 0 && !attempts(value.attemptsRemaining) || value.nextSendAtMs !== void 0 && !timestamp(value.nextSendAtMs) || value.availableMethods !== void 0 && !methods(value.availableMethods)) {
|
|
322
363
|
throw otpFailure(OtpErrorReason2.InvalidChallenge);
|
|
364
|
+
}
|
|
323
365
|
return {
|
|
324
366
|
sessionId: value.sessionId.trim(),
|
|
325
367
|
accountType: value.accountType,
|
|
@@ -357,9 +399,7 @@ var MemoryTokenStorage = class {
|
|
|
357
399
|
function resolveLocalStorage() {
|
|
358
400
|
const g = globalThis;
|
|
359
401
|
if (!g.localStorage || typeof g.localStorage.getItem !== "function") {
|
|
360
|
-
throw new Error(
|
|
361
|
-
"LocalStorageTokenStorage: globalThis.localStorage is not available in this environment"
|
|
362
|
-
);
|
|
402
|
+
throw new Error("LocalStorageTokenStorage: globalThis.localStorage is not available in this environment");
|
|
363
403
|
}
|
|
364
404
|
return g.localStorage;
|
|
365
405
|
}
|
|
@@ -378,9 +418,13 @@ var LocalStorageTokenStorage = class {
|
|
|
378
418
|
async load() {
|
|
379
419
|
try {
|
|
380
420
|
const raw = this.store.getItem(this.key);
|
|
381
|
-
if (!raw?.trim())
|
|
421
|
+
if (!raw?.trim()) {
|
|
422
|
+
return {};
|
|
423
|
+
}
|
|
382
424
|
const parsed = JSON.parse(raw);
|
|
383
|
-
if (parsed === null || typeof parsed !== "object")
|
|
425
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
426
|
+
return {};
|
|
427
|
+
}
|
|
384
428
|
const o = parsed;
|
|
385
429
|
return {
|
|
386
430
|
accessToken: typeof o.accessToken === "string" ? o.accessToken : void 0,
|
|
@@ -421,9 +465,15 @@ import {
|
|
|
421
465
|
// ../../src/auth-session/auth-session-not-ready.ts
|
|
422
466
|
import { AuthSessionErrorReason, TorrowSdkError as TorrowSdkError2, TorrowSdkErrorDomain as TorrowSdkErrorDomain2 } from "@torrow/sdk-client";
|
|
423
467
|
function isAuthSessionNotReadyYet(error) {
|
|
424
|
-
if (!(error instanceof TorrowSdkError2))
|
|
425
|
-
|
|
426
|
-
|
|
468
|
+
if (!(error instanceof TorrowSdkError2)) {
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
if (error.detail?.domain === TorrowSdkErrorDomain2.AuthSession && error.detail.reason === AuthSessionErrorReason.SessionNotReady) {
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
if (!error.http) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
427
477
|
const body = error.getSensitiveDetails().body;
|
|
428
478
|
const text = [error.http.apiErrorName, typeof body === "string" ? body : JSON.stringify(body ?? "")].join(" ").toLowerCase();
|
|
429
479
|
return text.includes("session is not ready") || text.includes("unauthorized_client");
|
|
@@ -462,14 +512,12 @@ var SessionFailureStage = /* @__PURE__ */ ((SessionFailureStage2) => {
|
|
|
462
512
|
return SessionFailureStage2;
|
|
463
513
|
})(SessionFailureStage || {});
|
|
464
514
|
function sessionFailure(error, context) {
|
|
465
|
-
const detail = {
|
|
515
|
+
const detail = {
|
|
516
|
+
domain: TorrowSdkErrorDomain3.AuthSession,
|
|
517
|
+
...context.reason ? { reason: context.reason } : {}
|
|
518
|
+
};
|
|
466
519
|
if (context.category !== void 0) {
|
|
467
|
-
return new TorrowSdkError3({
|
|
468
|
-
...context,
|
|
469
|
-
category: context.category,
|
|
470
|
-
detail,
|
|
471
|
-
sensitive: { cause: error }
|
|
472
|
-
});
|
|
520
|
+
return new TorrowSdkError3({ ...context, category: context.category, detail, sensitive: { cause: error } });
|
|
473
521
|
}
|
|
474
522
|
if (error instanceof TorrowSdkError3) {
|
|
475
523
|
return error.withContext({
|
|
@@ -491,8 +539,12 @@ function sessionFailure(error, context) {
|
|
|
491
539
|
|
|
492
540
|
// ../../src/auth-session/fetch-with-401-retry.ts
|
|
493
541
|
function requestUrl(input) {
|
|
494
|
-
if (typeof input === "string")
|
|
495
|
-
|
|
542
|
+
if (typeof input === "string") {
|
|
543
|
+
return input;
|
|
544
|
+
}
|
|
545
|
+
if (input instanceof URL) {
|
|
546
|
+
return input.href;
|
|
547
|
+
}
|
|
496
548
|
return input.url;
|
|
497
549
|
}
|
|
498
550
|
function isAuthIdentityUrl(url) {
|
|
@@ -502,9 +554,13 @@ function createFetchWith401Retry(options) {
|
|
|
502
554
|
const baseFetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
503
555
|
const wrapped = async (input, init) => {
|
|
504
556
|
const first = await baseFetch(input, init);
|
|
505
|
-
if (first.status !== 401)
|
|
557
|
+
if (first.status !== 401) {
|
|
558
|
+
return first;
|
|
559
|
+
}
|
|
506
560
|
const url = requestUrl(input);
|
|
507
|
-
if (isAuthIdentityUrl(url))
|
|
561
|
+
if (isAuthIdentityUrl(url)) {
|
|
562
|
+
return first;
|
|
563
|
+
}
|
|
508
564
|
await options.refresh();
|
|
509
565
|
const token = await options.getAccessToken();
|
|
510
566
|
const headers = new Headers(init?.headers);
|
|
@@ -521,18 +577,28 @@ function createFetchWith401Retry(options) {
|
|
|
521
577
|
// ../../src/auth-session/merge-tokens.ts
|
|
522
578
|
import { isTokenRespReadyStatus } from "@torrow/sdk-client";
|
|
523
579
|
function normalizeTokenResp(raw) {
|
|
524
|
-
if (raw === null || raw === void 0)
|
|
580
|
+
if (raw === null || raw === void 0) {
|
|
581
|
+
return {};
|
|
582
|
+
}
|
|
525
583
|
if (typeof raw === "string") {
|
|
526
584
|
const t = raw.trim();
|
|
527
585
|
return t ? { accessToken: t } : {};
|
|
528
586
|
}
|
|
529
|
-
if (typeof raw !== "object")
|
|
587
|
+
if (typeof raw !== "object") {
|
|
588
|
+
return {};
|
|
589
|
+
}
|
|
530
590
|
const o = raw;
|
|
531
591
|
const { access, refresh, expiration: expRaw, status: statusRaw } = tokenResponseFields(o);
|
|
532
592
|
const out = {};
|
|
533
|
-
if (typeof access === "string" && access.trim())
|
|
534
|
-
|
|
535
|
-
|
|
593
|
+
if (typeof access === "string" && access.trim()) {
|
|
594
|
+
out.accessToken = access.trim();
|
|
595
|
+
}
|
|
596
|
+
if (typeof refresh === "string" && refresh.trim()) {
|
|
597
|
+
out.refreshToken = refresh.trim();
|
|
598
|
+
}
|
|
599
|
+
if (typeof expRaw === "number" && Number.isFinite(expRaw)) {
|
|
600
|
+
out.expiration = expRaw;
|
|
601
|
+
}
|
|
536
602
|
if (typeof statusRaw === "string" && statusRaw.trim()) {
|
|
537
603
|
out.status = statusRaw.trim();
|
|
538
604
|
}
|
|
@@ -551,12 +617,20 @@ function decodeJwtJsonSegment(segment) {
|
|
|
551
617
|
}
|
|
552
618
|
function accessExpiresAtMsFromJwt(accessToken) {
|
|
553
619
|
const parts = accessToken.split(".");
|
|
554
|
-
if (parts.length < 2)
|
|
555
|
-
|
|
620
|
+
if (parts.length < 2) {
|
|
621
|
+
return void 0;
|
|
622
|
+
}
|
|
623
|
+
if (decodeJwtJsonSegment(parts[0]) === void 0) {
|
|
624
|
+
return void 0;
|
|
625
|
+
}
|
|
556
626
|
const payload = decodeJwtJsonSegment(parts[1]);
|
|
557
|
-
if (payload === null || typeof payload !== "object")
|
|
627
|
+
if (payload === null || typeof payload !== "object") {
|
|
628
|
+
return void 0;
|
|
629
|
+
}
|
|
558
630
|
const exp = payload.exp;
|
|
559
|
-
if (typeof exp !== "number" || !Number.isFinite(exp))
|
|
631
|
+
if (typeof exp !== "number" || !Number.isFinite(exp)) {
|
|
632
|
+
return void 0;
|
|
633
|
+
}
|
|
560
634
|
return exp * 1e3;
|
|
561
635
|
}
|
|
562
636
|
function accessTokenLooksLikeJwt(accessToken) {
|
|
@@ -591,9 +665,7 @@ function mergeAuthTokens(prev, tokens, opts) {
|
|
|
591
665
|
function assertTokenRespReadyForStorage(tokens, context) {
|
|
592
666
|
const status = tokens.status;
|
|
593
667
|
if (!isTokenRespReadyStatus(status)) {
|
|
594
|
-
throw new Error(
|
|
595
|
-
`${context}: TokenResp.status=${status} (\u043E\u0436\u0438\u0434\u0430\u043B\u0441\u044F TokenReady). \u0422\u043E\u043A\u0435\u043D\u044B \u043D\u0435 \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u0435\u043C.`
|
|
596
|
-
);
|
|
668
|
+
throw new Error(`${context}: TokenResp.status=${status} (\u043E\u0436\u0438\u0434\u0430\u043B\u0441\u044F TokenReady). \u0422\u043E\u043A\u0435\u043D\u044B \u043D\u0435 \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u0435\u043C.`);
|
|
597
669
|
}
|
|
598
670
|
if (!tokens.accessToken?.trim() && !tokens.refreshToken?.trim()) {
|
|
599
671
|
throw new Error(`${context}: TokenResp \u0431\u0435\u0437 accessToken \u0438 refreshToken.`);
|
|
@@ -605,9 +677,13 @@ function assertTokenRespReadyForStorage(tokens, context) {
|
|
|
605
677
|
var DEFAULT_SKEW_MS = 3e4;
|
|
606
678
|
var SESSION_CLOSED_MESSAGE = "TokenSession: session closed (logout)";
|
|
607
679
|
function defaultOnRefreshFailure(err) {
|
|
608
|
-
if (!(err instanceof TorrowSdkError4) || !err.http)
|
|
680
|
+
if (!(err instanceof TorrowSdkError4) || !err.http) {
|
|
681
|
+
return "keep";
|
|
682
|
+
}
|
|
609
683
|
const s = err.http?.status;
|
|
610
|
-
if (s === 429 || s === 502 || s === 503 || s === 504)
|
|
684
|
+
if (s === 429 || s === 502 || s === 503 || s === 504) {
|
|
685
|
+
return "keep";
|
|
686
|
+
}
|
|
611
687
|
return "clear";
|
|
612
688
|
}
|
|
613
689
|
var TokenSession = class _TokenSession {
|
|
@@ -645,7 +721,11 @@ var TokenSession = class _TokenSession {
|
|
|
645
721
|
category: TorrowSdkErrorCategory4.StorageFailure
|
|
646
722
|
});
|
|
647
723
|
}
|
|
648
|
-
effects.push({
|
|
724
|
+
effects.push({
|
|
725
|
+
area: TorrowSdkEffectArea.SessionMemory,
|
|
726
|
+
step: AuthSessionEffectStep.SetTokens,
|
|
727
|
+
state: TorrowSdkEffectState.Applied
|
|
728
|
+
});
|
|
649
729
|
failureAt = "InitializeDevice" /* InitializeDevice */;
|
|
650
730
|
if (!session.tokenSnapshot.deviceId?.trim()) {
|
|
651
731
|
const id = session.resolveDeviceInfo().deviceId?.trim();
|
|
@@ -700,7 +780,9 @@ var TokenSession = class _TokenSession {
|
|
|
700
780
|
}
|
|
701
781
|
/** Получить access после проактивного refresh; closed возвращает undefined без записи. */
|
|
702
782
|
async getAccessToken() {
|
|
703
|
-
if (this.closed)
|
|
783
|
+
if (this.closed) {
|
|
784
|
+
return void 0;
|
|
785
|
+
}
|
|
704
786
|
try {
|
|
705
787
|
await this.ensureFresh();
|
|
706
788
|
} catch (error) {
|
|
@@ -723,7 +805,11 @@ var TokenSession = class _TokenSession {
|
|
|
723
805
|
try {
|
|
724
806
|
await this.applyTokenRespUnlocked(tokens, opts, effects);
|
|
725
807
|
} catch (error) {
|
|
726
|
-
throw sessionFailure(error, {
|
|
808
|
+
throw sessionFailure(error, {
|
|
809
|
+
operation: "TokenSession.applyTokenResp",
|
|
810
|
+
failureAt: "ApplyTokens" /* ApplyTokens */,
|
|
811
|
+
effects
|
|
812
|
+
});
|
|
727
813
|
}
|
|
728
814
|
});
|
|
729
815
|
}
|
|
@@ -734,7 +820,11 @@ var TokenSession = class _TokenSession {
|
|
|
734
820
|
try {
|
|
735
821
|
await this.clearTokensUnlocked(effects);
|
|
736
822
|
} catch (error) {
|
|
737
|
-
throw sessionFailure(error, {
|
|
823
|
+
throw sessionFailure(error, {
|
|
824
|
+
operation: "TokenSession.clearTokens",
|
|
825
|
+
failureAt: "ClearTokens" /* ClearTokens */,
|
|
826
|
+
effects
|
|
827
|
+
});
|
|
738
828
|
}
|
|
739
829
|
});
|
|
740
830
|
}
|
|
@@ -746,7 +836,11 @@ var TokenSession = class _TokenSession {
|
|
|
746
836
|
const effects = [];
|
|
747
837
|
await this.runExclusive(async () => {
|
|
748
838
|
this.closed = true;
|
|
749
|
-
effects.push({
|
|
839
|
+
effects.push({
|
|
840
|
+
area: TorrowSdkEffectArea.SessionMemory,
|
|
841
|
+
step: AuthSessionEffectStep.CloseSession,
|
|
842
|
+
state: TorrowSdkEffectState.Applied
|
|
843
|
+
});
|
|
750
844
|
const refresh = this.tokenSnapshot.refreshToken?.trim();
|
|
751
845
|
if (refresh) {
|
|
752
846
|
let state = TorrowSdkEffectState.Applied;
|
|
@@ -763,7 +857,11 @@ var TokenSession = class _TokenSession {
|
|
|
763
857
|
try {
|
|
764
858
|
await this.clearTokensUnlocked(effects);
|
|
765
859
|
} catch (error) {
|
|
766
|
-
throw sessionFailure(error, {
|
|
860
|
+
throw sessionFailure(error, {
|
|
861
|
+
operation: "TokenSession.logout",
|
|
862
|
+
failureAt: "ClearTokens" /* ClearTokens */,
|
|
863
|
+
effects
|
|
864
|
+
});
|
|
767
865
|
}
|
|
768
866
|
});
|
|
769
867
|
}
|
|
@@ -799,7 +897,9 @@ var TokenSession = class _TokenSession {
|
|
|
799
897
|
const identity = this.identityClient();
|
|
800
898
|
let resp;
|
|
801
899
|
try {
|
|
802
|
-
resp = normalizeTokenResp(
|
|
900
|
+
resp = normalizeTokenResp(
|
|
901
|
+
await requestAuthToken(identity, { sessionId, code, scopes, deviceInfo }, args.signal)
|
|
902
|
+
);
|
|
803
903
|
} catch (error) {
|
|
804
904
|
effects.push({
|
|
805
905
|
area: TorrowSdkEffectArea.Remote,
|
|
@@ -818,7 +918,11 @@ var TokenSession = class _TokenSession {
|
|
|
818
918
|
}
|
|
819
919
|
failureAt = "ValidateTokens" /* ValidateTokens */;
|
|
820
920
|
if (tokenTransition(resp.status, true) !== TokenStatusValues3.TokenReady) {
|
|
821
|
-
effects.push({
|
|
921
|
+
effects.push({
|
|
922
|
+
area: TorrowSdkEffectArea.Remote,
|
|
923
|
+
step: AuthSessionEffectStep.IssueTokens,
|
|
924
|
+
state: TorrowSdkEffectState.Unknown
|
|
925
|
+
});
|
|
822
926
|
throw sessionFailure(void 0, {
|
|
823
927
|
operation: "TokenSession.requestTokenWithCode",
|
|
824
928
|
failureAt,
|
|
@@ -831,7 +935,11 @@ var TokenSession = class _TokenSession {
|
|
|
831
935
|
try {
|
|
832
936
|
ready = assertTokenRespReadyForStorage(resp, "TokenSession.requestTokenWithCode");
|
|
833
937
|
} catch (error) {
|
|
834
|
-
effects.push({
|
|
938
|
+
effects.push({
|
|
939
|
+
area: TorrowSdkEffectArea.Remote,
|
|
940
|
+
step: AuthSessionEffectStep.IssueTokens,
|
|
941
|
+
state: TorrowSdkEffectState.Unknown
|
|
942
|
+
});
|
|
835
943
|
throw sessionFailure(error, {
|
|
836
944
|
operation: "TokenSession.requestTokenWithCode",
|
|
837
945
|
failureAt,
|
|
@@ -839,7 +947,11 @@ var TokenSession = class _TokenSession {
|
|
|
839
947
|
category: TorrowSdkErrorCategory4.InvalidResponse
|
|
840
948
|
});
|
|
841
949
|
}
|
|
842
|
-
effects.push({
|
|
950
|
+
effects.push({
|
|
951
|
+
area: TorrowSdkEffectArea.Remote,
|
|
952
|
+
step: AuthSessionEffectStep.IssueTokens,
|
|
953
|
+
state: TorrowSdkEffectState.Applied
|
|
954
|
+
});
|
|
843
955
|
failureAt = "ApplyTokens" /* ApplyTokens */;
|
|
844
956
|
await this.runExclusive(() => this.applyTokenRespUnlocked(ready, { replace: true }, effects));
|
|
845
957
|
return ready;
|
|
@@ -867,10 +979,16 @@ var TokenSession = class _TokenSession {
|
|
|
867
979
|
});
|
|
868
980
|
}
|
|
869
981
|
const result = await this.refreshWithFailurePolicy(effects);
|
|
870
|
-
if (result.outcome === "refreshed")
|
|
982
|
+
if (result.outcome === "refreshed") {
|
|
983
|
+
return result.resp;
|
|
984
|
+
}
|
|
871
985
|
throw result.error ?? this.lastRefreshError;
|
|
872
986
|
} catch (error) {
|
|
873
|
-
throw sessionFailure(error, {
|
|
987
|
+
throw sessionFailure(error, {
|
|
988
|
+
operation: "TokenSession.refresh",
|
|
989
|
+
failureAt: "RefreshTokens" /* RefreshTokens */,
|
|
990
|
+
effects
|
|
991
|
+
});
|
|
874
992
|
}
|
|
875
993
|
});
|
|
876
994
|
}
|
|
@@ -881,7 +999,11 @@ var TokenSession = class _TokenSession {
|
|
|
881
999
|
try {
|
|
882
1000
|
await this.ensureFreshImpl(effects);
|
|
883
1001
|
} catch (error) {
|
|
884
|
-
throw sessionFailure(error, {
|
|
1002
|
+
throw sessionFailure(error, {
|
|
1003
|
+
operation: "TokenSession.ensureFresh",
|
|
1004
|
+
failureAt: "RefreshTokens" /* RefreshTokens */,
|
|
1005
|
+
effects
|
|
1006
|
+
});
|
|
885
1007
|
}
|
|
886
1008
|
});
|
|
887
1009
|
}
|
|
@@ -914,7 +1036,11 @@ var TokenSession = class _TokenSession {
|
|
|
914
1036
|
// Host TTL survives refresh without expiration only while still fresh (incl. skew); else cleared → opaque until 401.
|
|
915
1037
|
keepPrevTtlIfExpiresAfterMs: Date.now() + (this.opts.accessTokenSkewMs ?? DEFAULT_SKEW_MS)
|
|
916
1038
|
});
|
|
917
|
-
effects.push({
|
|
1039
|
+
effects.push({
|
|
1040
|
+
area: TorrowSdkEffectArea.SessionMemory,
|
|
1041
|
+
step: AuthSessionEffectStep.SetTokens,
|
|
1042
|
+
state: TorrowSdkEffectState.Applied
|
|
1043
|
+
});
|
|
918
1044
|
await this.persist(true, effects);
|
|
919
1045
|
}
|
|
920
1046
|
async clearTokensUnlocked(effects = []) {
|
|
@@ -924,7 +1050,11 @@ var TokenSession = class _TokenSession {
|
|
|
924
1050
|
refreshToken: void 0,
|
|
925
1051
|
accessExpiresAtMs: void 0
|
|
926
1052
|
};
|
|
927
|
-
effects.push({
|
|
1053
|
+
effects.push({
|
|
1054
|
+
area: TorrowSdkEffectArea.SessionMemory,
|
|
1055
|
+
step: AuthSessionEffectStep.ClearTokens,
|
|
1056
|
+
state: TorrowSdkEffectState.Applied
|
|
1057
|
+
});
|
|
928
1058
|
await this.persist(true, effects, true);
|
|
929
1059
|
}
|
|
930
1060
|
/** Caller must hold `runExclusive`. `refreshWithFailurePolicy` skips when no refreshToken; guard here is intentional defense-in-depth. */
|
|
@@ -955,7 +1085,11 @@ var TokenSession = class _TokenSession {
|
|
|
955
1085
|
try {
|
|
956
1086
|
assertTokenRespReadyForStorage(normalized, "TokenSession.refresh");
|
|
957
1087
|
} catch (error) {
|
|
958
|
-
effects.push({
|
|
1088
|
+
effects.push({
|
|
1089
|
+
area: TorrowSdkEffectArea.Remote,
|
|
1090
|
+
step: AuthSessionEffectStep.RefreshTokens,
|
|
1091
|
+
state: TorrowSdkEffectState.Unknown
|
|
1092
|
+
});
|
|
959
1093
|
throw sessionFailure(error, {
|
|
960
1094
|
operation: "TokenSession",
|
|
961
1095
|
failureAt: "ValidateTokens" /* ValidateTokens */,
|
|
@@ -963,19 +1097,29 @@ var TokenSession = class _TokenSession {
|
|
|
963
1097
|
category: TorrowSdkErrorCategory4.InvalidResponse
|
|
964
1098
|
});
|
|
965
1099
|
}
|
|
966
|
-
effects.push({
|
|
1100
|
+
effects.push({
|
|
1101
|
+
area: TorrowSdkEffectArea.Remote,
|
|
1102
|
+
step: AuthSessionEffectStep.RefreshTokens,
|
|
1103
|
+
state: TorrowSdkEffectState.Applied
|
|
1104
|
+
});
|
|
967
1105
|
await this.applyTokenRespUnlocked(resp, void 0, effects);
|
|
968
1106
|
return resp;
|
|
969
1107
|
}
|
|
970
1108
|
/** Caller must hold `runExclusive`; сведения принадлежат только текущей операции. */
|
|
971
1109
|
async refreshWithFailurePolicy(effects = []) {
|
|
972
|
-
if (this.closed || !this.tokenSnapshot.refreshToken?.trim())
|
|
1110
|
+
if (this.closed || !this.tokenSnapshot.refreshToken?.trim()) {
|
|
1111
|
+
return { outcome: "unchanged" };
|
|
1112
|
+
}
|
|
973
1113
|
try {
|
|
974
1114
|
const resp = await this.refreshUnlocked(effects);
|
|
975
1115
|
this.lastRefreshError = void 0;
|
|
976
1116
|
return { outcome: "refreshed", resp };
|
|
977
1117
|
} catch (cause) {
|
|
978
|
-
const error = sessionFailure(cause, {
|
|
1118
|
+
const error = sessionFailure(cause, {
|
|
1119
|
+
operation: "TokenSession",
|
|
1120
|
+
failureAt: "RefreshTokens" /* RefreshTokens */,
|
|
1121
|
+
effects
|
|
1122
|
+
});
|
|
979
1123
|
this.lastRefreshError = error.withContext({ effects: void 0, operation: void 0, failureAt: void 0 });
|
|
980
1124
|
let action;
|
|
981
1125
|
try {
|
|
@@ -989,8 +1133,12 @@ var TokenSession = class _TokenSession {
|
|
|
989
1133
|
reason: AuthSessionErrorReason2.CallbackFailed
|
|
990
1134
|
});
|
|
991
1135
|
}
|
|
992
|
-
if (action === "throw")
|
|
993
|
-
|
|
1136
|
+
if (action === "throw") {
|
|
1137
|
+
throw error;
|
|
1138
|
+
}
|
|
1139
|
+
if (action === "keep") {
|
|
1140
|
+
return { outcome: "unchanged", error };
|
|
1141
|
+
}
|
|
994
1142
|
await this.clearTokensUnlocked(effects);
|
|
995
1143
|
return { outcome: "cleared", error: error.withContext({ effects }) };
|
|
996
1144
|
}
|
|
@@ -1009,7 +1157,9 @@ var TokenSession = class _TokenSession {
|
|
|
1009
1157
|
}
|
|
1010
1158
|
}
|
|
1011
1159
|
async ensureFreshImpl(effects = []) {
|
|
1012
|
-
if (this.closed)
|
|
1160
|
+
if (this.closed) {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1013
1163
|
const skew = this.opts.accessTokenSkewMs ?? DEFAULT_SKEW_MS;
|
|
1014
1164
|
const access = this.tokenSnapshot.accessToken?.trim() ?? "";
|
|
1015
1165
|
const expires = this.tokenSnapshot.accessExpiresAtMs ?? 0;
|
|
@@ -1045,7 +1195,9 @@ var TokenSession = class _TokenSession {
|
|
|
1045
1195
|
return "authenticated";
|
|
1046
1196
|
}
|
|
1047
1197
|
const hasAny = Boolean(access) || Boolean(this.tokenSnapshot.refreshToken?.trim()) || typeof expires === "number" && expires > 0;
|
|
1048
|
-
if (!hasAny)
|
|
1198
|
+
if (!hasAny) {
|
|
1199
|
+
return "unauthenticated";
|
|
1200
|
+
}
|
|
1049
1201
|
return "expired";
|
|
1050
1202
|
}
|
|
1051
1203
|
emitStatusChange() {
|
|
@@ -1077,7 +1229,9 @@ var TokenSession = class _TokenSession {
|
|
|
1077
1229
|
fetchImpl = createFetchWith401Retry({
|
|
1078
1230
|
fetch: this.opts.fetch,
|
|
1079
1231
|
getAccessToken: async () => {
|
|
1080
|
-
if (this.closed)
|
|
1232
|
+
if (this.closed) {
|
|
1233
|
+
return void 0;
|
|
1234
|
+
}
|
|
1081
1235
|
return this.tokenSnapshot.accessToken?.trim() || void 0;
|
|
1082
1236
|
},
|
|
1083
1237
|
refresh: async () => {
|
|
@@ -1098,9 +1252,7 @@ var TokenSession = class _TokenSession {
|
|
|
1098
1252
|
fetch: fetchImpl,
|
|
1099
1253
|
defaultHeaders: this.opts.defaultHeaders,
|
|
1100
1254
|
userAgent: this.opts.userAgent,
|
|
1101
|
-
authIdentityBasic: appCredentialsToAuthIdentityBasic(
|
|
1102
|
-
resolveAppCredentials(this.opts.appCredentials)
|
|
1103
|
-
),
|
|
1255
|
+
authIdentityBasic: appCredentialsToAuthIdentityBasic(resolveAppCredentials(this.opts.appCredentials)),
|
|
1104
1256
|
getAccessToken: async () => this.getAccessToken()
|
|
1105
1257
|
});
|
|
1106
1258
|
}
|
|
@@ -1122,7 +1274,9 @@ var TokenSession = class _TokenSession {
|
|
|
1122
1274
|
});
|
|
1123
1275
|
}
|
|
1124
1276
|
effects[effects.length - 1] = { ...effect, state: TorrowSdkEffectState.Applied };
|
|
1125
|
-
if (emitStatus)
|
|
1277
|
+
if (emitStatus) {
|
|
1278
|
+
this.emitStatusChange();
|
|
1279
|
+
}
|
|
1126
1280
|
}
|
|
1127
1281
|
};
|
|
1128
1282
|
|
|
@@ -1200,15 +1354,28 @@ async function runLinkLogin(session, options) {
|
|
|
1200
1354
|
});
|
|
1201
1355
|
throw error;
|
|
1202
1356
|
}
|
|
1203
|
-
effects.push({
|
|
1357
|
+
effects.push({
|
|
1358
|
+
area: TorrowSdkEffectArea2.Remote,
|
|
1359
|
+
step: AuthSessionEffectStep2.CreateAuthSession,
|
|
1360
|
+
state: TorrowSdkEffectState2.Unknown
|
|
1361
|
+
});
|
|
1204
1362
|
failureAt = "ValidateResponse" /* ValidateResponse */;
|
|
1205
1363
|
const sessionId = createResp.sessionId?.trim();
|
|
1206
1364
|
const code = createResp.code?.trim();
|
|
1207
1365
|
const authUrl = createResp.authUrl?.trim();
|
|
1208
1366
|
if (!sessionId || !code || !authUrl) {
|
|
1209
|
-
throw sessionFailure(void 0, {
|
|
1367
|
+
throw sessionFailure(void 0, {
|
|
1368
|
+
operation: "TorrowAuth.loginWithLink",
|
|
1369
|
+
failureAt,
|
|
1370
|
+
effects: [],
|
|
1371
|
+
category: TorrowSdkErrorCategory5.InvalidResponse
|
|
1372
|
+
});
|
|
1210
1373
|
}
|
|
1211
|
-
effects[effects.length - 1] = {
|
|
1374
|
+
effects[effects.length - 1] = {
|
|
1375
|
+
area: TorrowSdkEffectArea2.Remote,
|
|
1376
|
+
step: AuthSessionEffectStep2.CreateAuthSession,
|
|
1377
|
+
state: TorrowSdkEffectState2.Applied
|
|
1378
|
+
};
|
|
1212
1379
|
failureAt = "OnLink" /* OnLink */;
|
|
1213
1380
|
await options.onLink(authUrl);
|
|
1214
1381
|
const scopes = options.scopes && options.scopes.length > 0 ? options.scopes : [...DefaultAuthScopes3];
|
|
@@ -1226,9 +1393,17 @@ async function runLinkLogin(session, options) {
|
|
|
1226
1393
|
signal: options.signal
|
|
1227
1394
|
});
|
|
1228
1395
|
} catch (e) {
|
|
1229
|
-
if (!isAuthSessionNotReadyYet(e))
|
|
1396
|
+
if (!isAuthSessionNotReadyYet(e)) {
|
|
1397
|
+
throw e;
|
|
1398
|
+
}
|
|
1230
1399
|
if (Date.now() >= deadline) {
|
|
1231
|
-
throw sessionFailure(e, {
|
|
1400
|
+
throw sessionFailure(e, {
|
|
1401
|
+
operation: "TorrowAuth.loginWithLink",
|
|
1402
|
+
failureAt,
|
|
1403
|
+
effects: [],
|
|
1404
|
+
category: TorrowSdkErrorCategory5.InvalidState,
|
|
1405
|
+
reason: AuthSessionErrorReason3.SessionNotReady
|
|
1406
|
+
});
|
|
1232
1407
|
}
|
|
1233
1408
|
await sleepMs(intervalMs, options.signal);
|
|
1234
1409
|
}
|
|
@@ -1239,7 +1414,10 @@ async function runLinkLogin(session, options) {
|
|
|
1239
1414
|
throw sessionFailure(error, {
|
|
1240
1415
|
operation: "TorrowAuth.loginWithLink",
|
|
1241
1416
|
failureAt,
|
|
1242
|
-
effects: [
|
|
1417
|
+
effects: [
|
|
1418
|
+
...effects,
|
|
1419
|
+
...failureAt === "PollTokens" /* PollTokens */ && error instanceof TorrowSdkError5 ? error.effects ?? [] : []
|
|
1420
|
+
],
|
|
1243
1421
|
...callback ? { category: TorrowSdkErrorCategory5.Unknown, reason: AuthSessionErrorReason3.CallbackFailed } : {}
|
|
1244
1422
|
});
|
|
1245
1423
|
}
|
|
@@ -1377,7 +1555,9 @@ function scopesOrDefault2(scopes) {
|
|
|
1377
1555
|
return scopes && scopes.length > 0 ? scopes : [...DefaultAuthScopes5];
|
|
1378
1556
|
}
|
|
1379
1557
|
function effectiveCodeLength(raw, fallback) {
|
|
1380
|
-
if (typeof raw === "number" && raw > 0)
|
|
1558
|
+
if (typeof raw === "number" && raw > 0) {
|
|
1559
|
+
return raw;
|
|
1560
|
+
}
|
|
1381
1561
|
return fallback > 0 ? fallback : void 0;
|
|
1382
1562
|
}
|
|
1383
1563
|
async function requestTokenOrThrow(client, body, signal) {
|
|
@@ -1413,13 +1593,21 @@ async function runOtpLoginWithEffects(client, options) {
|
|
|
1413
1593
|
});
|
|
1414
1594
|
throw otpHttpFailure(error);
|
|
1415
1595
|
}
|
|
1416
|
-
effects.push({
|
|
1596
|
+
effects.push({
|
|
1597
|
+
area: TorrowSdkEffectArea3.Remote,
|
|
1598
|
+
step: AuthSessionEffectStep3.SendCode,
|
|
1599
|
+
state: TorrowSdkEffectState3.Unknown
|
|
1600
|
+
});
|
|
1417
1601
|
failureAt = "ValidateResponse" /* ValidateResponse */;
|
|
1418
1602
|
const sessionId = sendResp.sessionId?.trim();
|
|
1419
1603
|
if (!sessionId) {
|
|
1420
1604
|
throw otpFailure(TorrowSdkErrorCategory7.InvalidResponse);
|
|
1421
1605
|
}
|
|
1422
|
-
effects[effects.length - 1] = {
|
|
1606
|
+
effects[effects.length - 1] = {
|
|
1607
|
+
area: TorrowSdkEffectArea3.Remote,
|
|
1608
|
+
step: AuthSessionEffectStep3.SendCode,
|
|
1609
|
+
state: TorrowSdkEffectState3.Applied
|
|
1610
|
+
};
|
|
1423
1611
|
const result = {
|
|
1424
1612
|
accountName,
|
|
1425
1613
|
accountType,
|
|
@@ -1456,7 +1644,11 @@ async function runOtpLoginWithEffects(client, options) {
|
|
|
1456
1644
|
return code2;
|
|
1457
1645
|
}
|
|
1458
1646
|
});
|
|
1459
|
-
effects.push({
|
|
1647
|
+
effects.push({
|
|
1648
|
+
area: TorrowSdkEffectArea3.Remote,
|
|
1649
|
+
step: AuthSessionEffectStep3.IssueTokens,
|
|
1650
|
+
state: TorrowSdkEffectState3.Applied
|
|
1651
|
+
});
|
|
1460
1652
|
return { tokens, effects };
|
|
1461
1653
|
} catch (error) {
|
|
1462
1654
|
throw otpHttpFailure(error);
|
|
@@ -1496,11 +1688,18 @@ async function runOtpLoginWithEffects(client, options) {
|
|
|
1496
1688
|
} catch (cause) {
|
|
1497
1689
|
throw otpFailure(TorrowSdkErrorCategory7.InvalidResponse, void 0, cause);
|
|
1498
1690
|
}
|
|
1499
|
-
effects.push({
|
|
1691
|
+
effects.push({
|
|
1692
|
+
area: TorrowSdkEffectArea3.Remote,
|
|
1693
|
+
step: AuthSessionEffectStep3.IssueTokens,
|
|
1694
|
+
state: TorrowSdkEffectState3.Applied
|
|
1695
|
+
});
|
|
1500
1696
|
return { tokens: ready, effects };
|
|
1501
1697
|
} catch (cause) {
|
|
1502
1698
|
const error = options.signal?.aborted && !(cause instanceof TorrowSdkError7) ? new TorrowSdkError7({ category: TorrowSdkErrorCategory7.Cancelled, sensitive: { cause } }) : cause;
|
|
1503
|
-
const tokenStages = [
|
|
1699
|
+
const tokenStages = [
|
|
1700
|
+
"IssueTokens" /* IssueTokens */,
|
|
1701
|
+
"PollTokens" /* PollTokens */
|
|
1702
|
+
];
|
|
1504
1703
|
if (tokenStages.includes(failureAt)) {
|
|
1505
1704
|
effects.push({
|
|
1506
1705
|
area: TorrowSdkEffectArea3.Remote,
|
|
@@ -1560,12 +1759,14 @@ var TorrowAuth = {
|
|
|
1560
1759
|
let failureAt = "ValidateInput" /* ValidateInput */;
|
|
1561
1760
|
try {
|
|
1562
1761
|
const accountName = options.account.accountName.trim();
|
|
1563
|
-
if (!accountName)
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1762
|
+
if (!accountName) {
|
|
1763
|
+
throw sessionFailure(void 0, {
|
|
1764
|
+
operation: "TorrowAuth.loginWithOtp",
|
|
1765
|
+
failureAt,
|
|
1766
|
+
effects,
|
|
1767
|
+
category: TorrowSdkErrorCategory8.InvalidInput
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1569
1770
|
failureAt = "OpenSession" /* OpenSession */;
|
|
1570
1771
|
const opened = await TokenSession.openWithEffects(sessionOpenOptsForLogin(options));
|
|
1571
1772
|
const session = opened.session;
|
|
@@ -1660,7 +1861,11 @@ var TorrowAuth = {
|
|
|
1660
1861
|
const explicitTtl = options.accessExpiresAtMs;
|
|
1661
1862
|
const accessExpiresAtMs = typeof explicitTtl === "number" && Number.isFinite(explicitTtl) && explicitTtl > 0 ? explicitTtl : accessExpiresAtMsFromJwt(accessToken);
|
|
1662
1863
|
failureAt = "SeedStorage" /* SeedStorage */;
|
|
1663
|
-
effects.push({
|
|
1864
|
+
effects.push({
|
|
1865
|
+
area: TorrowSdkEffectArea4.Storage,
|
|
1866
|
+
step: AuthSessionEffectStep4.SaveTokens,
|
|
1867
|
+
state: TorrowSdkEffectState4.Unknown
|
|
1868
|
+
});
|
|
1664
1869
|
try {
|
|
1665
1870
|
await options.tokenStorage.save({
|
|
1666
1871
|
accessToken,
|
|
@@ -1681,7 +1886,9 @@ var TorrowAuth = {
|
|
|
1681
1886
|
try {
|
|
1682
1887
|
return await TorrowAuth.connect(options);
|
|
1683
1888
|
} catch (error) {
|
|
1684
|
-
if (error instanceof TorrowSdkError8)
|
|
1889
|
+
if (error instanceof TorrowSdkError8) {
|
|
1890
|
+
effects.push(...error.effects ?? []);
|
|
1891
|
+
}
|
|
1685
1892
|
throw error;
|
|
1686
1893
|
}
|
|
1687
1894
|
} catch (error) {
|