@furystack/security 7.0.9 → 8.0.1

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 (90) hide show
  1. package/CHANGELOG.md +21 -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/errors/password-complexity-error.d.ts +5 -4
  8. package/esm/errors/password-complexity-error.d.ts.map +1 -1
  9. package/esm/errors/password-complexity-error.js +5 -4
  10. package/esm/errors/password-complexity-error.js.map +1 -1
  11. package/esm/errors/unauthenticated-error.d.ts +3 -1
  12. package/esm/errors/unauthenticated-error.d.ts.map +1 -1
  13. package/esm/errors/unauthenticated-error.js +3 -1
  14. package/esm/errors/unauthenticated-error.js.map +1 -1
  15. package/esm/helpers.d.ts +20 -7
  16. package/esm/helpers.d.ts.map +1 -1
  17. package/esm/helpers.js +27 -13
  18. package/esm/helpers.js.map +1 -1
  19. package/esm/index.d.ts +3 -1
  20. package/esm/index.d.ts.map +1 -1
  21. package/esm/index.js +3 -1
  22. package/esm/index.js.map +1 -1
  23. package/esm/models/password-credential.d.ts +3 -13
  24. package/esm/models/password-credential.d.ts.map +1 -1
  25. package/esm/models/password-credential.js +3 -1
  26. package/esm/models/password-credential.js.map +1 -1
  27. package/esm/models/password-reset-token.d.ts +5 -9
  28. package/esm/models/password-reset-token.d.ts.map +1 -1
  29. package/esm/models/password-reset-token.js +5 -0
  30. package/esm/models/password-reset-token.js.map +1 -1
  31. package/esm/password-authenticator.d.ts +26 -15
  32. package/esm/password-authenticator.d.ts.map +1 -1
  33. package/esm/password-authenticator.js +73 -109
  34. package/esm/password-authenticator.js.map +1 -1
  35. package/esm/password-authenticator.spec.js +122 -212
  36. package/esm/password-authenticator.spec.js.map +1 -1
  37. package/esm/password-complexity-rules/contains-lowercase.d.ts +2 -2
  38. package/esm/password-complexity-rules/contains-lowercase.js +2 -2
  39. package/esm/password-complexity-rules/contains-uppercase.d.ts +2 -2
  40. package/esm/password-complexity-rules/contains-uppercase.js +2 -2
  41. package/esm/password-complexity-rules/max-length.d.ts +1 -4
  42. package/esm/password-complexity-rules/max-length.d.ts.map +1 -1
  43. package/esm/password-complexity-rules/max-length.js +1 -4
  44. package/esm/password-complexity-rules/max-length.js.map +1 -1
  45. package/esm/password-complexity-rules/min-length.d.ts +1 -4
  46. package/esm/password-complexity-rules/min-length.d.ts.map +1 -1
  47. package/esm/password-complexity-rules/min-length.js +1 -4
  48. package/esm/password-complexity-rules/min-length.js.map +1 -1
  49. package/esm/password-credential-store.d.ts +50 -0
  50. package/esm/password-credential-store.d.ts.map +1 -0
  51. package/esm/password-credential-store.js +73 -0
  52. package/esm/password-credential-store.js.map +1 -0
  53. package/esm/password-credential-store.spec.d.ts +2 -0
  54. package/esm/password-credential-store.spec.d.ts.map +1 -0
  55. package/esm/password-credential-store.spec.js +64 -0
  56. package/esm/password-credential-store.spec.js.map +1 -0
  57. package/esm/password-hasher.d.ts +21 -3
  58. package/esm/password-hasher.d.ts.map +1 -1
  59. package/esm/password-hasher.js +1 -19
  60. package/esm/password-hasher.js.map +1 -1
  61. package/esm/security-policy-manager.d.ts +46 -14
  62. package/esm/security-policy-manager.d.ts.map +1 -1
  63. package/esm/security-policy-manager.js +48 -52
  64. package/esm/security-policy-manager.js.map +1 -1
  65. package/esm/security-policy-manager.spec.js +58 -7
  66. package/esm/security-policy-manager.spec.js.map +1 -1
  67. package/esm/security-policy.d.ts +35 -9
  68. package/esm/security-policy.d.ts.map +1 -1
  69. package/esm/security-policy.js +23 -33
  70. package/esm/security-policy.js.map +1 -1
  71. package/package.json +7 -7
  72. package/src/crypto-password-hasher.ts +46 -39
  73. package/src/errors/password-complexity-error.ts +7 -4
  74. package/src/errors/unauthenticated-error.ts +3 -1
  75. package/src/helpers.ts +27 -15
  76. package/src/index.ts +3 -2
  77. package/src/models/password-credential.ts +5 -15
  78. package/src/models/password-reset-token.ts +5 -9
  79. package/src/password-authenticator.spec.ts +134 -254
  80. package/src/password-authenticator.ts +92 -86
  81. package/src/password-complexity-rules/contains-lowercase.ts +2 -2
  82. package/src/password-complexity-rules/contains-uppercase.ts +2 -2
  83. package/src/password-complexity-rules/max-length.ts +1 -4
  84. package/src/password-complexity-rules/min-length.ts +1 -4
  85. package/src/password-credential-store.spec.ts +77 -0
  86. package/src/password-credential-store.ts +79 -0
  87. package/src/password-hasher.ts +21 -9
  88. package/src/security-policy-manager.spec.ts +63 -7
  89. package/src/security-policy-manager.ts +91 -42
  90. package/src/security-policy.ts +50 -18
@@ -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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"}