@drax/identity-back 0.37.5 → 0.38.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.
@@ -21,7 +21,7 @@ async function apiKeyMiddleware(request, reply) {
21
21
  apiKey = request.headers?.authorization?.replace(/ApiKey /i, "");
22
22
  }
23
23
  //Por authorization '<uuid-key>'
24
- const uuidRegex = /^[0-9a-fA-F]{24}$/i;
24
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
25
25
  if (request.headers['authorization'] && uuidRegex.test(request.headers['authorization'])) {
26
26
  apiKey = request.headers['authorization'];
27
27
  }
@@ -32,7 +32,11 @@ async function apiKeyMiddleware(request, reply) {
32
32
  id: userApiKey.user._id.toString(),
33
33
  username: userApiKey.user.username,
34
34
  roleId: userApiKey.user.role?._id?.toString(),
35
+ roleName: userApiKey.user.role?.name,
35
36
  tenantId: userApiKey.user?.tenant?._id?.toString(),
37
+ tenantName: userApiKey.user?.tenant?.name,
38
+ apiKeyId: userApiKey?._id?.toString(),
39
+ apiKeyName: userApiKey?.name
36
40
  };
37
41
  request.authUser = authUser;
38
42
  }
package/dist/rbac/Rbac.js CHANGED
@@ -11,8 +11,13 @@ class Rbac {
11
11
  return {
12
12
  id: this.userId,
13
13
  username: this.username,
14
+ session: this.session,
14
15
  roleId: this.roleId,
15
- tenantId: this.tenantId
16
+ roleName: this.roleName,
17
+ tenantId: this.tenantId,
18
+ tenantName: this.tenantName,
19
+ apiKeyId: this.apiKeyId,
20
+ apiKeyName: this.apiKeyName
16
21
  };
17
22
  }
