@absolutejs/auth 0.27.0-beta.6 → 0.27.0-beta.7

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.
@@ -19,6 +19,7 @@ export type CredentialEmailMessage = {
19
19
  type: CredentialEmailType;
20
20
  };
21
21
  export type CredentialsConfig<UserType> = {
22
+ checkBreachesOnLogin?: boolean;
22
23
  credentialStore: CredentialStore;
23
24
  getUserByEmail: (email: string) => Promise<UserType | null | undefined> | UserType | null | undefined;
24
25
  isMfaRequired?: (user: UserType) => boolean | Promise<boolean>;
@@ -1,6 +1,6 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import { type CredentialRouteProps } from './config';
3
- export declare const credentialsLogin: <UserType>({ authSessionStore, credentialStore, getUserByEmail, isMfaRequired, lockoutGuard, loginRoute, onCredentialsLoginError, onCredentialsLoginSuccess, requireEmailVerification, sessionDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
3
+ export declare const credentialsLogin: <UserType>({ authSessionStore, checkBreachesOnLogin, credentialStore, getUserByEmail, isMfaRequired, lockoutGuard, loginRoute, onCredentialsLoginError, onCredentialsLoginSuccess, requireEmailVerification, sessionDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
4
4
  decorator: {};
5
5
  store: {
6
6
  session: import("..").SessionRecord<UserType>;
@@ -32,6 +32,7 @@ export declare const credentialsLogin: <UserType>({ authSessionStore, credential
32
32
  200: {
33
33
  readonly status: "mfa_required";
34
34
  } | {
35
+ readonly passwordCompromised: boolean;
35
36
  readonly status: "authenticated";
36
37
  };
37
38
  401: "Invalid email or password";
@@ -100,6 +100,7 @@ export declare const credentialRoutes: <UserType>(config: CredentialRouteProps<U
100
100
  200: {
101
101
  readonly status: "mfa_required";
102
102
  } | {
103
+ readonly passwordCompromised: boolean;
103
104
  readonly status: "authenticated";
104
105
  };
105
106
  401: "Invalid email or password";
package/dist/index.d.ts CHANGED
@@ -12725,6 +12725,7 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
12725
12725
  200: {
12726
12726
  readonly status: "mfa_required";
12727
12727
  } | {
12728
+ readonly passwordCompromised: boolean;
12728
12729
  readonly status: "authenticated";
12729
12730
  };
12730
12731
  401: "Invalid email or password";
package/dist/index.js CHANGED
@@ -3391,8 +3391,60 @@ var credentialsEmailVerification = ({
3391
3391
 
3392
3392
  // src/credentials/login.ts
3393
3393
  import { Elysia as Elysia6, t as t6 } from "elysia";
3394
+
3395
+ // src/credentials/passwordPolicy.ts
3396
+ var DEFAULT_MIN_LENGTH = 12;
3397
+ var HEX_RADIX = 16;
3398
+ var HIBP_PREFIX_LENGTH = 5;
3399
+ var HIBP_RANGE_URL = "https://api.pwnedpasswords.com/range/";
3400
+ var sha1Hex = async (input) => {
3401
+ const digest = await crypto.subtle.digest("SHA-1", new TextEncoder().encode(input));
3402
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(HEX_RADIX).padStart(2, "0")).join("").toUpperCase();
3403
+ };
3404
+ var isPasswordBreached = async (password) => {
3405
+ try {
3406
+ const hash = await sha1Hex(password);
3407
+ const prefix = hash.slice(0, HIBP_PREFIX_LENGTH);
3408
+ const suffix = hash.slice(HIBP_PREFIX_LENGTH);
3409
+ const response = await fetch(`${HIBP_RANGE_URL}${prefix}`);
3410
+ if (!response.ok)
3411
+ return false;
3412
+ const body = await response.text();
3413
+ return body.split(`
3414
+ `).some((line) => line.split(":")[0]?.trim() === suffix);
3415
+ } catch {
3416
+ return false;
3417
+ }
3418
+ };
3419
+ var evaluatePassword = async (password, policy = {}) => {
3420
+ const minLength = policy.minLength ?? DEFAULT_MIN_LENGTH;
3421
+ const violations = [];
3422
+ if (password.length < minLength) {
3423
+ violations.push("too_short");
3424
+ }
3425
+ if (policy.requireUppercase && !/[A-Z]/u.test(password)) {
3426
+ violations.push("missing_uppercase");
3427
+ }
3428
+ if (policy.requireLowercase && !/[a-z]/u.test(password)) {
3429
+ violations.push("missing_lowercase");
3430
+ }
3431
+ if (policy.requireDigit && !/\d/u.test(password)) {
3432
+ violations.push("missing_digit");
3433
+ }
3434
+ if (policy.requireSymbol && !/[^A-Za-z0-9]/u.test(password)) {
3435
+ violations.push("missing_symbol");
3436
+ }
3437
+ if (policy.checkBreaches && await isPasswordBreached(password)) {
3438
+ violations.push("breached");
3439
+ }
3440
+ return { ok: violations.length === 0, violations };
3441
+ };
3442
+ var isPasswordCompromised = (password) => isPasswordBreached(password);
3443
+
3444
+ // src/credentials/login.ts
3394
3445
  var credentialsLogin = ({
3395
3446
  authSessionStore,
3447
+ checkBreachesOnLogin,
3396
3448
  credentialStore,
3397
3449
  getUserByEmail,
3398
3450
  isMfaRequired,
@@ -3451,6 +3503,7 @@ var credentialsLogin = ({
3451
3503
  await persistWhen(authSessionStore !== undefined, compatibilityLayer.persist);
3452
3504
  return status("OK", { status: "mfa_required" });
3453
3505
  }
3506
+ const passwordCompromised = checkBreachesOnLogin ? await isPasswordCompromised(password) : false;
3454
3507
  const userSessionId = await promoteToSession({
3455
3508
  authSessionStore,
3456
3509
  cookie: user_session_id,
@@ -3459,7 +3512,7 @@ var credentialsLogin = ({
3459
3512
  user
3460
3513
  });
3461
3514
  await onCredentialsLoginSuccess?.({ user, userSessionId });
3462
- return status("OK", { status: "authenticated" });
3515
+ return status("OK", { passwordCompromised, status: "authenticated" });
3463
3516
  }, {
3464
3517
  body: t6.Object({ email: t6.String(), password: t6.String() }),
3465
3518
  cookie: t6.Cookie({ user_session_id: userSessionIdTypebox })
@@ -3467,57 +3520,6 @@ var credentialsLogin = ({
3467
3520
 
3468
3521
  // src/credentials/passwordReset.ts
3469
3522
  import { Elysia as Elysia7, t as t7 } from "elysia";
3470
-
3471
- // src/credentials/passwordPolicy.ts
3472
- var DEFAULT_MIN_LENGTH = 12;
3473
- var HEX_RADIX = 16;
3474
- var HIBP_PREFIX_LENGTH = 5;
3475
- var HIBP_RANGE_URL = "https://api.pwnedpasswords.com/range/";
3476
- var sha1Hex = async (input) => {
3477
- const digest = await crypto.subtle.digest("SHA-1", new TextEncoder().encode(input));
3478
- return [...new Uint8Array(digest)].map((byte) => byte.toString(HEX_RADIX).padStart(2, "0")).join("").toUpperCase();
3479
- };
3480
- var isPasswordBreached = async (password) => {
3481
- try {
3482
- const hash = await sha1Hex(password);
3483
- const prefix = hash.slice(0, HIBP_PREFIX_LENGTH);
3484
- const suffix = hash.slice(HIBP_PREFIX_LENGTH);
3485
- const response = await fetch(`${HIBP_RANGE_URL}${prefix}`);
3486
- if (!response.ok)
3487
- return false;
3488
- const body = await response.text();
3489
- return body.split(`
3490
- `).some((line) => line.split(":")[0]?.trim() === suffix);
3491
- } catch {
3492
- return false;
3493
- }
3494
- };
3495
- var evaluatePassword = async (password, policy = {}) => {
3496
- const minLength = policy.minLength ?? DEFAULT_MIN_LENGTH;
3497
- const violations = [];
3498
- if (password.length < minLength) {
3499
- violations.push("too_short");
3500
- }
3501
- if (policy.requireUppercase && !/[A-Z]/u.test(password)) {
3502
- violations.push("missing_uppercase");
3503
- }
3504
- if (policy.requireLowercase && !/[a-z]/u.test(password)) {
3505
- violations.push("missing_lowercase");
3506
- }
3507
- if (policy.requireDigit && !/\d/u.test(password)) {
3508
- violations.push("missing_digit");
3509
- }
3510
- if (policy.requireSymbol && !/[^A-Za-z0-9]/u.test(password)) {
3511
- violations.push("missing_symbol");
3512
- }
3513
- if (policy.checkBreaches && await isPasswordBreached(password)) {
3514
- violations.push("breached");
3515
- }
3516
- return { ok: violations.length === 0, violations };
3517
- };
3518
- var isPasswordCompromised = (password) => isPasswordBreached(password);
3519
-
3520
- // src/credentials/passwordReset.ts
3521
3523
  var credentialsPasswordReset = ({
3522
3524
  credentialStore,
3523
3525
  onPasswordReset,
@@ -20974,5 +20976,5 @@ export {
20974
20976
  AuthIdentityConflictError
20975
20977
  };
20976
20978
 
20977
- //# debugId=D6A51261327D341C64756E2164756E21
20979
+ //# debugId=580D3E8ACE9EF4E864756E2164756E21
20978
20980
  //# sourceMappingURL=index.js.map