cauthy-auth 0.27.0 → 0.28.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/cli.js +3 -1
- package/dist/client.d.mts +12 -3
- package/dist/client.d.ts +12 -3
- package/dist/client.js +132 -17
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +126 -16
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +152 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -20
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +27 -1
- package/dist/react.d.ts +27 -1
- package/dist/react.js +150 -23
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +150 -23
- package/dist/react.mjs.map +1 -1
- package/dist/styles.css +6 -0
- package/dist/svelte.d.mts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +120 -15
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +120 -15
- package/dist/svelte.mjs.map +1 -1
- package/dist/validate-sEXG82po.d.mts +66 -0
- package/dist/validate-sEXG82po.d.ts +66 -0
- package/dist/vue.d.mts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +120 -15
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +120 -15
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/validate-BTRit1O1.d.mts +0 -19
- package/dist/validate-BTRit1O1.d.ts +0 -19
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-XkIbG5gE.mjs';
|
|
2
2
|
export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PermissionOf, e as Permitted, f as Policy, g as PolicyPermission, h as PolicyRole, i as PublicSession, j as PushPolicyOptions, R as RoleOf, S as Session, k as SessionOrganization, l as SessionStatus, m as SessionUser, n as SystemKey, o as SystemOptions, p as can, q as createSystem, r as definePolicy, s as policySource, t as pullPolicy, u as pushPolicy } from './system-BxMsSIu1.mjs';
|
|
3
3
|
export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, StackmythTokens, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth, tokensFromStackmyth } from './theme.mjs';
|
|
4
|
-
export { A as AuthField, F as FieldProblem, M as MIN_PASSWORD, c as checkCode,
|
|
4
|
+
export { A as AuthField, D as DEFAULT_PASSWORD_POLICY, F as FieldProblem, M as MIN_PASSWORD, P as PasswordClass, a as PasswordLocale, b as PasswordPolicy, c as PasswordReason, d as checkCode, e as checkEmail, f as checkName, g as checkNewPassword, h as checkPassword, i as describePasswordPolicy, j as explainPasswordProblems, p as passwordPolicyOf, k as passwordProblems } from './validate-sEXG82po.mjs';
|
|
5
5
|
import { JWTVerifyGetKey } from 'jose';
|
|
6
6
|
|
|
7
7
|
interface ConnectOptions {
|
|
@@ -33,10 +33,16 @@ interface Connected {
|
|
|
33
33
|
/** Shown this once: Cauthy keeps only its hash. */
|
|
34
34
|
clientSecret: string;
|
|
35
35
|
redirectUris: string[];
|
|
36
|
+
/**
|
|
37
|
+
* The subscription to events, when `eventsUrl` was given. Its `secret` signs
|
|
38
|
+
* the HMAC header (X-Cauthy-Signature) and is shown this once; `auth.webhook`
|
|
39
|
+
* does not need it, as it verifies by Cauthy's published keys.
|
|
40
|
+
*/
|
|
36
41
|
webhook: {
|
|
37
42
|
id: string;
|
|
38
43
|
url: string;
|
|
39
44
|
events: string[];
|
|
45
|
+
secret: string;
|
|
40
46
|
} | null;
|
|
41
47
|
/**
|
|
42
48
|
* Everything the application sets: what Cauthy answered, plus CAUTHY_SECRET,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-DGAy45G2.js';
|
|
2
2
|
export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PermissionOf, e as Permitted, f as Policy, g as PolicyPermission, h as PolicyRole, i as PublicSession, j as PushPolicyOptions, R as RoleOf, S as Session, k as SessionOrganization, l as SessionStatus, m as SessionUser, n as SystemKey, o as SystemOptions, p as can, q as createSystem, r as definePolicy, s as policySource, t as pullPolicy, u as pushPolicy } from './system-DTIeDXDP.js';
|
|
3
3
|
export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, StackmythTokens, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth, tokensFromStackmyth } from './theme.js';
|
|
4
|
-
export { A as AuthField, F as FieldProblem, M as MIN_PASSWORD, c as checkCode,
|
|
4
|
+
export { A as AuthField, D as DEFAULT_PASSWORD_POLICY, F as FieldProblem, M as MIN_PASSWORD, P as PasswordClass, a as PasswordLocale, b as PasswordPolicy, c as PasswordReason, d as checkCode, e as checkEmail, f as checkName, g as checkNewPassword, h as checkPassword, i as describePasswordPolicy, j as explainPasswordProblems, p as passwordPolicyOf, k as passwordProblems } from './validate-sEXG82po.js';
|
|
5
5
|
import { JWTVerifyGetKey } from 'jose';
|
|
6
6
|
|
|
7
7
|
interface ConnectOptions {
|
|
@@ -33,10 +33,16 @@ interface Connected {
|
|
|
33
33
|
/** Shown this once: Cauthy keeps only its hash. */
|
|
34
34
|
clientSecret: string;
|
|
35
35
|
redirectUris: string[];
|
|
36
|
+
/**
|
|
37
|
+
* The subscription to events, when `eventsUrl` was given. Its `secret` signs
|
|
38
|
+
* the HMAC header (X-Cauthy-Signature) and is shown this once; `auth.webhook`
|
|
39
|
+
* does not need it, as it verifies by Cauthy's published keys.
|
|
40
|
+
*/
|
|
36
41
|
webhook: {
|
|
37
42
|
id: string;
|
|
38
43
|
url: string;
|
|
39
44
|
events: string[];
|
|
45
|
+
secret: string;
|
|
40
46
|
} | null;
|
|
41
47
|
/**
|
|
42
48
|
* Everything the application sets: what Cauthy answered, plus CAUTHY_SECRET,
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(src_exports, {
|
|
|
24
24
|
CauthyConfigError: () => CauthyConfigError,
|
|
25
25
|
CauthyTokenError: () => CauthyTokenError,
|
|
26
26
|
CauthyWebhookError: () => CauthyWebhookError,
|
|
27
|
+
DEFAULT_PASSWORD_POLICY: () => DEFAULT_PASSWORD_POLICY,
|
|
27
28
|
MIN_PASSWORD: () => MIN_PASSWORD,
|
|
28
29
|
can: () => can,
|
|
29
30
|
checkCode: () => checkCode,
|
|
@@ -35,6 +36,10 @@ __export(src_exports, {
|
|
|
35
36
|
createCauthy: () => createCauthy,
|
|
36
37
|
createSystem: () => createSystem,
|
|
37
38
|
definePolicy: () => definePolicy,
|
|
39
|
+
describePasswordPolicy: () => describePasswordPolicy,
|
|
40
|
+
explainPasswordProblems: () => explainPasswordProblems,
|
|
41
|
+
passwordPolicyOf: () => passwordPolicyOf,
|
|
42
|
+
passwordProblems: () => passwordProblems,
|
|
38
43
|
policySource: () => policySource,
|
|
39
44
|
pullPolicy: () => pullPolicy,
|
|
40
45
|
pushPolicy: () => pushPolicy,
|
|
@@ -543,7 +548,9 @@ function createSystem(given = {}) {
|
|
|
543
548
|
async function fail(res, what) {
|
|
544
549
|
const body = await res.json().catch(() => null);
|
|
545
550
|
const first = body?.errors?.[0];
|
|
546
|
-
|
|
551
|
+
const code = typeof body?.error === "string" ? body.error : first?.code;
|
|
552
|
+
const message = typeof body?.error === "string" ? body.error_description : first?.message;
|
|
553
|
+
throw new CauthyApiError(res.status, code ?? "error", `Cauthy refused ${what} (${res.status}): ${message ?? res.statusText}`);
|
|
547
554
|
}
|
|
548
555
|
let held;
|
|
549
556
|
let asking;
|
|
@@ -653,9 +660,113 @@ function createSystem(given = {}) {
|
|
|
653
660
|
}
|
|
654
661
|
|
|
655
662
|
// src/validate.ts
|
|
656
|
-
var MIN_PASSWORD =
|
|
657
|
-
var MAX_PASSWORD =
|
|
663
|
+
var MIN_PASSWORD = 12;
|
|
664
|
+
var MAX_PASSWORD = 128;
|
|
665
|
+
var FLOOR_PASSWORD = 8;
|
|
658
666
|
var MAX_NAME = 120;
|
|
667
|
+
var CLASSES = ["lowercase", "uppercase", "digit", "symbol"];
|
|
668
|
+
var DEFAULT_PASSWORD_POLICY = Object.freeze({ min: MIN_PASSWORD, max: MAX_PASSWORD, requires: [], min_classes: 0, reject_breached: false });
|
|
669
|
+
var int = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? Math.trunc(v) : fallback;
|
|
670
|
+
function passwordPolicyOf(raw) {
|
|
671
|
+
const r = raw && typeof raw === "object" ? raw : {};
|
|
672
|
+
const min = Math.min(Math.max(int(r.min ?? r.min_length, MIN_PASSWORD) || MIN_PASSWORD, FLOOR_PASSWORD), MAX_PASSWORD);
|
|
673
|
+
const max = Math.max(Math.min(int(r.max ?? r.max_length, MAX_PASSWORD) || MAX_PASSWORD, MAX_PASSWORD), min);
|
|
674
|
+
const asked = Array.isArray(r.requires) ? r.requires : [];
|
|
675
|
+
return {
|
|
676
|
+
min,
|
|
677
|
+
max,
|
|
678
|
+
requires: CLASSES.filter((c) => asked.includes(c)),
|
|
679
|
+
min_classes: Math.min(Math.max(int(r.min_classes ?? r.minClasses, 0), 0), CLASSES.length),
|
|
680
|
+
reject_breached: (r.reject_breached ?? r.rejectBreached) === true
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
function utf8Length(v) {
|
|
684
|
+
let n = 0;
|
|
685
|
+
for (const ch of v) {
|
|
686
|
+
const c = ch.codePointAt(0);
|
|
687
|
+
n += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : 4;
|
|
688
|
+
}
|
|
689
|
+
return n;
|
|
690
|
+
}
|
|
691
|
+
function classesOf(v) {
|
|
692
|
+
const has = /* @__PURE__ */ new Set();
|
|
693
|
+
for (const ch of v) {
|
|
694
|
+
if (/\p{Ll}/u.test(ch)) has.add("lowercase");
|
|
695
|
+
else if (/\p{Lu}/u.test(ch)) has.add("uppercase");
|
|
696
|
+
else if (/\p{Nd}/u.test(ch)) has.add("digit");
|
|
697
|
+
else if (!/\p{L}/u.test(ch)) has.add("symbol");
|
|
698
|
+
}
|
|
699
|
+
return has;
|
|
700
|
+
}
|
|
701
|
+
function passwordProblems(value, policy = DEFAULT_PASSWORD_POLICY) {
|
|
702
|
+
const p = passwordPolicyOf(policy);
|
|
703
|
+
const out2 = [];
|
|
704
|
+
const length = utf8Length(value);
|
|
705
|
+
if (length < p.min) out2.push("too_short");
|
|
706
|
+
if (length > p.max) out2.push("too_long");
|
|
707
|
+
const has = classesOf(value);
|
|
708
|
+
for (const c of p.requires) if (!has.has(c)) out2.push(`needs_${c}`);
|
|
709
|
+
if (p.min_classes > 0 && CLASSES.filter((c) => has.has(c)).length < p.min_classes) out2.push("needs_classes");
|
|
710
|
+
return out2;
|
|
711
|
+
}
|
|
712
|
+
var RULES = {
|
|
713
|
+
en: {
|
|
714
|
+
between: "Between {min} and {max} characters.",
|
|
715
|
+
requires: "Include {kinds}.",
|
|
716
|
+
and: "and",
|
|
717
|
+
classes: "Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.",
|
|
718
|
+
breached: "Passwords found in known data breaches are not accepted.",
|
|
719
|
+
kinds: { lowercase: "a lowercase letter", uppercase: "an uppercase letter", digit: "a digit", symbol: "a symbol" },
|
|
720
|
+
reasons: {
|
|
721
|
+
too_short: "Use at least {min} characters.",
|
|
722
|
+
too_long: "Use at most {max} characters.",
|
|
723
|
+
needs_lowercase: "Include a lowercase letter.",
|
|
724
|
+
needs_uppercase: "Include an uppercase letter.",
|
|
725
|
+
needs_digit: "Include a digit.",
|
|
726
|
+
needs_symbol: "Include a symbol.",
|
|
727
|
+
needs_classes: "Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.",
|
|
728
|
+
breached: "This password appears in a known data breach. Choose a different one."
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
es: {
|
|
732
|
+
between: "Entre {min} y {max} caracteres.",
|
|
733
|
+
requires: "Incluye {kinds}.",
|
|
734
|
+
and: "y",
|
|
735
|
+
classes: "Usa al menos {n} de estos tipos: min\xFAsculas, may\xFAsculas, n\xFAmeros, s\xEDmbolos.",
|
|
736
|
+
breached: "No se aceptan contrase\xF1as que aparecen en filtraciones de datos conocidas.",
|
|
737
|
+
kinds: { lowercase: "una min\xFAscula", uppercase: "una may\xFAscula", digit: "un n\xFAmero", symbol: "un s\xEDmbolo" },
|
|
738
|
+
reasons: {
|
|
739
|
+
too_short: "Usa al menos {min} caracteres.",
|
|
740
|
+
too_long: "Usa como m\xE1ximo {max} caracteres.",
|
|
741
|
+
needs_lowercase: "Incluye una min\xFAscula.",
|
|
742
|
+
needs_uppercase: "Incluye una may\xFAscula.",
|
|
743
|
+
needs_digit: "Incluye un n\xFAmero.",
|
|
744
|
+
needs_symbol: "Incluye un s\xEDmbolo.",
|
|
745
|
+
needs_classes: "Usa al menos {n} de estos tipos: min\xFAsculas, may\xFAsculas, n\xFAmeros, s\xEDmbolos.",
|
|
746
|
+
breached: "Esta contrase\xF1a aparece en una filtraci\xF3n de datos conocida. Elige otra."
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
var fill = (s, p) => s.replace("{min}", String(p.min)).replace("{max}", String(p.max)).replace("{n}", String(p.min_classes));
|
|
751
|
+
function describePasswordPolicy(policy = DEFAULT_PASSWORD_POLICY, locale = "en") {
|
|
752
|
+
const p = passwordPolicyOf(policy);
|
|
753
|
+
const t = RULES[locale] ?? RULES.en;
|
|
754
|
+
const parts = [fill(t.between, p)];
|
|
755
|
+
if (p.requires.length > 0) {
|
|
756
|
+
const kinds = p.requires.map((c) => t.kinds[c]);
|
|
757
|
+
const listed = kinds.length === 1 ? kinds[0] : `${kinds.slice(0, -1).join(", ")} ${t.and} ${kinds[kinds.length - 1]}`;
|
|
758
|
+
parts.push(t.requires.replace("{kinds}", listed));
|
|
759
|
+
}
|
|
760
|
+
if (p.min_classes > 0) parts.push(fill(t.classes, p));
|
|
761
|
+
if (p.reject_breached) parts.push(t.breached);
|
|
762
|
+
return parts.join(" ");
|
|
763
|
+
}
|
|
764
|
+
function explainPasswordProblems(reasons, policy = DEFAULT_PASSWORD_POLICY, locale = "en") {
|
|
765
|
+
const p = passwordPolicyOf(policy);
|
|
766
|
+
const t = RULES[locale] ?? RULES.en;
|
|
767
|
+
const said = reasons.filter((r) => r in t.reasons).map((r) => fill(t.reasons[r], p));
|
|
768
|
+
return said.length > 0 ? said.join(" ") : describePasswordPolicy(p, locale);
|
|
769
|
+
}
|
|
659
770
|
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
660
771
|
function checkEmail(value) {
|
|
661
772
|
const v = typeof value === "string" ? value.trim() : "";
|
|
@@ -668,13 +779,12 @@ function checkPassword(value) {
|
|
|
668
779
|
if (value.length > MAX_PASSWORD) return { field: "password", code: "too_long", message: "That password is too long." };
|
|
669
780
|
return null;
|
|
670
781
|
}
|
|
671
|
-
function checkNewPassword(value) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
return null;
|
|
782
|
+
function checkNewPassword(value, policy) {
|
|
783
|
+
if (typeof value !== "string" || value === "") return { field: "password", code: "required", message: "Enter your password." };
|
|
784
|
+
const p = policy ? passwordPolicyOf(policy) : DEFAULT_PASSWORD_POLICY;
|
|
785
|
+
const reasons = passwordProblems(value, p);
|
|
786
|
+
if (reasons.length === 0) return null;
|
|
787
|
+
return { field: "password", code: reasons[0], message: explainPasswordProblems(reasons, p) };
|
|
678
788
|
}
|
|
679
789
|
function checkName(value) {
|
|
680
790
|
if (value === void 0 || value === null || value === "") return null;
|
|
@@ -1133,7 +1243,7 @@ function createCauthy(given = {}) {
|
|
|
1133
1243
|
connectedAt: String(d?.created_at ?? ""),
|
|
1134
1244
|
lastUsedAt: String(d?.last_used_at ?? "")
|
|
1135
1245
|
});
|
|
1136
|
-
const problem = (status2, code, message, field, headers) => json({ error: { code, message, ...field ? { field } : {} } }, status2, headers);
|
|
1246
|
+
const problem = (status2, code, message, field, headers, reasons) => json({ error: { code, message, ...field ? { field } : {}, ...reasons && reasons.length > 0 ? { reasons } : {} } }, status2, headers);
|
|
1137
1247
|
const invalid = (p) => problem(400, p.code, p.message, p.field);
|
|
1138
1248
|
function ownRequest(request) {
|
|
1139
1249
|
const origin = request.headers.get("origin");
|
|
@@ -1191,7 +1301,8 @@ function createCauthy(given = {}) {
|
|
|
1191
1301
|
const b = res.status === 204 || res.status === 202 ? null : await res.json().catch(() => null);
|
|
1192
1302
|
if (res.ok) return { status: res.status, data: b?.data ?? b };
|
|
1193
1303
|
const first = b?.errors?.[0];
|
|
1194
|
-
|
|
1304
|
+
const reasons = Array.isArray(first?.meta?.reasons) ? first.meta.reasons.map(String) : void 0;
|
|
1305
|
+
return { status: res.status, data: null, error: { code: String(first?.code ?? "error"), message: String(first?.message ?? "The request could not be completed."), ...reasons ? { reasons } : {} } };
|
|
1195
1306
|
} catch {
|
|
1196
1307
|
return { status: 503, data: null, error: { code: "unavailable", message: "Sign-in is unavailable right now. Try again in a moment." } };
|
|
1197
1308
|
}
|
|
@@ -1219,6 +1330,19 @@ function createCauthy(given = {}) {
|
|
|
1219
1330
|
return json({ status: "signed_in", session: await toPublic(toSession(s)), ...more }, 200, h);
|
|
1220
1331
|
}
|
|
1221
1332
|
let lookCache = null;
|
|
1333
|
+
let policyCache = null;
|
|
1334
|
+
const keepPolicy = (settings) => {
|
|
1335
|
+
policyCache = { until: Date.now() + LOOK_TTL_MS, policy: settings.error || !settings.data?.password_policy ? null : passwordPolicyOf(settings.data.password_policy) };
|
|
1336
|
+
return policyCache.policy;
|
|
1337
|
+
};
|
|
1338
|
+
async function workspacePolicy(request) {
|
|
1339
|
+
if (policyCache !== null && policyCache.until >= Date.now()) return policyCache.policy;
|
|
1340
|
+
return keepPolicy(await ask(request, "GET", "/v1/auth/settings"));
|
|
1341
|
+
}
|
|
1342
|
+
async function newPasswordProblem(request, value) {
|
|
1343
|
+
const policy = await workspacePolicy(request);
|
|
1344
|
+
return checkNewPassword(value, policy ?? { min: 8, max: 128, requires: [], min_classes: 0, reject_breached: false });
|
|
1345
|
+
}
|
|
1222
1346
|
async function ownRoute(request, url, route) {
|
|
1223
1347
|
const post = request.method === "POST";
|
|
1224
1348
|
const own = [
|
|
@@ -1296,6 +1420,7 @@ function createCauthy(given = {}) {
|
|
|
1296
1420
|
ask(request, "GET", "/v1/auth/sso/connections")
|
|
1297
1421
|
]);
|
|
1298
1422
|
const list = Array.isArray(providers.data) ? providers.data : [];
|
|
1423
|
+
const password = keepPolicy(settings);
|
|
1299
1424
|
const here = place.data?.here === true;
|
|
1300
1425
|
return json({
|
|
1301
1426
|
providers: list.map((p) => ({ id: String(p.provider ?? p.id ?? ""), name: String(p.label ?? p.name ?? p.provider ?? "") })).filter((p) => p.id !== ""),
|
|
@@ -1311,7 +1436,9 @@ function createCauthy(given = {}) {
|
|
|
1311
1436
|
sso: Array.isArray(sso.data) && sso.data.some((c) => c?.discoverable === true),
|
|
1312
1437
|
// The terms a sign-up accepts and the consents it answers, when the workspace asks any.
|
|
1313
1438
|
...settings.data?.legal ? { legal: legalOf(settings.data.legal) } : {},
|
|
1314
|
-
...settings.data?.captcha_enabled === true && settings.data?.captcha_site_key ? { captchaSiteKey: String(settings.data.captcha_site_key) } : {}
|
|
1439
|
+
...settings.data?.captcha_enabled === true && settings.data?.captcha_site_key ? { captchaSiteKey: String(settings.data.captcha_site_key) } : {},
|
|
1440
|
+
// What a new password must be: for the form to say it and check it.
|
|
1441
|
+
...password ? { password } : {}
|
|
1315
1442
|
});
|
|
1316
1443
|
}
|
|
1317
1444
|
if (route === "/sign-in/sso" && !post) {
|
|
@@ -1601,13 +1728,13 @@ function createCauthy(given = {}) {
|
|
|
1601
1728
|
return json({ status: "sent", sentTo: String(res.data?.sent_to ?? ""), channel: String(res.data?.channel ?? "sms") });
|
|
1602
1729
|
}
|
|
1603
1730
|
if (route === "/sign-up/email") {
|
|
1604
|
-
const bad = firstProblem(checkName(b.name), checkEmail(b.email),
|
|
1731
|
+
const bad = firstProblem(checkName(b.name), checkEmail(b.email), await newPasswordProblem(request, b.password), checkOrganization(b.organization));
|
|
1605
1732
|
if (bad) return invalid(bad);
|
|
1606
1733
|
const email = String(b.email).trim();
|
|
1607
1734
|
const organization = typeof b.organization === "string" && b.organization.trim() !== "" ? { organization: { name: b.organization.trim() } } : {};
|
|
1608
1735
|
const legal = { ...b.acceptLegal === true ? { accept_legal: true } : {}, ...b.consents && typeof b.consents === "object" ? { consents: b.consents } : {} };
|
|
1609
1736
|
const made = await ask(request, "POST", "/v1/auth/register", { email, password: b.password, display_name: typeof b.name === "string" ? b.name.trim() : "", ...organization, ...legal }, pages.verifyEmail);
|
|
1610
|
-
if (made.error) return problem(made.status, made.error.code, made.error.message);
|
|
1737
|
+
if (made.error) return problem(made.status, made.error.code, made.error.message, made.error.code === "weak_password" ? "password" : void 0, void 0, made.error.reasons);
|
|
1611
1738
|
if (made.data?.verification_required === true) return json({ status: "verification_required", email });
|
|
1612
1739
|
const res = await ask(request, "POST", "/v1/auth/login", { email, password: b.password });
|
|
1613
1740
|
if (res.error || res.data?.mfa_required === true) return json({ status: "verification_required", email });
|
|
@@ -1623,7 +1750,7 @@ function createCauthy(given = {}) {
|
|
|
1623
1750
|
const mine = await signedInAs(request);
|
|
1624
1751
|
if ("response" in mine) return mine.response;
|
|
1625
1752
|
const as = (path, payload, method = "POST") => ask(request, method, path, payload, void 0, mine.token);
|
|
1626
|
-
const refused = (res, field) => problem(res.status, res.error.code, res.error.message, field, mine.headers);
|
|
1753
|
+
const refused = (res, field) => problem(res.status, res.error.code, res.error.message, field, mine.headers, res.error.reasons);
|
|
1627
1754
|
const password = typeof b.password === "string" ? b.password : "";
|
|
1628
1755
|
if (route === "/me") {
|
|
1629
1756
|
const bad = checkName(b.name);
|
|
@@ -1644,7 +1771,7 @@ function createCauthy(given = {}) {
|
|
|
1644
1771
|
return json({ status: "accepted" }, 200, mine.headers);
|
|
1645
1772
|
}
|
|
1646
1773
|
if (route === "/me/password") {
|
|
1647
|
-
const bad =
|
|
1774
|
+
const bad = await newPasswordProblem(request, b.newPassword);
|
|
1648
1775
|
if (bad) return problem(400, bad.code, bad.message, "newPassword");
|
|
1649
1776
|
const res = await as("/v1/auth/me/password", { current_password: password, new_password: b.newPassword });
|
|
1650
1777
|
if (res.error) return refused(res, res.error.code === "wrong_password" ? "password" : res.error.code === "weak_password" ? "newPassword" : void 0);
|
|
@@ -1737,7 +1864,7 @@ function createCauthy(given = {}) {
|
|
|
1737
1864
|
return json({ status: "removed", id }, 200, mine.headers);
|
|
1738
1865
|
}
|
|
1739
1866
|
if (route === "/me/upgrade") {
|
|
1740
|
-
const bad = firstProblem(checkName(b.name), checkEmail(b.email),
|
|
1867
|
+
const bad = firstProblem(checkName(b.name), checkEmail(b.email), await newPasswordProblem(request, b.password));
|
|
1741
1868
|
if (bad) return invalid(bad);
|
|
1742
1869
|
const res = await as("/v1/auth/anonymous/upgrade", { email: String(b.email).trim(), password: b.password, display_name: typeof b.name === "string" ? b.name.trim() : "" });
|
|
1743
1870
|
if (res.error) return refused(res, res.error.code === "weak_password" ? "password" : "email");
|
|
@@ -1804,10 +1931,10 @@ function createCauthy(given = {}) {
|
|
|
1804
1931
|
const badLink = () => problem(422, "invalid_token", "This link is not valid, or it has expired.");
|
|
1805
1932
|
if (route === "/reset-password") {
|
|
1806
1933
|
if (!isToken(b.token)) return badLink();
|
|
1807
|
-
const bad =
|
|
1934
|
+
const bad = await newPasswordProblem(request, b.password);
|
|
1808
1935
|
if (bad) return invalid(bad);
|
|
1809
1936
|
const res = await ask(request, "POST", "/v1/auth/password/change", { token: String(b.token), new_password: b.password });
|
|
1810
|
-
if (res.error) return problem(res.status, res.error.code, res.error.message, res.error.code === "weak_password" ? "password" : void 0);
|
|
1937
|
+
if (res.error) return problem(res.status, res.error.code, res.error.message, res.error.code === "weak_password" ? "password" : void 0, void 0, res.error.reasons);
|
|
1811
1938
|
return json({ status: "changed" });
|
|
1812
1939
|
}
|
|
1813
1940
|
if (route === "/verify-email") {
|
|
@@ -2181,6 +2308,7 @@ async function verifyToken(from, options = {}) {
|
|
|
2181
2308
|
CauthyConfigError,
|
|
2182
2309
|
CauthyTokenError,
|
|
2183
2310
|
CauthyWebhookError,
|
|
2311
|
+
DEFAULT_PASSWORD_POLICY,
|
|
2184
2312
|
MIN_PASSWORD,
|
|
2185
2313
|
can,
|
|
2186
2314
|
checkCode,
|
|
@@ -2192,6 +2320,10 @@ async function verifyToken(from, options = {}) {
|
|
|
2192
2320
|
createCauthy,
|
|
2193
2321
|
createSystem,
|
|
2194
2322
|
definePolicy,
|
|
2323
|
+
describePasswordPolicy,
|
|
2324
|
+
explainPasswordProblems,
|
|
2325
|
+
passwordPolicyOf,
|
|
2326
|
+
passwordProblems,
|
|
2195
2327
|
policySource,
|
|
2196
2328
|
pullPolicy,
|
|
2197
2329
|
pushPolicy,
|