18
23
  get username() {
@@ -21,12 +26,27 @@ class Rbac {
21
26
  get userId() {
22
27
  return this.authUser?.id.toString();
23
28
  }
29
+ get session() {
30
+ return this.authUser?.session;
31
+ }
32
+ get apiKeyId() {
33
+ return this.authUser?.apiKeyId?.toString();
34
+ }
35
+ get apiKeyName() {
36
+ return this.authUser?.apiKeyName;
37
+ }
24
38
  get roleId() {
25
- return this.authUser?.roleId.toString();
39
+ return this.authUser?.roleId?.toString();
40
+ }
41
+ get roleName() {
42
+ return this.authUser?.roleName;
26
43
  }
27
44
  get tenantId() {
28
45
  return this.authUser?.tenantId?.toString();
29
46
  }
47
+ get tenantName() {
48
+ return this.authUser?.tenantName;
49
+ }
30
50
  assertAuthenticated() {
31
51
  if (!this.authUser) {
32
52
  throw new UnauthorizedError();
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+ const TokenPayloadSchema = z.object({
3
+ id: z.string(),
4
+ username: z.string(),
5
+ session: z.string(),
6
+ roleId: z.string(),
7
+ roleName: z.string().optional().nullable(),
8
+ tenantId: z.string().optional().nullable(),
9
+ tenantName: z.string().optional().nullable(),
10
+ apiKeyId: z.string().optional().nullable(),
11
+ apiKeyName: z.string().optional().nullable(),
12
+ });
13
+ export default TokenPayloadSchema;
14
+ export { TokenPayloadSchema };
@@ -15,19 +15,19 @@ class UserService extends AbstractService {
15
15
  }
16
16
  async auth(username, password, { userAgent, ip }) {
17
17
  let user = null;
18
- console.log("auth username", username);
19
18
  user = await this.findByUsernameWithPassword(username);
20
19
  if (user && user.active && AuthUtils.checkPassword(password, user.password)) {
21
- //TODO: Generar session
22
- const sessionUUID = randomUUID();
23
- const sessionService = UserSessionServiceFactory();
24
- await sessionService.create({
25
- user: user._id.toString(),
26
- uuid: sessionUUID,
27
- userAgent: userAgent,
28
- ip: ip
29
- });
30
- const accessToken = AuthUtils.generateToken(user._id.toString(), user.username, user.role._id, user.tenant?._id, sessionUUID);
20
+ const sessionUUID = await this.generateSession(user, userAgent, ip);
21
+ const tokenPayload = {
22
+ id: user._id.toString(),
23
+ username: user.username,
24
+ roleId: user.role?._id?.toString(),
25
+ roleName: user.role?.name,
26
+ tenantId: user.tenant ? user.tenant?._id?.toString() : null,
27
+ tenantName: user.tenant ? user.tenant?.name : null,
28
+ session: sessionUUID
29
+ };
30
+ const accessToken = AuthUtils.generateToken(tokenPayload);
31
31
  return { accessToken: accessToken };
32
32
  }
33
33
  else {
@@ -40,11 +40,22 @@ class UserService extends AbstractService {
40
40
  throw new BadCredentialsError();
41
41
  }
42
42
  }
43
+ async generateSession(user, userAgent, ip) {
44
+ const sessionUUID = randomUUID();
45
+ const sessionService = UserSessionServiceFactory();
46
+ await sessionService.create({
47
+ user: user._id.toString(),
48
+ uuid: sessionUUID,
49
+ userAgent: userAgent,
50
+ ip: ip
51
+ });
52
+ return sessionUUID;
53
+ }
43
54
  async switchTenant(accessToken, tenantId) {
44
55
  const newAccessToken = AuthUtils.switchTenant(accessToken, tenantId);
45
56
  return { accessToken: newAccessToken };
46
57
  }
47
- async authByEmail(email, createIfNotFound = false, userData) {
58
+ async authByEmail(email, createIfNotFound = false, userData, { userAgent, ip }) {
48
59
  let user = null;
49
60
  console.log("auth email", email);
50
61
  user = await this.findByEmail(email);
@@ -54,8 +65,17 @@ class UserService extends AbstractService {
54
65
  user = await this.create(userData);
55
66
  }
56
67
  if (user && user.active) {
57
- const session = randomUUID();
58
- const accessToken = AuthUtils.generateToken(user._id.toString(), user.username, user.role._id, user.tenant?._id, session);
68
+ const sessionUUID = await this.generateSession(user, userAgent, ip);
69
+ const tokenPayload = {
70
+ id: user._id.toString(),
71
+ username: user.username,
72
+ roleId: user.role?._id?.toString(),
73
+ roleName: user.role?.name,
74
+ tenantId: user.tenant ? user.tenant?._id?.toString() : null,
75
+ tenantName: user.tenant ? user.tenant?.name : null,
76
+ session: sessionUUID
77
+ };
78
+ const accessToken = AuthUtils.generateToken(tokenPayload);
59
79
  return { accessToken: accessToken };
60
80
  }
61
81
  else {
@@ -3,6 +3,7 @@ import jsonwebtoken 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 { TokenPayloadSchema } from "../schemas/TokenPayloadSchema.js";
6
7
  class AuthUtils {
7
8
  static verifyToken(token) {
8
9
  const JWT_SECRET = DraxConfig.getOrLoad(IdentityConfig.JwtSecret);
@@ -12,7 +13,9 @@ class AuthUtils {
12
13
  const options = {
13
14
  algorithms: ['HS256'],
14
15
  };
15
- return jsonwebtoken.verify(token, JWT_SECRET, options);
16
+ const tokenPayload = jsonwebtoken.verify(token, JWT_SECRET, options);
17
+ TokenPayloadSchema.parse(tokenPayload);
18
+ return tokenPayload;
16
19
  }
17
20
  static hashPassword(password) {
18
21
  if (!password) {
@@ -25,17 +28,8 @@ class AuthUtils {
25
28
  static checkPassword(password, hashPassword) {
26
29
  return bcryptjs.compareSync(password, hashPassword);
27
30
  }
28
- static tokenSignPayload(userId, username, roleId, tenantId, session) {
29
- return {
30
- id: userId,
31
- username: username,
32
- roleId: roleId,
33
- tenantId: tenantId,
34
- session: session
35
- };
36
- }
37
- static generateToken(userId, username, roleId, tenantId, session) {
38
- const payload = AuthUtils.tokenSignPayload(userId, username, roleId, tenantId, session);
31
+ static generateToken(payload) {
32
+ TokenPayloadSchema.parse(payload);
39
33
  const JWT_SECRET = DraxConfig.getOrLoad(IdentityConfig.JwtSecret);
40
34
  if (!JWT_SECRET) {
41
35
  throw new Error("JWT_SECRET ENV must be provided");
@@ -44,9 +38,9 @@ class AuthUtils {
44
38
  const JWT_ISSUER = DraxConfig.getOrLoad(IdentityConfig.JwtIssuer) || 'DRAX';
45
39
  const options = {
46
40
  expiresIn: JWT_EXPIRATION,
47
- jwtid: userId,
41
+ jwtid: payload.id,
48
42
  algorithm: 'HS256',
49
- audience: username,
43
+ audience: payload.username,
50
44
  issuer: JWT_ISSUER
51
45
  };
52
46
  let token = jsonwebtoken.sign(payload, JWT_SECRET, options);
@@ -62,31 +56,23 @@ class AuthUtils {
62
56
  }
63
57
  static switchTenant(accessToken, newTenantId) {
64
58
  // Verificar que el token actual sea válido
65
- const decodedToken = AuthUtils.verifyToken(accessToken);
66
- if (!decodedToken) {
59
+ const tokenPayload = AuthUtils.verifyToken(accessToken);
60
+ if (!tokenPayload) {
67
61
  throw new Error("Invalid access token");
68
62
  }
69
- // Crear el nuevo payload manteniendo todos los datos excepto tenantId
70
- const newPayload = {
71
- id: decodedToken.id,
72
- username: decodedToken.username,
73
- roleId: decodedToken.roleId,
74
- tenantId: newTenantId,
75
- session: decodedToken.session,
76
- exp: decodedToken.exp
77
- };
63
+ tokenPayload.tenantId = newTenantId;
78
64
  const JWT_SECRET = DraxConfig.getOrLoad(IdentityConfig.JwtSecret);
79
65
  if (!JWT_SECRET) {
80
66
  throw new Error("JWT_SECRET ENV must be provided");
81
67
  }
82
68
  const JWT_ISSUER = DraxConfig.getOrLoad(IdentityConfig.JwtIssuer) || 'DRAX';
83
69
  const options = {
84
- jwtid: decodedToken.id,
70
+ jwtid: tokenPayload.id,
85
71
  algorithm: 'HS256',
86
- audience: decodedToken.username,
72
+ audience: tokenPayload.username,
87
73
  issuer: JWT_ISSUER
88
74
  };
89
- return jsonwebtoken.sign(newPayload, JWT_SECRET, options);
75
+ return jsonwebtoken.sign(tokenPayload, JWT_SECRET, options);
90
76
  }
91
77
  }
92
78
  export default AuthUtils;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.37.5",
6
+ "version": "0.38.1",
7
7
  "description": "Identity module for user management, authentication and authorization.",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -28,11 +28,11 @@
28
28
  "author": "Cristian Incarnato & Drax Team",
29
29
  "license": "ISC",
30
30
  "dependencies": {
31
- "@drax/common-back": "^0.37.2",
32
- "@drax/crud-back": "^0.37.5",
33
- "@drax/crud-share": "^0.37.0",
34
- "@drax/email-back": "^0.37.0",
35
- "@drax/identity-share": "^0.37.0",
31
+ "@drax/common-back": "^0.38.0",
32
+ "@drax/crud-back": "^0.38.1",
33
+ "@drax/crud-share": "^0.38.0",
34
+ "@drax/email-back": "^0.38.0",
35
+ "@drax/identity-share": "^0.38.0",
36
36
  "bcryptjs": "^2.4.3",
37
37
  "graphql": "^16.8.2",
38
38
  "jsonwebtoken": "^9.0.2"
@@ -63,5 +63,5 @@
63
63
  "debug": "0"
64
64
  }
65
65
  },
66
- "gitHead": "2fd3d1fa98a875f67691ea4524682985a52cba17"
66
+ "gitHead": "33404c9f1b3df6a3f86624389916d1cae0c56904"
67
67
  }
@@ -29,19 +29,23 @@ async function apiKeyMiddleware (request, reply) {
29
29
  }
30
30
 
31
31
  //Por authorization '<uuid-key>'
32
- const uuidRegex = /^[0-9a-fA-F]{24}$/i;
32
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
33
33
  if(request.headers['authorization'] && uuidRegex.test(request.headers['authorization'])){
34
34
  apiKey = request.headers['authorization']
35
35
  }
36
36
 
37
37
  if(apiKey){
38
- const userApiKey = await draxCache.getOrLoad(apiKey, userApiKeyLoader)
38
+ const userApiKey : IUserApiKey = await draxCache.getOrLoad(apiKey, userApiKeyLoader)
39
39
  if(userApiKey && userApiKey.user){
40
40
  const authUser: IAuthUser = {
41
41
  id: userApiKey.user._id.toString(),
42
42
  username: userApiKey.user.username,
43
43
  roleId: userApiKey.user.role?._id?.toString(),
44
+ roleName: userApiKey.user.role?.name,
44
45
  tenantId: userApiKey.user?.tenant?._id?.toString(),
46
+ tenantName: userApiKey.user?.tenant?.name,
47
+ apiKeyId: userApiKey?._id?.toString(),
48
+ apiKeyName: userApiKey?.name
45
49
  }
46
50
  request.authUser = authUser
47
51
  }
@@ -1,5 +1,5 @@
1
1
  import AuthUtils from "../utils/AuthUtils.js";
2
- import {IJwtUser} from "@drax/identity-share";
2
+ import {IAuthUser} from "@drax/identity-share";
3
3
 
4
4
  function jwtMiddleware (request, reply, done) {
5
5
  try{
@@ -14,7 +14,7 @@ function jwtMiddleware (request, reply, done) {
14
14
  const routerPath = request.url
15
15
 
16
16
  if(routerPath != '/api/auth/login' && token){
17
- const authUser = AuthUtils.verifyToken(token) as IJwtUser
17
+ const authUser: IAuthUser = AuthUtils.verifyToken(token)
18
18
  if(authUser){
19
19
  request.authUser = authUser
20
20
  request.token = token
@@ -1,4 +1,4 @@
1
- import {IJwtUser, IRole} from "@drax/identity-share";
1
+ import {IAuthUser, IRbac, IRole} from "@drax/identity-share";
2
2
  import {DraxCache, DraxConfig} from "@drax/common-back";
3
3
  import RoleServiceFactory from "../factory/RoleServiceFactory.js";
4
4
  import Rbac from "../rbac/Rbac.js";
@@ -16,14 +16,14 @@ async function roleLoader(k):Promise<IRole | null> {
16
16
 
17
17
  async function rbacMiddleware (request, reply) {
18
18
  try{
19
- if(request.authUser as IJwtUser){
20
- const authUser = request.authUser
19
+ if(request.authUser as IAuthUser){
20
+ const authUser: IAuthUser = request.authUser
21
21
  const cacheKey = authUser.roleId
22
- const role = await draxCache.getOrLoad(cacheKey, roleLoader)
23
- const rbac = new Rbac(authUser,role)
22
+ const role : IRole = await draxCache.getOrLoad(cacheKey, roleLoader)
23
+ const rbac: IRbac = new Rbac(authUser,role)
24
24
  request.rbac = rbac
25
25
  }else{
26
- const rbac = new Rbac(null,null)
26
+ const rbac: IRbac = new Rbac(null,null)
27
27
  request.rbac = rbac
28
28
  }
29
29
  return
package/src/rbac/Rbac.ts CHANGED
@@ -1,12 +1,11 @@
1
- import type {IJwtUser, IRole, IRbac} from "@drax/identity-share";
1
+ import type { IAuthUser, IRole, IRbac} from "@drax/identity-share";
2
2
  import {UnauthorizedError, ForbiddenError} from "@drax/common-back";
3
- import {IAuthUser} from "@drax/identity-share/dist";
4
3
 
5
4
  class Rbac implements IRbac{
6
5
  private role: IRole;
7
6
  private authUser: IAuthUser;
8
7
 
9
- constructor(authUser: IJwtUser, role: IRole) {
8
+ constructor(authUser: IAuthUser, role: IRole) {
10
9
  this.authUser = authUser;
11
10
  this.role = role;
12
11
  }
@@ -19,8 +18,13 @@ class Rbac implements IRbac{
19
18
  return {
20
19
  id: this.userId,
21
20
  username: this.username,
21
+ session: this.session,
22
22
  roleId: this.roleId,
23
- tenantId: this.tenantId
23
+ roleName: this.roleName,
24
+ tenantId: this.tenantId,
25
+ tenantName: this.tenantName,
26
+ apiKeyId: this.apiKeyId,
27
+ apiKeyName: this.apiKeyName
24
28
  }
25
29
  }
26
30
 
@@ -32,14 +36,34 @@ class Rbac implements IRbac{
32
36
  return this.authUser?.id.toString()
33
37
  }
34
38
 
39
+ get session(): string {
40
+ return this.authUser?.session
41
+ }
42
+
43
+ get apiKeyId(): string {
44
+ return this.authUser?.apiKeyId?.toString()
45
+ }
46
+
47
+ get apiKeyName(): string {
48
+ return this.authUser?.apiKeyName
49
+ }
50
+
35
51
  get roleId(): string {
36
- return this.authUser?.roleId.toString()
52
+ return this.authUser?.roleId?.toString()
53
+ }
54
+
55
+ get roleName(): string {
56
+ return this.authUser?.roleName
37
57
  }
38
58
 
39
59
  get tenantId(): string | undefined {
40
60
  return this.authUser?.tenantId?.toString();
41
61
  }
42
62
 
63
+ get tenantName(): string | undefined {
64
+ return this.authUser?.tenantName;
65
+ }
66
+
43
67
  assertAuthenticated() {
44
68
  if (!this.authUser) {
45
69
  throw new UnauthorizedError()
@@ -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