@furystack/security 7.0.9 → 8.0.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +9 -3
  3. package/esm/crypto-password-hasher.d.ts +10 -12
  4. package/esm/crypto-password-hasher.d.ts.map +1 -1
  5. package/esm/crypto-password-hasher.js +43 -36
  6. package/esm/crypto-password-hasher.js.map +1 -1
  7. package/esm/helpers.d.ts +20 -7
  8. package/esm/helpers.d.ts.map +1 -1
  9. package/esm/helpers.js +27 -13
  10. package/esm/helpers.js.map +1 -1
  11. package/esm/index.d.ts +3 -1
  12. package/esm/index.d.ts.map +1 -1
  13. package/esm/index.js +3 -1
  14. package/esm/index.js.map +1 -1
  15. package/esm/password-authenticator.d.ts +26 -15
  16. package/esm/password-authenticator.d.ts.map +1 -1
  17. package/esm/password-authenticator.js +73 -109
  18. package/esm/password-authenticator.js.map +1 -1
  19. package/esm/password-authenticator.spec.js +122 -212
  20. package/esm/password-authenticator.spec.js.map +1 -1
  21. package/esm/password-credential-store.d.ts +50 -0
  22. package/esm/password-credential-store.d.ts.map +1 -0
  23. package/esm/password-credential-store.js +73 -0
  24. package/esm/password-credential-store.js.map +1 -0
  25. package/esm/password-credential-store.spec.d.ts +2 -0
  26. package/esm/password-credential-store.spec.d.ts.map +1 -0
  27. package/esm/password-credential-store.spec.js +64 -0
  28. package/esm/password-credential-store.spec.js.map +1 -0
  29. package/esm/password-hasher.d.ts +21 -3
  30. package/esm/password-hasher.d.ts.map +1 -1
  31. package/esm/password-hasher.js +1 -19
  32. package/esm/password-hasher.js.map +1 -1
  33. package/esm/security-policy-manager.d.ts +46 -14
  34. package/esm/security-policy-manager.d.ts.map +1 -1
  35. package/esm/security-policy-manager.js +48 -52
  36. package/esm/security-policy-manager.js.map +1 -1
  37. package/esm/security-policy-manager.spec.js +58 -7
  38. package/esm/security-policy-manager.spec.js.map +1 -1
  39. package/esm/security-policy.d.ts +35 -9
  40. package/esm/security-policy.d.ts.map +1 -1
  41. package/esm/security-policy.js +23 -33
  42. package/esm/security-policy.js.map +1 -1
  43. package/package.json +5 -5
  44. package/src/crypto-password-hasher.ts +46 -39
  45. package/src/helpers.ts +27 -15
  46. package/src/index.ts +3 -2
  47. package/src/password-authenticator.spec.ts +134 -254
  48. package/src/password-authenticator.ts +92 -86
  49. package/src/password-credential-store.spec.ts +77 -0
  50. package/src/password-credential-store.ts +79 -0
  51. package/src/password-hasher.ts +21 -9
  52. package/src/security-policy-manager.spec.ts +63 -7
  53. package/src/security-policy-manager.ts +91 -42
  54. package/src/security-policy.ts +50 -18
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [8.0.0] - 2026-04-25
4
+
5
+ ### 💥 Breaking Changes
6
+
7
+ Password policy, hasher, and authenticator are now DI tokens, not `@Injectable` classes. See the [v7 migration guide](../../docs/migrations/v7-functional-di.md) for rationale, recipes, and pitfalls.
8
+
9
+ - Removed the `@Injectable`-based `PasswordAuthenticator` and `CryptoPasswordHasher` classes. Resolve them as tokens via `injector.get(PasswordAuthenticator)` / `injector.get(CryptoPasswordHasher)`.
10
+ - Added `SecurityPolicy` interface + token. `usePasswordPolicy(injector, overrides?)` binds the settings, the hasher defaults, and the authenticator token.
11
+ - `PasswordCredentialStore` and `PasswordResetTokenStore` are now throw-by-default `StoreToken`s. Apps must `injector.bind(…, factory)` a persistent implementation before resolving anything downstream.
12
+
3
13
  ## [7.0.9] - 2026-04-17
