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