@drax/identity-back 0.37.4 → 0.38.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.
- package/dist/index.js +11 -3
- package/dist/middleware/apiKeyMiddleware.js +5 -1
- package/dist/models/UserLoginFailModel.js +8 -8
- package/dist/models/UserSessionModel.js +8 -8
- package/dist/rbac/Rbac.js +21 -1
- package/dist/schemas/TokenPayloadSchema.js +14 -0
- package/dist/services/UserService.js +34 -14
- package/dist/utils/AuthUtils.js +14 -28
- package/package.json +7 -7
- package/src/index.ts +22 -2
- package/src/middleware/apiKeyMiddleware.ts +6 -2
- package/src/middleware/jwtMiddleware.ts +2 -2
- package/src/middleware/rbacMiddleware.ts +6 -6
- package/src/models/UserLoginFailModel.ts +8 -8
- package/src/models/UserSessionModel.ts +8 -8
- package/src/rbac/Rbac.ts +28 -4
- package/src/schemas/TokenPayloadSchema.ts +23 -0
- package/src/services/UserService.ts +42 -15
- package/src/utils/AuthUtils.ts +17 -31
- package/tsconfig.tsbuildinfo +1 -1
- package/types/index.d.ts +9 -3
- package/types/index.d.ts.map +1 -1
- package/types/middleware/apiKeyMiddleware.d.ts.map +1 -1
- package/types/models/UserLoginFailModel.d.ts +2 -2
- package/types/models/UserLoginFailModel.d.ts.map +1 -1
- package/types/models/UserSessionModel.d.ts +2 -2
- package/types/models/UserSessionModel.d.ts.map +1 -1
- package/types/rbac/Rbac.d.ts +7 -3
- package/types/rbac/Rbac.d.ts.map +1 -1
- package/types/schemas/TokenPayloadSchema.d.ts +35 -0
- package/types/schemas/TokenPayloadSchema.d.ts.map +1 -0
- package/types/schemas/UserLoginFailSchema.d.ts +1 -1
- package/types/schemas/UserSessionSchema.d.ts +1 -1
- package/types/services/UserService.d.ts +5 -1
- package/types/services/UserService.d.ts.map +1 -1
- package/types/utils/AuthUtils.d.ts +3 -4
- package/types/utils/AuthUtils.d.ts.map +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {z} from 'zod';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const TokenPayloadSchema = z.object({
|
|
5
|
+
id: z.string(),
|
|
6
|
+
username: z.string(),
|
|
7
|
+
|
|
8
|
+
session: z.string(),
|
|
9
|
+
|
|
10
|
+
roleId: z.string(),
|
|
11
|
+
roleName: z.string().optional().nullable(),
|
|
12
|
+
|
|
13
|
+
tenantId: z.string().optional().nullable(),
|
|
14
|
+
tenantName: z.string().optional().nullable(),
|
|
15
|
+
|
|
16
|
+
apiKeyId: z.string().optional().nullable(),
|
|
17
|
+
apiKeyName: z.string().optional().nullable(),
|
|
18
|
+
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export default TokenPayloadSchema;
|
|
23
|
+
export {TokenPayloadSchema}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {IUser, IUserCreate, IUserUpdate} from "@drax/identity-share";
|
|
1
|
+
import type {IAuthUser, IUser, IUserCreate, IUserUpdate} from "@drax/identity-share";
|
|
2
2
|
import type {IUserRepository} from "../interfaces/IUserRepository";
|
|
3
3
|
|
|
4
4
|
import {ZodError} from "zod";
|
|
@@ -24,19 +24,22 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate> {
|
|
|
24
24
|
|
|
25
25
|
async auth(username: string, password: string, {userAgent, ip}) {
|
|
26
26
|
let user = null
|
|
27
|
-
console.log("auth username", username)
|
|
28
27
|
user = await this.findByUsernameWithPassword(username)
|
|
29
28
|
if (user && user.active && AuthUtils.checkPassword(password, user.password)) {
|
|
30
|
-
|
|
31
|
-
const sessionUUID =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
|
|
30
|
+
const sessionUUID = await this.generateSession(user, userAgent, ip);
|
|
31
|
+
|
|
32
|
+
const tokenPayload: IAuthUser = {
|
|
33
|
+
id: user._id.toString(),
|
|
34
|
+
username: user.username,
|
|
35
|
+
roleId: user.role?._id?.toString(),
|
|
36
|
+
roleName: user.role?.name,
|
|
37
|
+
tenantId: user.tenant ? user.tenant?._id?.toString() : null,
|
|
38
|
+
tenantName: user.tenant ? user.tenant?.name : null,
|
|
39
|
+
session: sessionUUID
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const accessToken = AuthUtils.generateToken(tokenPayload)
|
|
40
43
|
return {accessToken: accessToken}
|
|
41
44
|
} else {
|
|
42
45
|
const userLoginFailService = UserLoginFailServiceFactory()
|
|
@@ -49,12 +52,24 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate> {
|
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
private async generateSession(user, userAgent, ip) {
|
|
56
|
+
const sessionUUID = randomUUID()
|
|
57
|
+
const sessionService = UserSessionServiceFactory()
|
|
58
|
+
await sessionService.create({
|
|
59
|
+
user: user._id.toString(),
|
|
60
|
+
uuid: sessionUUID,
|
|
61
|
+
userAgent: userAgent,
|
|
62
|
+
ip: ip
|
|
63
|
+
})
|
|
64
|
+
return sessionUUID;
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
async switchTenant(accessToken: string, tenantId: string) {
|
|
53
68
|
const newAccessToken = AuthUtils.switchTenant(accessToken, tenantId)
|
|
54
69
|
return {accessToken: newAccessToken}
|
|
55
70
|
}
|
|
56
71
|
|
|
57
|
-
async authByEmail(email: string, createIfNotFound: boolean = false, userData: IUserCreate) {
|
|
72
|
+
async authByEmail(email: string, createIfNotFound: boolean = false, userData: IUserCreate, {userAgent, ip}) {
|
|
58
73
|
let user = null
|
|
59
74
|
console.log("auth email", email)
|
|
60
75
|
user = await this.findByEmail(email)
|
|
@@ -66,8 +81,20 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate> {
|
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
if (user && user.active) {
|
|
69
|
-
const
|
|
70
|
-
|
|
84
|
+
const sessionUUID = await this.generateSession(user, userAgent, ip);
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
const tokenPayload: IAuthUser = {
|
|
88
|
+
id: user._id.toString(),
|
|
89
|
+
username: user.username,
|
|
90
|
+
roleId: user.role?._id?.toString(),
|
|
91
|
+
roleName: user.role?.name,
|
|
92
|
+
tenantId: user.tenant ? user.tenant?._id?.toString() : null,
|
|
93
|
+
tenantName: user.tenant ? user.tenant?.name : null,
|
|
94
|
+
session: sessionUUID
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const accessToken = AuthUtils.generateToken(tokenPayload)
|
|
71
98
|
return {accessToken: accessToken}
|
|
72
99
|
} else {
|
|
73
100
|
throw new BadCredentialsError()
|
package/src/utils/AuthUtils.ts
CHANGED
|
@@ -3,11 +3,12 @@ import jsonwebtoken, {SignOptions, VerifyOptions} from "jsonwebtoken";
|
|
|
3
3
|
import {DraxConfig} from "@drax/common-back";
|
|
4
4
|
import IdentityConfig from "../config/IdentityConfig.js";
|
|
5
5
|
import crypto from "crypto";
|
|
6
|
-
import type {
|
|
6
|
+
import type {IAuthUser} from "@drax/identity-share";
|
|
7
|
+
import {TokenPayloadSchema} from "../schemas/TokenPayloadSchema.js";
|
|
7
8
|
|
|
8
9
|
class AuthUtils{
|
|
9
10
|
|
|
10
|
-
static verifyToken(token : string) {
|
|
11
|
+
static verifyToken(token : string): IAuthUser {
|
|
11
12
|
const JWT_SECRET = DraxConfig.getOrLoad(IdentityConfig.JwtSecret)
|
|
12
13
|
if(!JWT_SECRET){
|
|
13
14
|
throw new Error("DraxConfig.JWT_SECRET must be provided")
|
|
@@ -15,7 +16,9 @@ class AuthUtils{
|
|
|
15
16
|
const options : VerifyOptions = {
|
|
16
17
|
algorithms: ['HS256'],
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
const tokenPayload = jsonwebtoken.verify(token, JWT_SECRET, options)
|
|
20
|
+
TokenPayloadSchema.parse(tokenPayload)
|
|
21
|
+
return tokenPayload as IAuthUser;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
static hashPassword(password : string) :string {
|
|
@@ -32,18 +35,10 @@ class AuthUtils{
|
|
|
32
35
|
return bcryptjs.compareSync(password, hashPassword);
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
static tokenSignPayload(userId : string, username: string, roleId: string, tenantId: string, session : string): IJwtUser {
|
|
36
|
-
return {
|
|
37
|
-
id: userId,
|
|
38
|
-
username: username,
|
|
39
|
-
roleId: roleId,
|
|
40
|
-
tenantId: tenantId,
|
|
41
|
-
session: session
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
38
|
|
|
45
|
-
static generateToken(
|
|
46
|
-
|
|
39
|
+
static generateToken(payload: IAuthUser) {
|
|
40
|
+
|
|
41
|
+
TokenPayloadSchema.parse(payload)
|
|
47
42
|
|
|
48
43
|
const JWT_SECRET = DraxConfig.getOrLoad(IdentityConfig.JwtSecret)
|
|
49
44
|
if(!JWT_SECRET){
|
|
@@ -55,9 +50,9 @@ class AuthUtils{
|
|
|
55
50
|
|
|
56
51
|
const options : SignOptions = {
|
|
57
52
|
expiresIn: JWT_EXPIRATION,
|
|
58
|
-
jwtid:
|
|
53
|
+
jwtid: payload.id,
|
|
59
54
|
algorithm: 'HS256',
|
|
60
|
-
audience: username,
|
|
55
|
+
audience: payload.username,
|
|
61
56
|
issuer: JWT_ISSUER
|
|
62
57
|
}
|
|
63
58
|
|
|
@@ -81,21 +76,13 @@ class AuthUtils{
|
|
|
81
76
|
|
|
82
77
|
static switchTenant(accessToken: string, newTenantId: string): string {
|
|
83
78
|
// Verificar que el token actual sea válido
|
|
84
|
-
const
|
|
79
|
+
const tokenPayload = AuthUtils.verifyToken(accessToken) as IAuthUser & { exp?: number };
|
|
85
80
|
|
|
86
|
-
if (!
|
|
81
|
+
if (!tokenPayload) {
|
|
87
82
|
throw new Error("Invalid access token");
|
|
88
83
|
}
|
|
89
84
|
|
|
90
|
-
|
|
91
|
-
const newPayload: IJwtUser = {
|
|
92
|
-
id: decodedToken.id,
|
|
93
|
-
username: decodedToken.username,
|
|
94
|
-
roleId: decodedToken.roleId,
|
|
95
|
-
tenantId: newTenantId,
|
|
96
|
-
session: decodedToken.session,
|
|
97
|
-
exp: decodedToken.exp
|
|
98
|
-
};
|
|
85
|
+
tokenPayload.tenantId = newTenantId;
|
|
99
86
|
|
|
100
87
|
const JWT_SECRET = DraxConfig.getOrLoad(IdentityConfig.JwtSecret);
|
|
101
88
|
if (!JWT_SECRET) {
|
|
@@ -105,14 +92,13 @@ class AuthUtils{
|
|
|
105
92
|
const JWT_ISSUER = DraxConfig.getOrLoad(IdentityConfig.JwtIssuer) || 'DRAX';
|
|
106
93
|
|
|
107
94
|
const options: SignOptions = {
|
|
108
|
-
jwtid:
|
|
95
|
+
jwtid: tokenPayload.id,
|
|
109
96
|
algorithm: 'HS256',
|
|
110
|
-
audience:
|
|
97
|
+
audience: tokenPayload.username,
|
|
111
98
|
issuer: JWT_ISSUER
|
|
112
99
|
};
|
|
113
100
|
|
|
114
|
-
|
|
115
|
-
return jsonwebtoken.sign(newPayload, JWT_SECRET, options);
|
|
101
|
+
return jsonwebtoken.sign(tokenPayload, JWT_SECRET, options);
|
|
116
102
|
}
|
|
117
103
|
}
|
|
118
104
|
|