4
14
 
5
15
  ### ⬆️ Dependencies
package/README.md CHANGED
@@ -15,10 +15,10 @@ yarn add @furystack/security
15
15
  ### Setup a password policy
16
16
 
17
17
  ```ts
18
- import { Injector } from '@furystack/inject'
18
+ import { createInjector } from '@furystack/inject'
19
19
  import { usePasswordPolicy, createMinLengthComplexityRule, createMaxLengthComplexityRule } from '@furystack/security'
20
20
 
21
- const injector = new Injector()
21
+ const injector = createInjector()
22
22
  usePasswordPolicy(injector, {
23
23
  passwordComplexityRules: [createMinLengthComplexityRule(8), createMaxLengthComplexityRule(64)],
24
24
  passwordExpirationDays: 90,
@@ -26,12 +26,18 @@ usePasswordPolicy(injector, {
26
26
  })
27
27
  ```
28
28
 
29
+ `usePasswordPolicy` binds the `SecurityPolicy` settings, the
30
+ `CryptoPasswordHasher` defaults, and the `PasswordAuthenticator` token.
31
+ Applications must also bind concrete stores for the
32
+ `PasswordCredentialStore` and `PasswordResetTokenStore` tokens (they
33
+ throw by default) before resolving anything that depends on them.
34
+
29
35
  ### Check if a user's password is valid
30
36
 
