@twin.org/api-auth-entity-storage-service 0.0.2-next.11 → 0.0.2-next.12
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/cjs/index.cjs +37 -39
- package/dist/esm/index.mjs +37 -39
- package/dist/types/processors/authHeaderProcessor.d.ts +1 -1
- package/dist/types/services/entityStorageAuthenticationAdminService.d.ts +1 -1
- package/dist/types/services/entityStorageAuthenticationService.d.ts +1 -1
- package/dist/types/utils/passwordHelper.d.ts +4 -0
- package/dist/types/utils/tokenHelper.d.ts +4 -0
- package/docs/changelog.md +16 -0
- package/docs/reference/classes/AuthHeaderProcessor.md +1 -5
- package/docs/reference/classes/EntityStorageAuthenticationAdminService.md +1 -5
- package/docs/reference/classes/EntityStorageAuthenticationService.md +1 -5
- package/docs/reference/classes/PasswordHelper.md +8 -0
- package/docs/reference/classes/TokenHelper.md +8 -0
- package/locales/en.json +2 -6
- package/package.json +24 -5
package/dist/cjs/index.cjs
CHANGED
|
@@ -59,9 +59,8 @@ exports.AuthenticationUser = __decorate([
|
|
|
59
59
|
class TokenHelper {
|
|
60
60
|
/**
|
|
61
61
|
* Runtime name for the class.
|
|
62
|
-
* @internal
|
|
63
62
|
*/
|
|
64
|
-
static
|
|
63
|
+
static CLASS_NAME = "TokenHelper";
|
|
65
64
|
/**
|
|
66
65
|
* Create a new token.
|
|
67
66
|
* @param vaultConnector The vault connector.
|
|
@@ -92,16 +91,16 @@ class TokenHelper {
|
|
|
92
91
|
*/
|
|
93
92
|
static async verify(vaultConnector, signingKeyName, token) {
|
|
94
93
|
if (!core.Is.stringValue(token)) {
|
|
95
|
-
throw new core.UnauthorizedError(
|
|
94
|
+
throw new core.UnauthorizedError(TokenHelper.CLASS_NAME, "missing");
|
|
96
95
|
}
|
|
97
96
|
const decoded = await web.Jwt.verifyWithVerifier(token, async (t) => vaultModels.VaultConnectorHelper.jwtVerifier(vaultConnector, signingKeyName, t));
|
|
98
97
|
// If some of the header/payload data is not properly populated then it is unauthorized.
|
|
99
98
|
if (!core.Is.stringValue(decoded.payload.sub)) {
|
|
100
|
-
throw new core.UnauthorizedError(
|
|
99
|
+
throw new core.UnauthorizedError(TokenHelper.CLASS_NAME, "payloadMissingSubject");
|
|
101
100
|
}
|
|
102
101
|
else if (!core.Is.empty(decoded.payload?.exp) &&
|
|
103
102
|
decoded.payload.exp < Math.trunc(Date.now() / 1000)) {
|
|
104
|
-
throw new core.UnauthorizedError(
|
|
103
|
+
throw new core.UnauthorizedError(TokenHelper.CLASS_NAME, "expired");
|
|
105
104
|
}
|
|
106
105
|
return {
|
|
107
106
|
header: decoded.header,
|
|
@@ -158,7 +157,7 @@ class AuthHeaderProcessor {
|
|
|
158
157
|
/**
|
|
159
158
|
* Runtime name for the class.
|
|
160
159
|
*/
|
|
161
|
-
CLASS_NAME = "AuthHeaderProcessor";
|
|
160
|
+
static CLASS_NAME = "AuthHeaderProcessor";
|
|
162
161
|
/**
|
|
163
162
|
* The vault for the keys.
|
|
164
163
|
* @internal
|
|
@@ -195,7 +194,7 @@ class AuthHeaderProcessor {
|
|
|
195
194
|
* @returns Nothing.
|
|
196
195
|
*/
|
|
197
196
|
async start(nodeIdentity, nodeLoggingComponentType) {
|
|
198
|
-
core.Guards.string(
|
|
197
|
+
core.Guards.string(AuthHeaderProcessor.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
199
198
|
this._nodeIdentity = nodeIdentity;
|
|
200
199
|
}
|
|
201
200
|
/**
|
|
@@ -523,9 +522,8 @@ function initSchema() {
|
|
|
523
522
|
class PasswordHelper {
|
|
524
523
|
/**
|
|
525
524
|
* Runtime name for the class.
|
|
526
|
-
* @internal
|
|
527
525
|
*/
|
|
528
|
-
static
|
|
526
|
+
static CLASS_NAME = "PasswordHelper";
|
|
529
527
|
/**
|
|
530
528
|
* Hash the password for the user.
|
|
531
529
|
* @param passwordBytes The password bytes.
|
|
@@ -533,8 +531,8 @@ class PasswordHelper {
|
|
|
533
531
|
* @returns The hashed password.
|
|
534
532
|
*/
|
|
535
533
|
static async hashPassword(passwordBytes, saltBytes) {
|
|
536
|
-
core.Guards.uint8Array(PasswordHelper.
|
|
537
|
-
core.Guards.uint8Array(PasswordHelper.
|
|
534
|
+
core.Guards.uint8Array(PasswordHelper.CLASS_NAME, "passwordBytes", passwordBytes);
|
|
535
|
+
core.Guards.uint8Array(PasswordHelper.CLASS_NAME, "saltBytes", saltBytes);
|
|
538
536
|
const combined = new Uint8Array(saltBytes.length + passwordBytes.length);
|
|
539
537
|
combined.set(saltBytes);
|
|
540
538
|
combined.set(passwordBytes, saltBytes.length);
|
|
@@ -547,15 +545,15 @@ class PasswordHelper {
|
|
|
547
545
|
* Implementation of the authentication component using entity storage.
|
|
548
546
|
*/
|
|
549
547
|
class EntityStorageAuthenticationAdminService {
|
|
548
|
+
/**
|
|
549
|
+
* Runtime name for the class.
|
|
550
|
+
*/
|
|
551
|
+
static CLASS_NAME = "EntityStorageAuthenticationAdminService";
|
|
550
552
|
/**
|
|
551
553
|
* The minimum password length.
|
|
552
554
|
* @internal
|
|
553
555
|
*/
|
|
554
556
|
static _DEFAULT_MIN_PASSWORD_LENGTH = 8;
|
|
555
|
-
/**
|
|
556
|
-
* Runtime name for the class.
|
|
557
|
-
*/
|
|
558
|
-
CLASS_NAME = "EntityStorageAuthenticationAdminService";
|
|
559
557
|
/**
|
|
560
558
|
* The entity storage for users.
|
|
561
559
|
* @internal
|
|
@@ -584,17 +582,17 @@ class EntityStorageAuthenticationAdminService {
|
|
|
584
582
|
* @returns Nothing.
|
|
585
583
|
*/
|
|
586
584
|
async create(email, password, identity) {
|
|
587
|
-
core.Guards.stringValue(
|
|
588
|
-
core.Guards.stringValue(
|
|
585
|
+
core.Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "email", email);
|
|
586
|
+
core.Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "password", password);
|
|
589
587
|
try {
|
|
590
588
|
if (password.length < this._minPasswordLength) {
|
|
591
|
-
throw new core.GeneralError(
|
|
589
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "passwordTooShort", {
|
|
592
590
|
minLength: this._minPasswordLength
|
|
593
591
|
});
|
|
594
592
|
}
|
|
595
593
|
const user = await this._userEntityStorage.get(email);
|
|
596
594
|
if (user) {
|
|
597
|
-
throw new core.GeneralError(
|
|
595
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "userExists");
|
|
598
596
|
}
|
|
599
597
|
const saltBytes = core.RandomHelper.generate(16);
|
|
600
598
|
const passwordBytes = core.Converter.utf8ToBytes(password);
|
|
@@ -608,7 +606,7 @@ class EntityStorageAuthenticationAdminService {
|
|
|
608
606
|
await this._userEntityStorage.set(newUser);
|
|
609
607
|
}
|
|
610
608
|
catch (error) {
|
|
611
|
-
throw new core.GeneralError(
|
|
609
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "createUserFailed", undefined, error);
|
|
612
610
|
}
|
|
613
611
|
}
|
|
614
612
|
/**
|
|
@@ -617,16 +615,16 @@ class EntityStorageAuthenticationAdminService {
|
|
|
617
615
|
* @returns Nothing.
|
|
618
616
|
*/
|
|
619
617
|
async remove(email) {
|
|
620
|
-
core.Guards.stringValue(
|
|
618
|
+
core.Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "email", email);
|
|
621
619
|
try {
|
|
622
620
|
const user = await this._userEntityStorage.get(email);
|
|
623
621
|
if (!user) {
|
|
624
|
-
throw new core.NotFoundError(
|
|
622
|
+
throw new core.NotFoundError(EntityStorageAuthenticationAdminService.CLASS_NAME, "userNotFound", email);
|
|
625
623
|
}
|
|
626
624
|
await this._userEntityStorage.remove(email);
|
|
627
625
|
}
|
|
628
626
|
catch (error) {
|
|
629
|
-
throw new core.GeneralError(
|
|
627
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "removeUserFailed", undefined, error);
|
|
630
628
|
}
|
|
631
629
|
}
|
|
632
630
|
/**
|
|
@@ -637,24 +635,24 @@ class EntityStorageAuthenticationAdminService {
|
|
|
637
635
|
* @returns Nothing.
|
|
638
636
|
*/
|
|
639
637
|
async updatePassword(email, newPassword, currentPassword) {
|
|
640
|
-
core.Guards.stringValue(
|
|
641
|
-
core.Guards.stringValue(
|
|
638
|
+
core.Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "email", email);
|
|
639
|
+
core.Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "newPassword", newPassword);
|
|
642
640
|
try {
|
|
643
641
|
if (newPassword.length < this._minPasswordLength) {
|
|
644
|
-
throw new core.GeneralError(
|
|
642
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "passwordTooShort", {
|
|
645
643
|
minLength: this._minPasswordLength
|
|
646
644
|
});
|
|
647
645
|
}
|
|
648
646
|
const user = await this._userEntityStorage.get(email);
|
|
649
647
|
if (!user) {
|
|
650
|
-
throw new core.NotFoundError(
|
|
648
|
+
throw new core.NotFoundError(EntityStorageAuthenticationAdminService.CLASS_NAME, "userNotFound", email);
|
|
651
649
|
}
|
|
652
650
|
if (core.Is.stringValue(currentPassword)) {
|
|
653
651
|
const saltBytes = core.Converter.base64ToBytes(user.salt);
|
|
654
652
|
const passwordBytes = core.Converter.utf8ToBytes(currentPassword);
|
|
655
653
|
const hashedPassword = await PasswordHelper.hashPassword(passwordBytes, saltBytes);
|
|
656
654
|
if (hashedPassword !== user.password) {
|
|
657
|
-
throw new core.GeneralError(
|
|
655
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "currentPasswordMismatch");
|
|
658
656
|
}
|
|
659
657
|
}
|
|
660
658
|
const saltBytes = core.RandomHelper.generate(16);
|
|
@@ -669,7 +667,7 @@ class EntityStorageAuthenticationAdminService {
|
|
|
669
667
|
await this._userEntityStorage.set(updatedUser);
|
|
670
668
|
}
|
|
671
669
|
catch (error) {
|
|
672
|
-
throw new core.GeneralError(
|
|
670
|
+
throw new core.GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "updatePasswordFailed", undefined, error);
|
|
673
671
|
}
|
|
674
672
|
}
|
|
675
673
|
}
|
|
@@ -678,15 +676,15 @@ class EntityStorageAuthenticationAdminService {
|
|
|
678
676
|
* Implementation of the authentication component using entity storage.
|
|
679
677
|
*/
|
|
680
678
|
class EntityStorageAuthenticationService {
|
|
679
|
+
/**
|
|
680
|
+
* Runtime name for the class.
|
|
681
|
+
*/
|
|
682
|
+
static CLASS_NAME = "EntityStorageAuthenticationService";
|
|
681
683
|
/**
|
|
682
684
|
* Default TTL in minutes.
|
|
683
685
|
* @internal
|
|
684
686
|
*/
|
|
685
687
|
static _DEFAULT_TTL_MINUTES = 60;
|
|
686
|
-
/**
|
|
687
|
-
* Runtime name for the class.
|
|
688
|
-
*/
|
|
689
|
-
CLASS_NAME = "EntityStorageAuthenticationService";
|
|
690
688
|
/**
|
|
691
689
|
* The user admin service.
|
|
692
690
|
* @internal
|
|
@@ -736,7 +734,7 @@ class EntityStorageAuthenticationService {
|
|
|
736
734
|
* @returns Nothing.
|
|
737
735
|
*/
|
|
738
736
|
async start(nodeIdentity, nodeLoggingComponentType) {
|
|
739
|
-
core.Guards.string(
|
|
737
|
+
core.Guards.string(EntityStorageAuthenticationService.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
740
738
|
this._nodeIdentity = nodeIdentity;
|
|
741
739
|
}
|
|
742
740
|
/**
|
|
@@ -746,24 +744,24 @@ class EntityStorageAuthenticationService {
|
|
|
746
744
|
* @returns The authentication token for the user, if it uses a mechanism with public access.
|
|
747
745
|
*/
|
|
748
746
|
async login(email, password) {
|
|
749
|
-
core.Guards.stringValue(
|
|
750
|
-
core.Guards.stringValue(
|
|
747
|
+
core.Guards.stringValue(EntityStorageAuthenticationService.CLASS_NAME, "email", email);
|
|
748
|
+
core.Guards.stringValue(EntityStorageAuthenticationService.CLASS_NAME, "password", password);
|
|
751
749
|
try {
|
|
752
750
|
const user = await this._userEntityStorage.get(email);
|
|
753
751
|
if (!user) {
|
|
754
|
-
throw new core.GeneralError(
|
|
752
|
+
throw new core.GeneralError(EntityStorageAuthenticationService.CLASS_NAME, "userNotFound");
|
|
755
753
|
}
|
|
756
754
|
const saltBytes = core.Converter.base64ToBytes(user.salt);
|
|
757
755
|
const passwordBytes = core.Converter.utf8ToBytes(password);
|
|
758
756
|
const hashedPassword = await PasswordHelper.hashPassword(passwordBytes, saltBytes);
|
|
759
757
|
if (hashedPassword !== user.password) {
|
|
760
|
-
throw new core.GeneralError(
|
|
758
|
+
throw new core.GeneralError(EntityStorageAuthenticationService.CLASS_NAME, "passwordMismatch");
|
|
761
759
|
}
|
|
762
760
|
const tokenAndExpiry = await TokenHelper.createToken(this._vaultConnector, `${this._nodeIdentity}/${this._signingKeyName}`, user.identity, this._defaultTtlMinutes);
|
|
763
761
|
return tokenAndExpiry;
|
|
764
762
|
}
|
|
765
763
|
catch (error) {
|
|
766
|
-
throw new core.UnauthorizedError(
|
|
764
|
+
throw new core.UnauthorizedError(EntityStorageAuthenticationService.CLASS_NAME, "loginFailed", undefined, error);
|
|
767
765
|
}
|
|
768
766
|
}
|
|
769
767
|
/**
|
package/dist/esm/index.mjs
CHANGED
|
@@ -57,9 +57,8 @@ AuthenticationUser = __decorate([
|
|
|
57
57
|
class TokenHelper {
|
|
58
58
|
/**
|
|
59
59
|
* Runtime name for the class.
|
|
60
|
-
* @internal
|
|
61
60
|
*/
|
|
62
|
-
static
|
|
61
|
+
static CLASS_NAME = "TokenHelper";
|
|
63
62
|
/**
|
|
64
63
|
* Create a new token.
|
|
65
64
|
* @param vaultConnector The vault connector.
|
|
@@ -90,16 +89,16 @@ class TokenHelper {
|
|
|
90
89
|
*/
|
|
91
90
|
static async verify(vaultConnector, signingKeyName, token) {
|
|
92
91
|
if (!Is.stringValue(token)) {
|
|
93
|
-
throw new UnauthorizedError(
|
|
92
|
+
throw new UnauthorizedError(TokenHelper.CLASS_NAME, "missing");
|
|
94
93
|
}
|
|
95
94
|
const decoded = await Jwt.verifyWithVerifier(token, async (t) => VaultConnectorHelper.jwtVerifier(vaultConnector, signingKeyName, t));
|
|
96
95
|
// If some of the header/payload data is not properly populated then it is unauthorized.
|
|
97
96
|
if (!Is.stringValue(decoded.payload.sub)) {
|
|
98
|
-
throw new UnauthorizedError(
|
|
97
|
+
throw new UnauthorizedError(TokenHelper.CLASS_NAME, "payloadMissingSubject");
|
|
99
98
|
}
|
|
100
99
|
else if (!Is.empty(decoded.payload?.exp) &&
|
|
101
100
|
decoded.payload.exp < Math.trunc(Date.now() / 1000)) {
|
|
102
|
-
throw new UnauthorizedError(
|
|
101
|
+
throw new UnauthorizedError(TokenHelper.CLASS_NAME, "expired");
|
|
103
102
|
}
|
|
104
103
|
return {
|
|
105
104
|
header: decoded.header,
|
|
@@ -156,7 +155,7 @@ class AuthHeaderProcessor {
|
|
|
156
155
|
/**
|
|
157
156
|
* Runtime name for the class.
|
|
158
157
|
*/
|
|
159
|
-
CLASS_NAME = "AuthHeaderProcessor";
|
|
158
|
+
static CLASS_NAME = "AuthHeaderProcessor";
|
|
160
159
|
/**
|
|
161
160
|
* The vault for the keys.
|
|
162
161
|
* @internal
|
|
@@ -193,7 +192,7 @@ class AuthHeaderProcessor {
|
|
|
193
192
|
* @returns Nothing.
|
|
194
193
|
*/
|
|
195
194
|
async start(nodeIdentity, nodeLoggingComponentType) {
|
|
196
|
-
Guards.string(
|
|
195
|
+
Guards.string(AuthHeaderProcessor.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
197
196
|
this._nodeIdentity = nodeIdentity;
|
|
198
197
|
}
|
|
199
198
|
/**
|
|
@@ -521,9 +520,8 @@ function initSchema() {
|
|
|
521
520
|
class PasswordHelper {
|
|
522
521
|
/**
|
|
523
522
|
* Runtime name for the class.
|
|
524
|
-
* @internal
|
|
525
523
|
*/
|
|
526
|
-
static
|
|
524
|
+
static CLASS_NAME = "PasswordHelper";
|
|
527
525
|
/**
|
|
528
526
|
* Hash the password for the user.
|
|
529
527
|
* @param passwordBytes The password bytes.
|
|
@@ -531,8 +529,8 @@ class PasswordHelper {
|
|
|
531
529
|
* @returns The hashed password.
|
|
532
530
|
*/
|
|
533
531
|
static async hashPassword(passwordBytes, saltBytes) {
|
|
534
|
-
Guards.uint8Array(PasswordHelper.
|
|
535
|
-
Guards.uint8Array(PasswordHelper.
|
|
532
|
+
Guards.uint8Array(PasswordHelper.CLASS_NAME, "passwordBytes", passwordBytes);
|
|
533
|
+
Guards.uint8Array(PasswordHelper.CLASS_NAME, "saltBytes", saltBytes);
|
|
536
534
|
const combined = new Uint8Array(saltBytes.length + passwordBytes.length);
|
|
537
535
|
combined.set(saltBytes);
|
|
538
536
|
combined.set(passwordBytes, saltBytes.length);
|
|
@@ -545,15 +543,15 @@ class PasswordHelper {
|
|
|
545
543
|
* Implementation of the authentication component using entity storage.
|
|
546
544
|
*/
|
|
547
545
|
class EntityStorageAuthenticationAdminService {
|
|
546
|
+
/**
|
|
547
|
+
* Runtime name for the class.
|
|
548
|
+
*/
|
|
549
|
+
static CLASS_NAME = "EntityStorageAuthenticationAdminService";
|
|
548
550
|
/**
|
|
549
551
|
* The minimum password length.
|
|
550
552
|
* @internal
|
|
551
553
|
*/
|
|
552
554
|
static _DEFAULT_MIN_PASSWORD_LENGTH = 8;
|
|
553
|
-
/**
|
|
554
|
-
* Runtime name for the class.
|
|
555
|
-
*/
|
|
556
|
-
CLASS_NAME = "EntityStorageAuthenticationAdminService";
|
|
557
555
|
/**
|
|
558
556
|
* The entity storage for users.
|
|
559
557
|
* @internal
|
|
@@ -582,17 +580,17 @@ class EntityStorageAuthenticationAdminService {
|
|
|
582
580
|
* @returns Nothing.
|
|
583
581
|
*/
|
|
584
582
|
async create(email, password, identity) {
|
|
585
|
-
Guards.stringValue(
|
|
586
|
-
Guards.stringValue(
|
|
583
|
+
Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "email", email);
|
|
584
|
+
Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "password", password);
|
|
587
585
|
try {
|
|
588
586
|
if (password.length < this._minPasswordLength) {
|
|
589
|
-
throw new GeneralError(
|
|
587
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "passwordTooShort", {
|
|
590
588
|
minLength: this._minPasswordLength
|
|
591
589
|
});
|
|
592
590
|
}
|
|
593
591
|
const user = await this._userEntityStorage.get(email);
|
|
594
592
|
if (user) {
|
|
595
|
-
throw new GeneralError(
|
|
593
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "userExists");
|
|
596
594
|
}
|
|
597
595
|
const saltBytes = RandomHelper.generate(16);
|
|
598
596
|
const passwordBytes = Converter.utf8ToBytes(password);
|
|
@@ -606,7 +604,7 @@ class EntityStorageAuthenticationAdminService {
|
|
|
606
604
|
await this._userEntityStorage.set(newUser);
|
|
607
605
|
}
|
|
608
606
|
catch (error) {
|
|
609
|
-
throw new GeneralError(
|
|
607
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "createUserFailed", undefined, error);
|
|
610
608
|
}
|
|
611
609
|
}
|
|
612
610
|
/**
|
|
@@ -615,16 +613,16 @@ class EntityStorageAuthenticationAdminService {
|
|
|
615
613
|
* @returns Nothing.
|
|
616
614
|
*/
|
|
617
615
|
async remove(email) {
|
|
618
|
-
Guards.stringValue(
|
|
616
|
+
Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "email", email);
|
|
619
617
|
try {
|
|
620
618
|
const user = await this._userEntityStorage.get(email);
|
|
621
619
|
if (!user) {
|
|
622
|
-
throw new NotFoundError(
|
|
620
|
+
throw new NotFoundError(EntityStorageAuthenticationAdminService.CLASS_NAME, "userNotFound", email);
|
|
623
621
|
}
|
|
624
622
|
await this._userEntityStorage.remove(email);
|
|
625
623
|
}
|
|
626
624
|
catch (error) {
|
|
627
|
-
throw new GeneralError(
|
|
625
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "removeUserFailed", undefined, error);
|
|
628
626
|
}
|
|
629
627
|
}
|
|
630
628
|
/**
|
|
@@ -635,24 +633,24 @@ class EntityStorageAuthenticationAdminService {
|
|
|
635
633
|
* @returns Nothing.
|
|
636
634
|
*/
|
|
637
635
|
async updatePassword(email, newPassword, currentPassword) {
|
|
638
|
-
Guards.stringValue(
|
|
639
|
-
Guards.stringValue(
|
|
636
|
+
Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "email", email);
|
|
637
|
+
Guards.stringValue(EntityStorageAuthenticationAdminService.CLASS_NAME, "newPassword", newPassword);
|
|
640
638
|
try {
|
|
641
639
|
if (newPassword.length < this._minPasswordLength) {
|
|
642
|
-
throw new GeneralError(
|
|
640
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "passwordTooShort", {
|
|
643
641
|
minLength: this._minPasswordLength
|
|
644
642
|
});
|
|
645
643
|
}
|
|
646
644
|
const user = await this._userEntityStorage.get(email);
|
|
647
645
|
if (!user) {
|
|
648
|
-
throw new NotFoundError(
|
|
646
|
+
throw new NotFoundError(EntityStorageAuthenticationAdminService.CLASS_NAME, "userNotFound", email);
|
|
649
647
|
}
|
|
650
648
|
if (Is.stringValue(currentPassword)) {
|
|
651
649
|
const saltBytes = Converter.base64ToBytes(user.salt);
|
|
652
650
|
const passwordBytes = Converter.utf8ToBytes(currentPassword);
|
|
653
651
|
const hashedPassword = await PasswordHelper.hashPassword(passwordBytes, saltBytes);
|
|
654
652
|
if (hashedPassword !== user.password) {
|
|
655
|
-
throw new GeneralError(
|
|
653
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "currentPasswordMismatch");
|
|
656
654
|
}
|
|
657
655
|
}
|
|
658
656
|
const saltBytes = RandomHelper.generate(16);
|
|
@@ -667,7 +665,7 @@ class EntityStorageAuthenticationAdminService {
|
|
|
667
665
|
await this._userEntityStorage.set(updatedUser);
|
|
668
666
|
}
|
|
669
667
|
catch (error) {
|
|
670
|
-
throw new GeneralError(
|
|
668
|
+
throw new GeneralError(EntityStorageAuthenticationAdminService.CLASS_NAME, "updatePasswordFailed", undefined, error);
|
|
671
669
|
}
|
|
672
670
|
}
|
|
673
671
|
}
|
|
@@ -676,15 +674,15 @@ class EntityStorageAuthenticationAdminService {
|
|
|
676
674
|
* Implementation of the authentication component using entity storage.
|
|
677
675
|
*/
|
|
678
676
|
class EntityStorageAuthenticationService {
|
|
677
|
+
/**
|
|
678
|
+
* Runtime name for the class.
|
|
679
|
+
*/
|
|
680
|
+
static CLASS_NAME = "EntityStorageAuthenticationService";
|
|
679
681
|
/**
|
|
680
682
|
* Default TTL in minutes.
|
|
681
683
|
* @internal
|
|
682
684
|
*/
|
|
683
685
|
static _DEFAULT_TTL_MINUTES = 60;
|
|
684
|
-
/**
|
|
685
|
-
* Runtime name for the class.
|
|
686
|
-
*/
|
|
687
|
-
CLASS_NAME = "EntityStorageAuthenticationService";
|
|
688
686
|
/**
|
|
689
687
|
* The user admin service.
|
|
690
688
|
* @internal
|
|
@@ -734,7 +732,7 @@ class EntityStorageAuthenticationService {
|
|
|
734
732
|
* @returns Nothing.
|
|
735
733
|
*/
|
|
736
734
|
async start(nodeIdentity, nodeLoggingComponentType) {
|
|
737
|
-
Guards.string(
|
|
735
|
+
Guards.string(EntityStorageAuthenticationService.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
738
736
|
this._nodeIdentity = nodeIdentity;
|
|
739
737
|
}
|
|
740
738
|
/**
|
|
@@ -744,24 +742,24 @@ class EntityStorageAuthenticationService {
|
|
|
744
742
|
* @returns The authentication token for the user, if it uses a mechanism with public access.
|
|
745
743
|
*/
|
|
746
744
|
async login(email, password) {
|
|
747
|
-
Guards.stringValue(
|
|
748
|
-
Guards.stringValue(
|
|
745
|
+
Guards.stringValue(EntityStorageAuthenticationService.CLASS_NAME, "email", email);
|
|
746
|
+
Guards.stringValue(EntityStorageAuthenticationService.CLASS_NAME, "password", password);
|
|
749
747
|
try {
|
|
750
748
|
const user = await this._userEntityStorage.get(email);
|
|
751
749
|
if (!user) {
|
|
752
|
-
throw new GeneralError(
|
|
750
|
+
throw new GeneralError(EntityStorageAuthenticationService.CLASS_NAME, "userNotFound");
|
|
753
751
|
}
|
|
754
752
|
const saltBytes = Converter.base64ToBytes(user.salt);
|
|
755
753
|
const passwordBytes = Converter.utf8ToBytes(password);
|
|
756
754
|
const hashedPassword = await PasswordHelper.hashPassword(passwordBytes, saltBytes);
|
|
757
755
|
if (hashedPassword !== user.password) {
|
|
758
|
-
throw new GeneralError(
|
|
756
|
+
throw new GeneralError(EntityStorageAuthenticationService.CLASS_NAME, "passwordMismatch");
|
|
759
757
|
}
|
|
760
758
|
const tokenAndExpiry = await TokenHelper.createToken(this._vaultConnector, `${this._nodeIdentity}/${this._signingKeyName}`, user.identity, this._defaultTtlMinutes);
|
|
761
759
|
return tokenAndExpiry;
|
|
762
760
|
}
|
|
763
761
|
catch (error) {
|
|
764
|
-
throw new UnauthorizedError(
|
|
762
|
+
throw new UnauthorizedError(EntityStorageAuthenticationService.CLASS_NAME, "loginFailed", undefined, error);
|
|
765
763
|
}
|
|
766
764
|
}
|
|
767
765
|
/**
|
|
@@ -7,7 +7,7 @@ export declare class AuthHeaderProcessor implements IBaseRouteProcessor {
|
|
|
7
7
|
/**
|
|
8
8
|
* Runtime name for the class.
|
|
9
9
|
*/
|
|
10
|
-
readonly CLASS_NAME: string;
|
|
10
|
+
static readonly CLASS_NAME: string;
|
|
11
11
|
/**
|
|
12
12
|
* Create a new instance of AuthCookiePreProcessor.
|
|
13
13
|
* @param options Options for the processor.
|
|
@@ -7,7 +7,7 @@ export declare class EntityStorageAuthenticationAdminService implements IAuthent
|
|
|
7
7
|
/**
|
|
8
8
|
* Runtime name for the class.
|
|
9
9
|
*/
|
|
10
|
-
readonly CLASS_NAME: string;
|
|
10
|
+
static readonly CLASS_NAME: string;
|
|
11
11
|
/**
|
|
12
12
|
* Create a new instance of EntityStorageAuthentication.
|
|
13
13
|
* @param options The dependencies for the identity connector.
|
|
@@ -7,7 +7,7 @@ export declare class EntityStorageAuthenticationService implements IAuthenticati
|
|
|
7
7
|
/**
|
|
8
8
|
* Runtime name for the class.
|
|
9
9
|
*/
|
|
10
|
-
readonly CLASS_NAME: string;
|
|
10
|
+
static readonly CLASS_NAME: string;
|
|
11
11
|
/**
|
|
12
12
|
* Create a new instance of EntityStorageAuthentication.
|
|
13
13
|
* @param options The dependencies for the identity connector.
|
|
@@ -4,6 +4,10 @@ import { type IHttpHeaders, type IJwtHeader, type IJwtPayload } from "@twin.org/
|
|
|
4
4
|
* Helper class for token operations.
|
|
5
5
|
*/
|
|
6
6
|
export declare class TokenHelper {
|
|
7
|
+
/**
|
|
8
|
+
* Runtime name for the class.
|
|
9
|
+
*/
|
|
10
|
+
static readonly CLASS_NAME: string;
|
|
7
11
|
/**
|
|
8
12
|
* Create a new token.
|
|
9
13
|
* @param vaultConnector The vault connector.
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @twin.org/api-auth-entity-storage-service - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.12](https://github.com/twinfoundation/api/compare/api-auth-entity-storage-service-v0.0.2-next.11...api-auth-entity-storage-service-v0.0.2-next.12) (2025-10-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add validate-locales ([cdba610](https://github.com/twinfoundation/api/commit/cdba610a0acb5022d2e3ce729732e6646a297e5e))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/api-auth-entity-storage-models bumped from 0.0.2-next.11 to 0.0.2-next.12
|
|
16
|
+
* @twin.org/api-core bumped from 0.0.2-next.11 to 0.0.2-next.12
|
|
17
|
+
* @twin.org/api-models bumped from 0.0.2-next.11 to 0.0.2-next.12
|
|
18
|
+
|
|
3
19
|
## [0.0.2-next.11](https://github.com/twinfoundation/api/compare/api-auth-entity-storage-service-v0.0.2-next.10...api-auth-entity-storage-service-v0.0.2-next.11) (2025-09-29)
|
|
4
20
|
|
|
5
21
|
|
|
@@ -30,14 +30,10 @@ Options for the processor.
|
|
|
30
30
|
|
|
31
31
|
### CLASS\_NAME
|
|
32
32
|
|
|
33
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
33
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
34
34
|
|
|
35
35
|
Runtime name for the class.
|
|
36
36
|
|
|
37
|
-
#### Implementation of
|
|
38
|
-
|
|
39
|
-
`IBaseRouteProcessor.CLASS_NAME`
|
|
40
|
-
|
|
41
37
|
## Methods
|
|
42
38
|
|
|
43
39
|
### start()
|
|
@@ -30,14 +30,10 @@ The dependencies for the identity connector.
|
|
|
30
30
|
|
|
31
31
|
### CLASS\_NAME
|
|
32
32
|
|
|
33
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
33
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
34
34
|
|
|
35
35
|
Runtime name for the class.
|
|
36
36
|
|
|
37
|
-
#### Implementation of
|
|
38
|
-
|
|
39
|
-
`IAuthenticationAdminComponent.CLASS_NAME`
|
|
40
|
-
|
|
41
37
|
## Methods
|
|
42
38
|
|
|
43
39
|
### create()
|
|
@@ -30,14 +30,10 @@ The dependencies for the identity connector.
|
|
|
30
30
|
|
|
31
31
|
### CLASS\_NAME
|
|
32
32
|
|
|
33
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
33
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
34
34
|
|
|
35
35
|
Runtime name for the class.
|
|
36
36
|
|
|
37
|
-
#### Implementation of
|
|
38
|
-
|
|
39
|
-
`IAuthenticationComponent.CLASS_NAME`
|
|
40
|
-
|
|
41
37
|
## Methods
|
|
42
38
|
|
|
43
39
|
### start()
|
package/locales/en.json
CHANGED
|
@@ -2,22 +2,18 @@
|
|
|
2
2
|
"error": {
|
|
3
3
|
"entityStorageAuthenticationService": {
|
|
4
4
|
"loginFailed": "Login failed",
|
|
5
|
-
"refreshFailed": "Refresh failed",
|
|
6
5
|
"userNotFound": "The user with the specified e-mail could not be found",
|
|
7
6
|
"passwordMismatch": "The password does not match the user's password"
|
|
8
7
|
},
|
|
9
8
|
"entityStorageAuthenticationAdminService": {
|
|
10
9
|
"userExists": "The user with the specified e-mail already exists",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
10
|
+
"createUserFailed": "Creating the user failed",
|
|
11
|
+
"removeUserFailed": "Removing the user failed",
|
|
13
12
|
"updatePasswordFailed": "Updating the user's password failed",
|
|
14
13
|
"passwordTooShort": "The password is too short, it must be at least {minLength} characters long",
|
|
15
14
|
"userNotFound": "The user with the specified e-mail could not be found \"{notFoundId}\"",
|
|
16
15
|
"currentPasswordMismatch": "The current password is incorrect"
|
|
17
16
|
},
|
|
18
|
-
"entityStorageAuthenticationProcessor": {
|
|
19
|
-
"initializeFailed": "The JSON Web token authentication processor could not be initialized"
|
|
20
|
-
},
|
|
21
17
|
"tokenHelper": {
|
|
22
18
|
"missing": "The JSON Web token could not be found in the authorization header",
|
|
23
19
|
"payloadMissingSubject": "The JSON Web token payload does not contain a subject",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/api-auth-entity-storage-service",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.12",
|
|
4
4
|
"description": "Auth Entity Storage contract implementation and REST endpoint definitions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twin.org/api-auth-entity-storage-models": "0.0.2-next.
|
|
18
|
-
"@twin.org/api-core": "0.0.2-next.
|
|
19
|
-
"@twin.org/api-models": "0.0.2-next.
|
|
17
|
+
"@twin.org/api-auth-entity-storage-models": "0.0.2-next.12",
|
|
18
|
+
"@twin.org/api-core": "0.0.2-next.12",
|
|
19
|
+
"@twin.org/api-models": "0.0.2-next.12",
|
|
20
20
|
"@twin.org/core": "next",
|
|
21
21
|
"@twin.org/crypto": "next",
|
|
22
22
|
"@twin.org/entity": "next",
|
|
@@ -42,5 +42,24 @@
|
|
|
42
42
|
"dist/types",
|
|
43
43
|
"locales",
|
|
44
44
|
"docs"
|
|
45
|
-
]
|
|
45
|
+
],
|
|
46
|
+
"keywords": [
|
|
47
|
+
"twin",
|
|
48
|
+
"trade",
|
|
49
|
+
"iota",
|
|
50
|
+
"framework",
|
|
51
|
+
"blockchain",
|
|
52
|
+
"api",
|
|
53
|
+
"entity",
|
|
54
|
+
"storage",
|
|
55
|
+
"persistence",
|
|
56
|
+
"database",
|
|
57
|
+
"service",
|
|
58
|
+
"microservice",
|
|
59
|
+
"business-logic"
|
|
60
|
+
],
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "git+https://github.com/twinfoundation/api/issues"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://twindev.org"
|
|
46
65
|
}
|