@nxgt/janus 0.17.1 → 0.18.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 +72 -18
- package/dist/auth/config/index.d.ts +1 -1
- package/dist/auth/config/index.d.ts.map +1 -1
- package/dist/auth/config/janus-config.d.ts +31 -0
- package/dist/auth/config/janus-config.d.ts.map +1 -1
- package/dist/auth/config/resolve-config.d.ts.map +1 -1
- package/dist/auth/config/resolve-throttle.d.ts +30 -0
- package/dist/auth/config/resolve-throttle.d.ts.map +1 -0
- package/dist/auth/config/resolved-config.d.ts +5 -0
- package/dist/auth/config/resolved-config.d.ts.map +1 -1
- package/dist/auth/config/warn-throttle-window.d.ts +14 -0
- package/dist/auth/config/warn-throttle-window.d.ts.map +1 -0
- package/dist/auth/counter-key.d.ts +19 -0
- package/dist/auth/counter-key.d.ts.map +1 -0
- package/dist/auth/email-flows/reset-password.d.ts.map +1 -1
- package/dist/auth/email-flows/verify-email.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/janus.d.ts.map +1 -1
- package/dist/auth/magic-link.d.ts.map +1 -1
- package/dist/auth/mail-requests.d.ts +51 -0
- package/dist/auth/mail-requests.d.ts.map +1 -0
- package/dist/auth/sign-in-attempts.d.ts +3 -6
- package/dist/auth/sign-in-attempts.d.ts.map +1 -1
- package/dist/auth/sign-in-code.d.ts +3 -2
- package/dist/auth/sign-in-code.d.ts.map +1 -1
- package/dist/auth/step-up/request.d.ts.map +1 -1
- package/dist/auth/types/email-flows.d.ts +16 -6
- package/dist/auth/types/email-flows.d.ts.map +1 -1
- package/dist/auth/types/magic-link.d.ts +4 -2
- package/dist/auth/types/magic-link.d.ts.map +1 -1
- package/dist/auth/types/step-up.d.ts +4 -1
- package/dist/auth/types/step-up.d.ts.map +1 -1
- package/dist/chunks/{index-kj3st57z.js → index-4khsm7mw.js} +2 -2
- package/dist/chunks/{index-6c9fbtv2.js → index-cntabs9d.js} +2 -2
- package/dist/chunks/{index-hnwggyxs.js → index-kppkcbn5.js} +52 -49
- package/dist/chunks/{index-hnwggyxs.js.map → index-kppkcbn5.js.map} +4 -4
- package/dist/chunks/{index-baazjyvc.js → index-kvjj5xkp.js} +2 -2
- package/dist/conformance/index.js +3 -3
- package/dist/errors/janus-error/codes.d.ts +10 -0
- package/dist/errors/janus-error/codes.d.ts.map +1 -1
- package/dist/errors/janus-error/index.d.ts +1 -1
- package/dist/errors/janus-error/index.d.ts.map +1 -1
- package/dist/errors/janus-error/options.d.ts +4 -3
- package/dist/errors/janus-error/options.d.ts.map +1 -1
- package/dist/errors/janus-error/refusals.d.ts +8 -0
- package/dist/errors/janus-error/refusals.d.ts.map +1 -1
- package/dist/errors/janus-error/status.d.ts +1 -1
- package/dist/errors/janus-error/status.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -29
- package/dist/index.js.map +18 -15
- package/dist/permissions/index.js +40 -29
- package/dist/permissions/index.js.map +6 -6
- package/docs/README.md +1 -1
- package/docs/guide/email-flows.md +164 -4
- package/docs/guide/errors.md +12 -3
- package/docs/guide/magic-link.md +41 -5
- package/docs/guide/passwords.md +2 -1
- package/docs/guide/sign-in-code.md +46 -7
- package/docs/guide/step-up.md +38 -7
- package/docs/guide/users.md +1 -0
- package/docs/roadmap.md +14 -1
- package/docs/troubleshooting.md +88 -3
- package/package.json +1 -1
- package/dist/auth/config/resolve-sign-in.d.ts +0 -5
- package/dist/auth/config/resolve-sign-in.d.ts.map +0 -1
- /package/dist/chunks/{index-kj3st57z.js.map → index-4khsm7mw.js.map} +0 -0
- /package/dist/chunks/{index-6c9fbtv2.js.map → index-cntabs9d.js.map} +0 -0
- /package/dist/chunks/{index-baazjyvc.js.map → index-kvjj5xkp.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
MAX_PAGE_SIZE2,
|
|
8
8
|
pageLimit2,
|
|
9
9
|
invalidCursor2
|
|
10
|
-
} from "./chunks/index-
|
|
10
|
+
} from "./chunks/index-4khsm7mw.js";
|
|
11
11
|
import {
|
|
12
12
|
mintId2,
|
|
13
13
|
isId2,
|
|
14
14
|
mintedAt2,
|
|
15
15
|
createMemoryStores2
|
|
16
|
-
} from "./chunks/index-
|
|
16
|
+
} from "./chunks/index-kvjj5xkp.js";
|
|
17
17
|
import {
|
|
18
18
|
JanusError2,
|
|
19
19
|
UserInvalidError2,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
TokenError2,
|
|
23
23
|
SecondFactorError2,
|
|
24
24
|
StepUpRequiredError2,
|
|
25
|
+
MailThrottledError2,
|
|
25
26
|
InvalidCursorError2,
|
|
26
27
|
UnsupportedError2,
|
|
27
28
|
PermissionDepthError2,
|
|
@@ -38,7 +39,7 @@ import {
|
|
|
38
39
|
formatTuple2,
|
|
39
40
|
parseTuple2,
|
|
40
41
|
parseSubject2
|
|
41
|
-
} from "./chunks/index-
|
|
42
|
+
} from "./chunks/index-kppkcbn5.js";
|
|
42
43
|
|
|
43
44
|
// src/auth/hashers.ts
|
|
44
45
|
import { randomBytes, scrypt, timingSafeEqual } from "node:crypto";
|
|
@@ -303,25 +304,32 @@ function resolveSecondFactor(config, where) {
|
|
|
303
304
|
};
|
|
304
305
|
}
|
|
305
306
|
|
|
306
|
-
// src/auth/config/resolve-
|
|
307
|
+
// src/auth/config/resolve-throttle.ts
|
|
307
308
|
function resolveSignInThrottle(config, where) {
|
|
309
|
+
return resolveThrottle(config, { option: "signIn", attempts: 10, window: "15m" }, where);
|
|
310
|
+
}
|
|
311
|
+
function resolveMailThrottle(config, where) {
|
|
312
|
+
return resolveThrottle(config, { option: "mail", attempts: 5, window: "10m" }, where);
|
|
313
|
+
}
|
|
314
|
+
function resolveThrottle(config, defaults, where) {
|
|
315
|
+
const { option } = defaults;
|
|
308
316
|
if (config !== undefined && (typeof config !== "object" || config === null)) {
|
|
309
|
-
throw new TypeError(`${where}:
|
|
317
|
+
throw new TypeError(`${where}: ${option} must be an object — { throttle }`);
|
|
310
318
|
}
|
|
311
319
|
const throttle = config?.throttle ?? {};
|
|
312
320
|
if (throttle === false)
|
|
313
321
|
return null;
|
|
314
|
-
const at = `${where}:
|
|
322
|
+
const at = `${where}: ${option}.throttle`;
|
|
315
323
|
if (typeof throttle !== "object" || throttle === null) {
|
|
316
324
|
throw new TypeError(`${at} must be { attempts, window }, or false to count nothing`);
|
|
317
325
|
}
|
|
318
|
-
const attempts = throttle.attempts ??
|
|
326
|
+
const attempts = throttle.attempts ?? defaults.attempts;
|
|
319
327
|
if (!Number.isSafeInteger(attempts) || attempts < 1) {
|
|
320
328
|
throw new TypeError(`${at}.attempts must be a whole number above zero`);
|
|
321
329
|
}
|
|
322
330
|
return {
|
|
323
331
|
attempts,
|
|
324
|
-
windowMs: parseDuration(throttle.window ??
|
|
332
|
+
windowMs: parseDuration(throttle.window ?? defaults.window, `${at}.window`)
|
|
325
333
|
};
|
|
326
334
|
}
|
|
327
335
|
|
|
@@ -372,6 +380,7 @@ function resolveConfig(config, where) {
|
|
|
372
380
|
tokenTtlMs: resolveTokenTtls(config, where),
|
|
373
381
|
cookie: resolveCookie(config.cookie ?? {}, where),
|
|
374
382
|
signInThrottle: resolveSignInThrottle(config.signIn, where),
|
|
383
|
+
mailThrottle: resolveMailThrottle(config.mail, where),
|
|
375
384
|
secondFactor: resolveSecondFactor(config.secondFactor, where),
|
|
376
385
|
devices: resolveDevices(config.devices, where)
|
|
377
386
|
};
|
|
@@ -419,6 +428,46 @@ function resolveTokenTtls(config, where) {
|
|
|
419
428
|
stepUp: parseDuration(config.tokens?.stepUp ?? "10m", `${where}: tokens.stepUp`)
|
|
420
429
|
};
|
|
421
430
|
}
|
|
431
|
+
// src/auth/config/warn-throttle-window.ts
|
|
432
|
+
var FLOWS = [
|
|
433
|
+
"magicLink",
|
|
434
|
+
"signInCode",
|
|
435
|
+
"resetPassword",
|
|
436
|
+
"verifyEmail",
|
|
437
|
+
"stepUp"
|
|
438
|
+
];
|
|
439
|
+
var UNITS2 = [
|
|
440
|
+
["d", 86400000],
|
|
441
|
+
["h", 3600000],
|
|
442
|
+
["m", 60000],
|
|
443
|
+
["s", 1000]
|
|
444
|
+
];
|
|
445
|
+
function show(ms) {
|
|
446
|
+
const unit = UNITS2.find(([, size]) => ms % size === 0);
|
|
447
|
+
return unit === undefined ? `${ms}ms` : `${ms / unit[1]}${unit[0]}`;
|
|
448
|
+
}
|
|
449
|
+
function throttleWindowMessage(resolved, where) {
|
|
450
|
+
const throttle = resolved.mailThrottle;
|
|
451
|
+
if (throttle === null)
|
|
452
|
+
return null;
|
|
453
|
+
const window = show(throttle.windowMs);
|
|
454
|
+
const shorter = FLOWS.filter((flow) => resolved.tokenTtlMs[flow] < throttle.windowMs);
|
|
455
|
+
if (shorter.length === 0)
|
|
456
|
+
return null;
|
|
457
|
+
const shortest = Math.min(...shorter.map((flow) => resolved.tokenTtlMs[flow]));
|
|
458
|
+
const parts = shorter.map((flow) => `tokens.${flow} is ${show(resolved.tokenTtlMs[flow])}, shorter than mail.throttle.window, ${window}`);
|
|
459
|
+
return `${where}: ${parts.join("; ")} — past the limit the last ${shorter.length === 1 ? "token" : "tokens"} sent can expire before the refusal ends. Set mail.throttle.window to ${show(shortest)} or less, or raise ${shorter.map((flow) => `tokens.${flow}`).join(", ")} to ${window} or more.`;
|
|
460
|
+
}
|
|
461
|
+
function warnThrottleWindow(resolved, where) {
|
|
462
|
+
const message = throttleWindowMessage(resolved, where);
|
|
463
|
+
if (message === null)
|
|
464
|
+
return;
|
|
465
|
+
if (typeof process === "undefined" || typeof process.emitWarning !== "function") {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
process.emitWarning(message, { code: "JANUS_THROTTLE_WINDOW" });
|
|
469
|
+
}
|
|
470
|
+
|
|
422
471
|
// src/auth/context/create-context.ts
|
|
423
472
|
function createContext(config, store, relations, capabilities, clock, hasher, verifiers, events = null) {
|
|
424
473
|
let dummy = null;
|
|
@@ -726,7 +775,7 @@ function assertStores(stores, where) {
|
|
|
726
775
|
}
|
|
727
776
|
}
|
|
728
777
|
const sessions = stores.sessions;
|
|
729
|
-
const collect = sessions
|
|
778
|
+
const collect = sessions["deleteExpiredSessions"];
|
|
730
779
|
if (collect !== undefined && typeof collect !== "function") {
|
|
731
780
|
throw new TypeError(`${where}: store.sessions.deleteExpiredSessions must be a function or absent`);
|
|
732
781
|
}
|
|
@@ -1008,6 +1057,13 @@ function sharedApi(context) {
|
|
|
1008
1057
|
types: [...config.types.keys()]
|
|
1009
1058
|
};
|
|
1010
1059
|
}
|
|
1060
|
+
// src/auth/counter-key.ts
|
|
1061
|
+
function counterKey(context, purpose) {
|
|
1062
|
+
const sealer = context.config.secondFactor?.sealer;
|
|
1063
|
+
return sealer === undefined ? Buffer.from(purpose) : derivedKey(sealer, purpose);
|
|
1064
|
+
}
|
|
1065
|
+
var keyed = (key, parts) => keyedHash(key, parts).toString("base64url");
|
|
1066
|
+
|
|
1011
1067
|
// src/auth/one-time/codes.ts
|
|
1012
1068
|
import { timingSafeEqual as timingSafeEqual3 } from "node:crypto";
|
|
1013
1069
|
|
|
@@ -1173,6 +1229,38 @@ async function insertLink(links, tokenHash) {
|
|
|
1173
1229
|
return inserted;
|
|
1174
1230
|
throw links.counting.vanished();
|
|
1175
1231
|
}
|
|
1232
|
+
// src/auth/mail-requests.ts
|
|
1233
|
+
var PURPOSE2 = "janus/mail/requests/v1";
|
|
1234
|
+
async function countMailByAddress(context, type, flow, email, where) {
|
|
1235
|
+
await countMail(context, type, flow, { address: normalizeEmail(email) }, where);
|
|
1236
|
+
}
|
|
1237
|
+
async function countMailByUser(context, type, flow, userId, where) {
|
|
1238
|
+
await countMail(context, type, flow, { userId }, where);
|
|
1239
|
+
}
|
|
1240
|
+
async function countMail(context, type, flow, counted, where) {
|
|
1241
|
+
const throttle = context.config.mailThrottle;
|
|
1242
|
+
if (throttle === null)
|
|
1243
|
+
return;
|
|
1244
|
+
const key = counterKey(context, PURPOSE2);
|
|
1245
|
+
const subject = "address" in counted ? keyed(key, [flow, "address", counted.address]) : keyed(key, [flow, "user", counted.userId]);
|
|
1246
|
+
const { attempts, endsAt } = await countInWindow(context, {
|
|
1247
|
+
windowMs: throttle.windowMs,
|
|
1248
|
+
spent: "carry",
|
|
1249
|
+
userId: subject,
|
|
1250
|
+
linkHash: (window, link) => hashSecret(keyed(key, [subject, String(window), String(link)])),
|
|
1251
|
+
vanished: () => new StoreFailure2(`${where}: the store dropped the requests it had just counted`, { slot: "tokens", operation: "countAttempt" })
|
|
1252
|
+
});
|
|
1253
|
+
if (attempts <= throttle.attempts)
|
|
1254
|
+
return;
|
|
1255
|
+
const now = context.clock.now().getTime();
|
|
1256
|
+
const byUser = "userId" in counted;
|
|
1257
|
+
throw new MailThrottledError2(`${where}: too many e-mails asked for this ${byUser ? "user" : "address"} — the last one sent still works; use it, or wait for the next window`, {
|
|
1258
|
+
userType: type.name,
|
|
1259
|
+
...byUser ? { userId: counted.userId } : {},
|
|
1260
|
+
retryAfter: Math.max(1, Math.ceil((endsAt - now) / 1000))
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1176
1264
|
// src/auth/password-written.ts
|
|
1177
1265
|
async function endWhatThePasswordOpened(context, userId) {
|
|
1178
1266
|
const now = context.clock.now();
|
|
@@ -1234,6 +1322,7 @@ function resetPasswordFlows(context, type, at) {
|
|
|
1234
1322
|
async request(email) {
|
|
1235
1323
|
const where = at("resetPassword.request");
|
|
1236
1324
|
passwordRule(type, where);
|
|
1325
|
+
await countMailByAddress(context, type, "resetPassword", String(email), where);
|
|
1237
1326
|
const record = await holderOfEmail(context, type, String(email));
|
|
1238
1327
|
if (record === null)
|
|
1239
1328
|
return null;
|
|
@@ -1278,6 +1367,7 @@ function verifyEmailFlows(context, type, at) {
|
|
|
1278
1367
|
async send(user) {
|
|
1279
1368
|
const where = at("verifyEmail.send");
|
|
1280
1369
|
const record = await getRecord(context, idOf(user), type.name, where);
|
|
1370
|
+
await countMailByUser(context, type, "verifyEmail", record.id, where);
|
|
1281
1371
|
return issueEmailToken(context, type, "verifyEmail", record, where);
|
|
1282
1372
|
},
|
|
1283
1373
|
async confirm(secret) {
|
|
@@ -1465,7 +1555,7 @@ async function finishEmailSignIn(context, type, finish, signIn) {
|
|
|
1465
1555
|
function magicLinkFlows(context, type, at, finish) {
|
|
1466
1556
|
return {
|
|
1467
1557
|
async request(email) {
|
|
1468
|
-
return requestLink(context, type, String(email));
|
|
1558
|
+
return requestLink(context, type, String(email), at("magicLink.request"));
|
|
1469
1559
|
},
|
|
1470
1560
|
async confirm(token, options) {
|
|
1471
1561
|
const where = at("magicLink.confirm");
|
|
@@ -1474,7 +1564,8 @@ function magicLinkFlows(context, type, at, finish) {
|
|
|
1474
1564
|
}
|
|
1475
1565
|
};
|
|
1476
1566
|
}
|
|
1477
|
-
async function requestLink(context, type, email) {
|
|
1567
|
+
async function requestLink(context, type, email, where) {
|
|
1568
|
+
await countMailByAddress(context, type, "magicLink", email, where);
|
|
1478
1569
|
const record = await signInHolder(context, type, email);
|
|
1479
1570
|
if (record === null)
|
|
1480
1571
|
return null;
|
|
@@ -1500,18 +1591,12 @@ async function confirmLink(context, type, finish, secret, where, device) {
|
|
|
1500
1591
|
}
|
|
1501
1592
|
|
|
1502
1593
|
// src/auth/sign-in-attempts.ts
|
|
1503
|
-
var
|
|
1504
|
-
var UNSEALED = Buffer.from(PURPOSE2);
|
|
1505
|
-
function counterKey(context) {
|
|
1506
|
-
const sealer = context.config.secondFactor?.sealer;
|
|
1507
|
-
return sealer === undefined ? UNSEALED : derivedKey(sealer, PURPOSE2);
|
|
1508
|
-
}
|
|
1509
|
-
var keyed = (key, parts) => keyedHash(key, parts).toString("base64url");
|
|
1594
|
+
var PURPOSE3 = "janus/sign-in/attempts/v1";
|
|
1510
1595
|
async function countLogin(context, type, login, where) {
|
|
1511
1596
|
const throttle = context.config.signInThrottle;
|
|
1512
1597
|
if (throttle === null)
|
|
1513
1598
|
return null;
|
|
1514
|
-
const key = counterKey(context);
|
|
1599
|
+
const key = counterKey(context, PURPOSE3);
|
|
1515
1600
|
const loginKey = keyed(key, [type.name, login]);
|
|
1516
1601
|
return countInWindow(context, {
|
|
1517
1602
|
windowMs: throttle.windowMs,
|
|
@@ -1634,7 +1719,7 @@ var RECOVERY_CODES = 10;
|
|
|
1634
1719
|
var ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
1635
1720
|
var LENGTH = 10;
|
|
1636
1721
|
var SHAPE = /^[0-9a-hjkmnp-tv-z]{10}$/;
|
|
1637
|
-
var
|
|
1722
|
+
var PURPOSE4 = "janus/second-factor/recovery-codes/v1";
|
|
1638
1723
|
function mintRecoveryCodes() {
|
|
1639
1724
|
return Array.from({ length: RECOVERY_CODES }, () => {
|
|
1640
1725
|
let code = "";
|
|
@@ -1648,7 +1733,7 @@ function readRecoveryCode(typed) {
|
|
|
1648
1733
|
const code = typed.toLowerCase().replace(/[\s-]/g, "").replace(/o/g, "0").replace(/[il]/g, "1");
|
|
1649
1734
|
return SHAPE.test(code) ? code : null;
|
|
1650
1735
|
}
|
|
1651
|
-
var macKey = (sealer, keyId) => derivedKey(sealer,
|
|
1736
|
+
var macKey = (sealer, keyId) => derivedKey(sealer, PURPOSE4, keyId);
|
|
1652
1737
|
var mac = (key, userId, code) => keyedHash(key, [userId, code]);
|
|
1653
1738
|
function hashRecoveryCode(sealer, userId, code) {
|
|
1654
1739
|
const read = readRecoveryCode(code) ?? code;
|
|
@@ -1759,7 +1844,7 @@ function accountOf(type, record, where) {
|
|
|
1759
1844
|
// src/auth/second-factor/app-code-attempts.ts
|
|
1760
1845
|
var APP_CODE_WINDOW_MS = 15 * 60000;
|
|
1761
1846
|
var WINDOW_MINUTES = APP_CODE_WINDOW_MS / 60000;
|
|
1762
|
-
var
|
|
1847
|
+
var PURPOSE5 = "janus/second-factor/regenerate-attempts/v1";
|
|
1763
1848
|
function linkHash(sealer, record, window, link) {
|
|
1764
1849
|
const parts = [
|
|
1765
1850
|
record.id,
|
|
@@ -1767,7 +1852,7 @@ function linkHash(sealer, record, window, link) {
|
|
|
1767
1852
|
String(record.secondFactor?.lastStep ?? ""),
|
|
1768
1853
|
String(link)
|
|
1769
1854
|
];
|
|
1770
|
-
const key = derivedKey(sealer,
|
|
1855
|
+
const key = derivedKey(sealer, PURPOSE5);
|
|
1771
1856
|
return hashSecret(keyedHash(key, parts).toString("base64url"));
|
|
1772
1857
|
}
|
|
1773
1858
|
async function countAppCodeAttempt(context, sealer, record, where) {
|
|
@@ -1883,14 +1968,15 @@ function secondFactorFlows(context, type, at) {
|
|
|
1883
1968
|
function signInCodeFlows(context, type, at, finish) {
|
|
1884
1969
|
return {
|
|
1885
1970
|
async request(email) {
|
|
1886
|
-
return requestCode(context, type, String(email));
|
|
1971
|
+
return requestCode(context, type, String(email), at("signInCode.request"));
|
|
1887
1972
|
},
|
|
1888
1973
|
async confirm(challenge, code, options) {
|
|
1889
1974
|
return confirmCode(context, type, finish, { challenge, code, options }, at);
|
|
1890
1975
|
}
|
|
1891
1976
|
};
|
|
1892
1977
|
}
|
|
1893
|
-
async function requestCode(context, type, email) {
|
|
1978
|
+
async function requestCode(context, type, email, where) {
|
|
1979
|
+
await countMailByAddress(context, type, "signInCode", email, where);
|
|
1894
1980
|
const record = await signInHolder(context, type, email);
|
|
1895
1981
|
if (record === null)
|
|
1896
1982
|
return null;
|
|
@@ -2028,6 +2114,7 @@ async function byEmail(context, type, record, where) {
|
|
|
2028
2114
|
operation: where
|
|
2029
2115
|
});
|
|
2030
2116
|
}
|
|
2117
|
+
await countMailByUser(context, type, "stepUp", record.id, where);
|
|
2031
2118
|
const { secret, code, expiresAt } = await issueCode(context, {
|
|
2032
2119
|
kind: "stepUp",
|
|
2033
2120
|
userId: record.id,
|
|
@@ -2136,7 +2223,7 @@ async function signIn(context, type, finish, input, call) {
|
|
|
2136
2223
|
const rule = passwordRule(type, where);
|
|
2137
2224
|
const hasher = requireHasher(context, where);
|
|
2138
2225
|
const login = input?.[rule.login];
|
|
2139
|
-
const password = input?.password;
|
|
2226
|
+
const password = input?.["password"];
|
|
2140
2227
|
const normalized = typeof login === "string" ? rule.normalize(login) : null;
|
|
2141
2228
|
if (normalized !== null) {
|
|
2142
2229
|
await countSignInAttempt(context, type, normalized, where);
|
|
@@ -2175,7 +2262,7 @@ function passwordFlows(context, type, at, finish) {
|
|
|
2175
2262
|
const where = at("signUp");
|
|
2176
2263
|
const device = deviceHint(context, options, where);
|
|
2177
2264
|
passwordRule(type, where);
|
|
2178
|
-
if (input?.password === undefined) {
|
|
2265
|
+
if (input?.["password"] === undefined) {
|
|
2179
2266
|
checkPassword(type, undefined, where);
|
|
2180
2267
|
}
|
|
2181
2268
|
const record = await insert(context, type, input, where);
|
|
@@ -2320,6 +2407,7 @@ function typeApi(context, type) {
|
|
|
2320
2407
|
function janus(config) {
|
|
2321
2408
|
const where = "janus";
|
|
2322
2409
|
const resolved = resolveConfig(config, where);
|
|
2410
|
+
warnThrottleWindow(resolved, where);
|
|
2323
2411
|
const capabilities = assertStores(config.store, where);
|
|
2324
2412
|
const hasher = config.hasher ?? null;
|
|
2325
2413
|
const verifiers = [
|
|
@@ -2346,7 +2434,7 @@ function janus(config) {
|
|
|
2346
2434
|
type.name,
|
|
2347
2435
|
typeApi(context, type)
|
|
2348
2436
|
]));
|
|
2349
|
-
const surface = resolved.single ? { ...shared, ...types
|
|
2437
|
+
const surface = resolved.single ? { ...shared, ...types["user"] } : { ...shared, ...types };
|
|
2350
2438
|
return surface;
|
|
2351
2439
|
}
|
|
2352
2440
|
// src/auth/sessions/fresh.ts
|
|
@@ -2363,6 +2451,7 @@ export {
|
|
|
2363
2451
|
InvalidCursorError2 as InvalidCursorError,
|
|
2364
2452
|
JanusError2 as JanusError,
|
|
2365
2453
|
MAX_PAGE_SIZE2 as MAX_PAGE_SIZE,
|
|
2454
|
+
MailThrottledError2 as MailThrottledError,
|
|
2366
2455
|
NotFoundError2 as NotFoundError,
|
|
2367
2456
|
PermissionDepthError2 as PermissionDepthError,
|
|
2368
2457
|
SecondFactorError2 as SecondFactorError,
|
|
@@ -2399,5 +2488,5 @@ export {
|
|
|
2399
2488
|
systemClock
|
|
2400
2489
|
};
|
|
2401
2490
|
|
|
2402
|
-
//# debugId=
|
|
2491
|
+
//# debugId=ACD85BEBE6A087E464756E2164756E21
|
|
2403
2492
|
//# sourceMappingURL=index.js.map
|