31
37
  ```ts
32
38
  import { PasswordAuthenticator } from '@furystack/security'
33
39
 
34
- const authenticator = injector.getInstance(PasswordAuthenticator)
40
+ const authenticator = injector.get(PasswordAuthenticator)
35
41
 
36
42
  const userName = 'john_doe'
37
43
  const plainPassword = 'SecureP@ssw0rd!'
@@ -1,14 +1,12 @@
1
+ import { type Token } from '@furystack/inject';
1
2
  import type { PasswordHasher } from './password-hasher.js';
2
- import type { PasswordCheckResult, PasswordCredential } from './models/index.js';
3
- export declare class CryptoPasswordHasher implements PasswordHasher {
4
- private readonly iterations;
5
- private readonly keylen;
6
- verifyCredential(password: string, { passwordHash, salt }: PasswordCredential): Promise<PasswordCheckResult>;
7
- createCredential(userName: string, password: string): Promise<{
8
- userName: string;
9
- salt: string;
10
- passwordHash: string;
11
- creationDate: string;
12
- }>;
13
- }
3
+ /**
4
+ * Default PBKDF2-based {@link PasswordHasher} implementation. Uses SHA-512
5
+ * with 1000 iterations and a 64-byte derived key length.
6
+ *
7
+ * Swap this token in {@link SecurityPolicy.hasher} to replace the hashing
8
+ * algorithm — for example with a stronger Argon2 implementation or a
9
+ * delegated hashing service.
10
+ */
11
+ export declare const CryptoPasswordHasher: Token<PasswordHasher, 'singleton'>;
14
12
  //# sourceMappingURL=crypto-password-hasher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-password-hasher.d.ts","sourceRoot":"","sources":["../src/crypto-password-hasher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEhF,qBACa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAK;IAEf,gBAAgB,CAC3B,QAAQ,EAAE,MAAM,EAChB,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,kBAAkB,GACzC,OAAO,CAAC,mBAAmB,CAAC;IAgBlB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;CAcjE"}
1
+ {"version":3,"file":"crypto-password-hasher.d.ts","sourceRoot":"","sources":["../src/crypto-password-hasher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAG7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAiB1D;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,cAAc,EAAE,WAAW,CAsBlE,CAAA"}
@@ -1,39 +1,46 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- import { Injectable } from '@furystack/inject';
8
- import { randomBytes, pbkdf2 } from 'crypto';
9
- let CryptoPasswordHasher = class CryptoPasswordHasher {
10
- iterations = 1000;
11
- keylen = 64;
12
- async verifyCredential(password, { passwordHash, salt }) {
13
- const newHash = await new Promise((resolve, reject) => pbkdf2(password, salt, this.iterations, this.keylen, 'sha512', (err, key) => err ? reject(err) : resolve(key.toString('hex'))));
14
- if (newHash === passwordHash) {
1
+ import { defineService } from '@furystack/inject';
2
+ import { pbkdf2, randomBytes } from 'crypto';
3
+ const ITERATIONS = 1000;
4
+ const KEY_LENGTH = 64;
5
+ const SALT_BYTES = 16;
6
+ const deriveHash = (password, salt) => new Promise((resolve, reject) => {
7
+ pbkdf2(password, salt, ITERATIONS, KEY_LENGTH, 'sha512', (err, key) => {
8
+ if (err) {
9
+ reject(err);
10
+ return;
11
+ }
12
+ resolve(key.toString('hex'));
13
+ });
14
+ });
15
+ /**
16
+ * Default PBKDF2-based {@link PasswordHasher} implementation. Uses SHA-512
17
+ * with 1000 iterations and a 64-byte derived key length.
18
+ *
19
+ * Swap this token in {@link SecurityPolicy.hasher} to replace the hashing
20
+ * algorithm — for example with a stronger Argon2 implementation or a
21
+ * delegated hashing service.
22
+ */
23
+ export const CryptoPasswordHasher = defineService({
24
+ name: 'furystack/security/CryptoPasswordHasher',
25
+ lifetime: 'singleton',
26
+ factory: () => ({
27
+ verifyCredential: async (password, { passwordHash, salt }) => {
28
+ const candidate = await deriveHash(password, salt);
29
+ if (candidate === passwordHash) {
30
+ return { isValid: true };
31
+ }
32
+ return { isValid: false, reason: 'badUsernameOrPassword' };
33
+ },
34
+ createCredential: async (userName, password) => {
35
+ const salt = randomBytes(SALT_BYTES).toString('hex');
36
+ const passwordHash = await deriveHash(password, salt);
15
37
  return {
16
- isValid: true,
38
+ userName,
39
+ salt,
40
+ passwordHash,
41
+ creationDate: new Date().toISOString(),
17
42
  };
18
- }
19
- return {
20
- isValid: false,
21
- reason: 'badUsernameOrPassword',
22
- };
23
- }
24
- async createCredential(userName, password) {
25
- const salt = randomBytes(16).toString('hex');
26
- const passwordHash = await new Promise((resolve, reject) => pbkdf2(password, salt, this.iterations, this.keylen, 'sha512', (err, key) => err ? reject(err) : resolve(key.toString('hex'))));
27
- return {
28
- userName,
29
- salt,
30
- passwordHash,
31
- creationDate: new Date().toISOString(),
32
- };
33
- }
34
- };
35
- CryptoPasswordHasher = __decorate([
36
- Injectable({ lifetime: 'singleton' })
37
- ], CryptoPasswordHasher);
38
- export { CryptoPasswordHasher };
43
+ },
44
+ }),
45
+ });
39
46
  //# sourceMappingURL=crypto-password-hasher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-password-hasher.js","sourceRoot":"","sources":["../src/crypto-password-hasher.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAIrC,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IACd,UAAU,GAAG,IAAI,CAAA;IACjB,MAAM,GAAG,EAAE,CAAA;IAErB,KAAK,CAAC,gBAAgB,CAC3B,QAAgB,EAChB,EAAE,YAAY,EAAE,IAAI,EAAsB;QAE1C,MAAM,OAAO,GAAG,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CACpD,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAC1E,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CACjD,CACF,CAAA;QACD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO,EAAE,IAAI;aACd,CAAA;QACH,CAAC;QACD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,uBAAuB;SAChC,CAAA;IACH,CAAC;IACM,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,QAAgB;QAC9D,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC5C,MAAM,YAAY,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CACjE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAC1E,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CACjD,CACF,CAAA;QACD,OAAO;YACL,QAAQ;YACR,IAAI;YACJ,YAAY;YACZ,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACvC,CAAA;IACH,CAAC;CACF,CAAA;AArCY,oBAAoB;IADhC,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,oBAAoB,CAqChC"}
1
+ {"version":3,"file":"crypto-password-hasher.js","sourceRoot":"","sources":["../src/crypto-password-hasher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAc,MAAM,mBAAmB,CAAA;AAC7D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAI5C,MAAM,UAAU,GAAG,IAAI,CAAA;AACvB,MAAM,UAAU,GAAG,EAAE,CAAA;AACrB,MAAM,UAAU,GAAG,EAAE,CAAA;AAErB,MAAM,UAAU,GAAG,CAAC,QAAgB,EAAE,IAAY,EAAmB,EAAE,CACrE,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACtC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACpE,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,CAAC,GAAG,CAAC,CAAA;YACX,OAAM;QACR,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEJ;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAuC,aAAa,CAAC;IACpF,IAAI,EAAE,yCAAyC;IAC/C,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,GAAmB,EAAE,CAAC,CAAC;QAC9B,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,EAAgC,EAAE;YACzF,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAClD,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;gBAC/B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YAC1B,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAA;QAC5D,CAAC;QACD,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;YAC7C,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACpD,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YACrD,OAAO;gBACL,QAAQ;gBACR,IAAI;gBACJ,YAAY;gBACZ,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACvC,CAAA;QACH,CAAC;KACF,CAAC;CACH,CAAC,CAAA"}
package/esm/helpers.d.ts CHANGED
@@ -1,14 +1,27 @@
1
1
  import type { Injector } from '@furystack/inject';
2
2
  import { SecurityPolicy } from './security-policy.js';
3
3
  /**
4
- * Sets up the @furystack/security with the provided settings.
4
+ * Rebinds the {@link SecurityPolicy} on the given injector with the default
5
+ * policy merged with `overrides`.
5
6
  *
6
- * **Prerequisite:** DataSets for `PasswordCredential` and `PasswordResetToken` must be registered
7
- * via `getRepository(injector).createDataSet()` before `PasswordAuthenticator` is instantiated,
8
- * as it resolves these DataSets through `@Injected`.
7
+ * Apply this at application setup before resolving any service that reads
8
+ * the policy — {@link PasswordAuthenticator}, {@link SecurityPolicyManager}
9
+ * or direct `injector.get(SecurityPolicy)` callers. Because those services
10
+ * capture the policy at resolve time, calling `usePasswordPolicy` after
11
+ * they have been resolved has no effect unless you also invalidate them.
9
12
  *
10
- * @param injector The Injector instance
11
- * @param policy The security policy to use
13
+ * **Prerequisite:** bind persistent implementations of
14
+ * `PasswordCredentialStore` and `PasswordResetTokenStore` before resolving
15
+ * {@link PasswordAuthenticator}. Their default factories throw on purpose
16
+ * so password data is never silently kept in-memory.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * usePasswordPolicy(injector, {
21
+ * passwordExpirationDays: 90,
22
+ * passwordComplexityRules: [createMinLengthComplexityRule(8)],
23
+ * })
24
+ * ```
12
25
  */
