@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.
Files changed (37) hide show
  1. package/dist/index.js +11 -3
  2. package/dist/middleware/apiKeyMiddleware.js +5 -1
  3. package/dist/models/UserLoginFailModel.js +8 -8
  4. package/dist/models/UserSessionModel.js +8 -8
  5. package/dist/rbac/Rbac.js +21 -1
  6. package/dist/schemas/TokenPayloadSchema.js +14 -0
  7. package/dist/services/UserService.js +34 -14
  8. package/dist/utils/AuthUtils.js +14 -28
  9. package/package.json +7 -7
  10. package/src/index.ts +22 -2
  11. package/src/middleware/apiKeyMiddleware.ts +6 -2
  12. package/src/middleware/jwtMiddleware.ts +2 -2
  13. package/src/middleware/rbacMiddleware.ts +6 -6
  14. package/src/models/UserLoginFailModel.ts +8 -8
  15. package/src/models/UserSessionModel.ts +8 -8
  16. package/src/rbac/Rbac.ts +28 -4
  17. package/src/schemas/TokenPayloadSchema.ts +23 -0
  18. package/src/services/UserService.ts +42 -15
  19. package/src/utils/AuthUtils.ts +17 -31
  20. package/tsconfig.tsbuildinfo +1 -1
  21. package/types/index.d.ts +9 -3
  22. package/types/index.d.ts.map +1 -1
  23. package/types/middleware/apiKeyMiddleware.d.ts.map +1 -1
  24. package/types/models/UserLoginFailModel.d.ts +2 -2
  25. package/types/models/UserLoginFailModel.d.ts.map +1 -1
  26. package/types/models/UserSessionModel.d.ts +2 -2
  27. package/types/models/UserSessionModel.d.ts.map +1 -1
  28. package/types/rbac/Rbac.d.ts +7 -3
  29. package/types/rbac/Rbac.d.ts.map +1 -1
  30. package/types/schemas/TokenPayloadSchema.d.ts +35 -0
  31. package/types/schemas/TokenPayloadSchema.d.ts.map +1 -0
  32. package/types/schemas/UserLoginFailSchema.d.ts +1 -1
  33. package/types/schemas/UserSessionSchema.d.ts +1 -1
  34. package/types/services/UserService.d.ts +5 -1
  35. package/types/services/UserService.d.ts.map +1 -1
  36. package/types/utils/AuthUtils.d.ts +3 -4
  37. 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
- //TODO: Generar session
31
- const sessionUUID = randomUUID()
32
- const sessionService = UserSessionServiceFactory()
33
- await sessionService.create({
34
- user:user._id.toString(),
35
- uuid: sessionUUID,
36
- userAgent: userAgent,
37
- ip: ip
38
- })
39
- const accessToken = AuthUtils.generateToken(user._id.toString(), user.username, user.role._id, user.tenant?._id, sessionUUID)
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 session = randomUUID()
70
- const accessToken = AuthUtils.generateToken(user._id.toString(), user.username, user.role._id, user.tenant?._id, session)
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()
@@ -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 {IJwtUser} from "@drax/identity-share";
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
- return jsonwebtoken.verify(token, JWT_SECRET, options)
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(userId : string, username: string, roleId: string, tenantId: string, session : string) {
46
- const payload = AuthUtils.tokenSignPayload(userId, username, roleId, tenantId, session)
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: userId,
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 decodedToken = AuthUtils.verifyToken(accessToken) as IJwtUser & { exp?: number };
79
+ const tokenPayload = AuthUtils.verifyToken(accessToken) as IAuthUser & { exp?: number };
85
80
 
86
- if (!decodedToken) {
81
+ if (!tokenPayload) {
87
82
  throw new Error("Invalid access token");
88
83
  }
89
84
 
90
- // Crear el nuevo payload manteniendo todos los datos excepto tenantId
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: decodedToken.id,
95
+ jwtid: tokenPayload.id,
109
96
  algorithm: 'HS256',
110
- audience: decodedToken.username,
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