13
- export declare const usePasswordPolicy: (injector: Injector, policy?: Partial<SecurityPolicy>) => void;
26
+ export declare const usePasswordPolicy: (injector: Injector, overrides?: Partial<SecurityPolicy>) => void;
14
27
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,QAAQ,EAAE,SAAS,OAAO,CAAC,cAAc,CAAC,SAQrF,CAAA"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAGjD,OAAO,EAAyB,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE5E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,QAAQ,EAAE,YAAY,OAAO,CAAC,cAAc,CAAC,KAAG,IAK3F,CAAA"}
package/esm/helpers.js CHANGED
@@ -1,19 +1,33 @@
1
- import { SecurityPolicy } from './security-policy.js';
1
+ import { PasswordAuthenticator } from './password-authenticator.js';
2
+ import { SecurityPolicyManager } from './security-policy-manager.js';
3
+ import { defaultSecurityPolicy, SecurityPolicy } from './security-policy.js';
2
4
  /**
3
- * Sets up the @furystack/security with the provided settings.
5
+ * Rebinds the {@link SecurityPolicy} on the given injector with the default
6
+ * policy merged with `overrides`.
4
7
  *
5
- * **Prerequisite:** DataSets for `PasswordCredential` and `PasswordResetToken` must be registered
6
- * via `getRepository(injector).createDataSet()` before `PasswordAuthenticator` is instantiated,
7
- * as it resolves these DataSets through `@Injected`.
8
+ * Apply this at application setup before resolving any service that reads
9
+ * the policy — {@link PasswordAuthenticator}, {@link SecurityPolicyManager}
10
+ * or direct `injector.get(SecurityPolicy)` callers. Because those services
11
+ * capture the policy at resolve time, calling `usePasswordPolicy` after
12
+ * they have been resolved has no effect unless you also invalidate them.
8
13
  *
9
- * @param injector The Injector instance
10
- * @param policy The security policy to use
14
+ * **Prerequisite:** bind persistent implementations of
15
+ * `PasswordCredentialStore` and `PasswordResetTokenStore` before resolving
16
+ * {@link PasswordAuthenticator}. Their default factories throw on purpose
17
+ * so password data is never silently kept in-memory.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * usePasswordPolicy(injector, {
22
+ * passwordExpirationDays: 90,
23
+ * passwordComplexityRules: [createMinLengthComplexityRule(8)],
24
+ * })
25
+ * ```
11
26
  */
12
- export const usePasswordPolicy = (injector, policy) => {
13
- const plainPolicy = new SecurityPolicy();
14
- if (policy) {
15
- Object.assign(plainPolicy, policy);
16
- }
17
- injector.setExplicitInstance(plainPolicy, SecurityPolicy);
27
+ export const usePasswordPolicy = (injector, overrides) => {
28
+ injector.bind(SecurityPolicy, () => ({ ...defaultSecurityPolicy(), ...overrides }));
29
+ injector.invalidate(SecurityPolicy);
30
+ injector.invalidate(SecurityPolicyManager);
31
+ injector.invalidate(PasswordAuthenticator);
18
32
  };
19
33
  //# sourceMappingURL=helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAkB,EAAE,MAAgC,EAAE,EAAE;IACxF,MAAM,WAAW,GAAG,IAAI,cAAc,EAAE,CAAA;IAExC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IACpC,CAAC;IAED,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;AAC3D,CAAC,CAAA"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE5E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAkB,EAAE,SAAmC,EAAQ,EAAE;IACjG,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,qBAAqB,EAAE,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC,CAAA;IACnF,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC,CAAA;IACnC,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAA;IAC1C,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAA;AAC5C,CAAC,CAAA"}
package/esm/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export * from './crypto-password-hasher.js';
2
2
  export * from './errors/index.js';
3
+ export * from './helpers.js';
3
4
  export * from './models/index.js';
4
5
  export * from './password-authenticator.js';
5
6
  export * from './password-complexity-rules/index.js';
7
+ export * from './password-credential-store.js';
6
8
  export * from './password-hasher.js';
7
9
  export * from './security-policy-manager.js';
8
- export * from './helpers.js';
10
+ export * from './security-policy.js';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sCAAsC,CAAA;AACpD,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAE5C,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sCAAsC,CAAA;AACpD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,sBAAsB,CAAA"}
package/esm/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  export * from './crypto-password-hasher.js';
2
2
  export * from './errors/index.js';
3
+ export * from './helpers.js';
3
4
  export * from './models/index.js';
4
5
  export * from './password-authenticator.js';
5
6
  export * from './password-complexity-rules/index.js';
7
+ export * from './password-credential-store.js';
6
8
  export * from './password-hasher.js';
7
9
  export * from './security-policy-manager.js';
8
- export * from './helpers.js';
10
+ export * from './security-policy.js';
9
11
  //# sourceMappingURL=index.js.map
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sCAAsC,CAAA;AACpD,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAE5C,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sCAAsC,CAAA;AACpD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,sBAAsB,CAAA"}
@@ -1,30 +1,41 @@
1
+ import { type Token } from '@furystack/inject';
1
2
  import type { PasswordCheckResult } from './models/index.js';
2
3
  import type { PasswordHasher } from './password-hasher.js';
3
4
  import { SecurityPolicyManager } from './security-policy-manager.js';
4
- export declare class PasswordAuthenticator {
5
- private readonly systemInjector;
6
- private readonly passwordDataSet;
7
- private readonly tokenDataSet;
5
+ /**
6
+ * Authenticator surface: check stored credentials, rotate passwords and
7
+ * consume reset tokens. All writes are funneled through a system-identity
8
+ * scope so the underlying DataSets skip caller-scoped authorization.
9
+ */
10
+ export interface PasswordAuthenticator {
11
+ /** The hasher bound by the active {@link SecurityPolicy}. Exposed for use in tests and migration helpers. */
8
12
  readonly hasher: PasswordHasher;
13
+ /** The {@link SecurityPolicyManager} resolved at construction. */
14
+ readonly policyManager: SecurityPolicyManager;
9
15
  /**
10
- * @param userName The User's unique name
11
- * @param plainPassword The plain password to check
12
- * @returns An object that contains an { isValid } value that indicates if the password is valid
16
+ * Verifies that the stored credential for `userName` matches
17
+ * `plainPassword` and honours the policy's expiration rules.
13
18
  */
14
19
  checkPasswordForUser(userName: string, plainPassword: string): Promise<PasswordCheckResult>;
15
20
  /**
16
- * Sets the password for the specific user
17
- * @param userName The user to set the password for
18
- * @param lastPassword The last user password
19
- * @param plainPassword The password as a plain string
21
+ * Replaces the stored credential for `userName` with one derived from
22
+ * `plainPassword`. Requires the current `lastPassword` to be valid and
23
+ * `plainPassword` to pass the configured complexity rules.
20
24
  */
21
25
  setPasswordForUser(userName: string, lastPassword: string, plainPassword: string): Promise<void>;
22
26
  /**
23
- * Resets the password with a Password Reset token entry
24
- * @param resetToken The Reset Token value
25
- * @param plainPassword The new password in plain string
27
+ * Consumes `resetToken` and rotates the associated user's password to
28
+ * one derived from `plainPassword`. Expired tokens are rejected and
29
+ * cleaned up; bad tokens raise {@link UnauthenticatedError}.
26
30
  */
27
31
  resetPasswordForUser(resetToken: string, plainPassword: string): Promise<void>;
28
- policyManager: SecurityPolicyManager;
29
32
  }
33
+ /**
34
+ * DI token for the singleton {@link PasswordAuthenticator}.
35
+ *
36
+ * The factory creates a system-identity child scope once (at first
37
+ * resolution) and uses it for every credential mutation. The scope is
38
+ * torn down alongside the owning injector via `onDispose`.
39
+ */
40
+ export declare const PasswordAuthenticator: Token<PasswordAuthenticator, 'singleton'>;
30
41
  //# sourceMappingURL=password-authenticator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"password-authenticator.d.ts","sourceRoot":"","sources":["../src/password-authenticator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEpE,qBACa,qBAAqB;IAChC,iBACyB,cAAc,CAAU;IAEjD,iBACyB,eAAe,CAAyC;IAEjF,iBACyB,YAAY,CAAsC;IAE3E,SAGwB,MAAM,EAAE,cAAc,CAAA;IAE9C;;;;OAIG;IACU,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkBxG;;;;;OAKG;IACU,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7G;;;;OAIG;IACU,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B5E,aAAa,EAAE,qBAAqB,CAAA;CACpD"}
1
+ {"version":3,"file":"password-authenticator.d.ts","sourceRoot":"","sources":["../src/password-authenticator.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAG7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEpE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,6GAA6G;IAC7G,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAA;IAC7C;;;OAGG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC3F;;;;OAIG;IACH,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChG;;;;OAIG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/E;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,qBAAqB,EAAE,WAAW,CAoE1E,CAAA"}
@@ -1,114 +1,78 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
1
  import { useSystemIdentityContext } from '@furystack/core';
11
- import { Injectable, Injected } from '@furystack/inject';
12
- import { getDataSetFor } from '@furystack/repository';
2
+ import { defineService } from '@furystack/inject';
13
3
  import { UnauthenticatedError } from './errors/index.js';
14
4
  import { PasswordComplexityError } from './errors/password-complexity-error.js';
15
- import { PasswordCredential, PasswordResetToken } from './models/index.js';
5
+ import { PasswordCredentialDataSet, PasswordResetTokenDataSet } from './password-credential-store.js';
16
6
  import { SecurityPolicyManager } from './security-policy-manager.js';
17
- let PasswordAuthenticator = class PasswordAuthenticator {
18
- /**
19
- * @param userName The User's unique name
20
- * @param plainPassword The plain password to check
21
- * @returns An object that contains an { isValid } value that indicates if the password is valid
22
- */
23
- async checkPasswordForUser(userName, plainPassword) {
24
- const entry = await this.passwordDataSet.get(this.systemInjector, userName);
25
- if (!entry) {
26
- return {
27
- isValid: false,
28
- reason: 'badUsernameOrPassword',
29
- };
30
- }
31
- const result = await this.hasher.verifyCredential(plainPassword, entry);
32
- if (result.isValid && this.policyManager.hasPasswordExpired(entry)) {
33
- return {
34
- isValid: false,
35
- reason: 'passwordExpired',
36
- };
37
- }
38
- return result;
39
- }
40
- /**
41
- * Sets the password for the specific user
42
- * @param userName The user to set the password for
43
- * @param lastPassword The last user password
44
- * @param plainPassword The password as a plain string
45
- */
46
- async setPasswordForUser(userName, lastPassword, plainPassword) {
47
- const complexityResult = await this.policyManager.matchPasswordComplexityRules(plainPassword);
48
- if (!complexityResult.match) {
49
- throw new PasswordComplexityError(complexityResult.errors);
50
- }
51
- const lastResult = await this.checkPasswordForUser(userName, lastPassword);
52
- if (!lastResult.isValid) {
53
- throw new UnauthenticatedError();
54
- }
55
- const newCredential = await this.hasher.createCredential(userName, plainPassword);
56
- const existing = await this.passwordDataSet.get(this.systemInjector, userName);
57
- if (existing) {
58
- await this.passwordDataSet.remove(this.systemInjector, existing.userName);
59
- }
60
- await this.passwordDataSet.add(this.systemInjector, newCredential);
61
- }
62
- /**
63
- * Resets the password with a Password Reset token entry
64
- * @param resetToken The Reset Token value
65
- * @param plainPassword The new password in plain string
66
- */
67
- async resetPasswordForUser(resetToken, plainPassword) {
68
- const token = await this.tokenDataSet.get(this.systemInjector, resetToken);
69
- if (!token) {
70
- throw new UnauthenticatedError();
71
- }
72
- if (this.policyManager.hasTokenExpired(token)) {
73
- await this.tokenDataSet.remove(this.systemInjector, resetToken);
74
- throw new UnauthenticatedError();
75
- }
76
- const complexityResult = await this.policyManager.matchPasswordComplexityRules(plainPassword);
77
- if (!complexityResult.match) {
78
- throw new PasswordComplexityError(complexityResult.errors);
79
- }
80
- const newCredential = await this.hasher.createCredential(token.userName, plainPassword);
81
- const existing = await this.passwordDataSet.get(this.systemInjector, token.userName);
82
- if (existing) {
83
- await this.passwordDataSet.remove(this.systemInjector, existing.userName);
84
- }
85
- await this.passwordDataSet.add(this.systemInjector, newCredential);
86
- }
87
- };
88
- __decorate([
89
- Injected((injector) => useSystemIdentityContext({ injector, username: 'PasswordAuthenticator' })),
90
- __metadata("design:type", Function)
91
- ], PasswordAuthenticator.prototype, "systemInjector", void 0);
92
- __decorate([
93
- Injected((injector) => getDataSetFor(injector, PasswordCredential, 'userName')),
94
- __metadata("design:type", Function)
95
- ], PasswordAuthenticator.prototype, "passwordDataSet", void 0);
96
- __decorate([
97
- Injected((injector) => getDataSetFor(injector, PasswordResetToken, 'token')),
98
- __metadata("design:type", Function)
99
- ], PasswordAuthenticator.prototype, "tokenDataSet", void 0);
100
- __decorate([
101
- Injected(function (injector) {
102
- return injector.getInstance(this.policyManager.policy.hasher);
103
- }),
104
- __metadata("design:type", Function)
105
- ], PasswordAuthenticator.prototype, "hasher", void 0);
106
- __decorate([
107
- Injected(SecurityPolicyManager),
108
- __metadata("design:type", SecurityPolicyManager)
109
- ], PasswordAuthenticator.prototype, "policyManager", void 0);
110
- PasswordAuthenticator = __decorate([
111
- Injectable({ lifetime: 'singleton' })
112
- ], PasswordAuthenticator);
113
- export { PasswordAuthenticator };
7
+ /**
8
+ * DI token for the singleton {@link PasswordAuthenticator}.
9
+ *
10
+ * The factory creates a system-identity child scope once (at first
11
+ * resolution) and uses it for every credential mutation. The scope is
12
+ * torn down alongside the owning injector via `onDispose`.
13
+ */
14
+ export const PasswordAuthenticator = defineService({
15
+ name: 'furystack/security/PasswordAuthenticator',
16
+ lifetime: 'singleton',
17
+ factory: ({ inject, injector, onDispose }) => {
18
+ const policyManager = inject(SecurityPolicyManager);
19
+ const hasher = inject(policyManager.policy.hasher);
20
+ const passwordDataSet = inject(PasswordCredentialDataSet);
21
+ const tokenDataSet = inject(PasswordResetTokenDataSet);
22
+ const systemInjector = useSystemIdentityContext({ injector, username: 'PasswordAuthenticator' });
23
+ onDispose(() => systemInjector[Symbol.asyncDispose]());
24
+ const checkPasswordForUser = async (userName, plainPassword) => {
25
+ const entry = await passwordDataSet.get(systemInjector, userName);
26
+ if (!entry) {
27
+ return { isValid: false, reason: 'badUsernameOrPassword' };
28
+ }
29
+ const result = await hasher.verifyCredential(plainPassword, entry);
30
+ if (result.isValid && policyManager.hasPasswordExpired(entry)) {
31
+ return { isValid: false, reason: 'passwordExpired' };
32
+ }
33
+ return result;
34
+ };
35
+ const replaceCredential = async (userName, plainPassword) => {
36
+ const newCredential = await hasher.createCredential(userName, plainPassword);
37
+ const existing = await passwordDataSet.get(systemInjector, userName);
38
+ if (existing) {
39
+ await passwordDataSet.remove(systemInjector, existing.userName);
40
+ }
41
+ await passwordDataSet.add(systemInjector, newCredential);
42
+ };
43
+ const setPasswordForUser = async (userName, lastPassword, plainPassword) => {
44
+ const complexityResult = await policyManager.matchPasswordComplexityRules(plainPassword);
45
+ if (!complexityResult.match) {
46
+ throw new PasswordComplexityError(complexityResult.errors);
47
+ }
48
+ const lastResult = await checkPasswordForUser(userName, lastPassword);
49
+ if (!lastResult.isValid) {
50
+ throw new UnauthenticatedError();
51
+ }
52
+ await replaceCredential(userName, plainPassword);
53
+ };
54
+ const resetPasswordForUser = async (resetToken, plainPassword) => {
55
+ const token = await tokenDataSet.get(systemInjector, resetToken);
56
+ if (!token) {
57
+ throw new UnauthenticatedError();
58
+ }
59
+ if (policyManager.hasTokenExpired(token)) {
60
+ await tokenDataSet.remove(systemInjector, resetToken);
61
+ throw new UnauthenticatedError();
62
+ }
63
+ const complexityResult = await policyManager.matchPasswordComplexityRules(plainPassword);
64
+ if (!complexityResult.match) {
65
+ throw new PasswordComplexityError(complexityResult.errors);
66
+ }
67
+ await replaceCredential(token.userName, plainPassword);
68
+ };
69
+ return {
70
+ hasher,
71
+ policyManager,
72
+ checkPasswordForUser,
73
+ setPasswordForUser,
74
+ resetPasswordForUser,
75
+ };
76
+ },
77
+ });
114
78
  //# sourceMappingURL=password-authenticator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"password-authenticator.js","sourceRoot":"","sources":["../src/password-authenticator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"password-authenticator.js","sourceRoot":"","sources":["../src/password-authenticator.ts"],"names":[],"mappings":"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"}