hi-secure 1.0.14 → 1.0.16

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 (99) hide show
  1. package/dist/adapters/ArgonAdapter.d.ts +1 -1
  2. package/dist/adapters/ArgonAdapter.d.ts.map +1 -1
  3. package/dist/adapters/ArgonAdapter.js +43 -5
  4. package/dist/adapters/ArgonAdapter.js.map +1 -1
  5. package/dist/adapters/BcryptAdapter.d.ts.map +1 -1
  6. package/dist/adapters/BcryptAdapter.js +43 -3
  7. package/dist/adapters/BcryptAdapter.js.map +1 -1
  8. package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
  9. package/dist/adapters/ExpressRLAdapter.js +48 -6
  10. package/dist/adapters/ExpressRLAdapter.js.map +1 -1
  11. package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
  12. package/dist/adapters/ExpressValidatorAdapter.js +50 -10
  13. package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
  14. package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
  15. package/dist/adapters/GoogleAdapter.js +82 -16
  16. package/dist/adapters/GoogleAdapter.js.map +1 -1
  17. package/dist/adapters/JWTAdapter.d.ts.map +1 -1
  18. package/dist/adapters/JWTAdapter.js +104 -15
  19. package/dist/adapters/JWTAdapter.js.map +1 -1
  20. package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
  21. package/dist/adapters/RLFlexibleAdapter.js +87 -12
  22. package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
  23. package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
  24. package/dist/adapters/SanitizeHtmlAdapter.js +81 -13
  25. package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
  26. package/dist/adapters/XSSAdapter.d.ts +1 -1
  27. package/dist/adapters/XSSAdapter.d.ts.map +1 -1
  28. package/dist/adapters/XSSAdapter.js +137 -20
  29. package/dist/adapters/XSSAdapter.js.map +1 -1
  30. package/dist/adapters/ZodAdapter.d.ts +1 -1
  31. package/dist/adapters/ZodAdapter.d.ts.map +1 -1
  32. package/dist/adapters/ZodAdapter.js +13 -8
  33. package/dist/adapters/ZodAdapter.js.map +1 -1
  34. package/dist/core/HiSecure.d.ts +3 -4
  35. package/dist/core/HiSecure.d.ts.map +1 -1
  36. package/dist/core/HiSecure.js +108 -121
  37. package/dist/core/HiSecure.js.map +1 -1
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +8 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/logging/index.d.ts.map +1 -1
  43. package/dist/logging/index.js +2 -0
  44. package/dist/logging/index.js.map +1 -1
  45. package/dist/logging/morganSetup.d.ts.map +1 -1
  46. package/dist/logging/morganSetup.js +22 -1
  47. package/dist/logging/morganSetup.js.map +1 -1
  48. package/dist/logging/winstonSetup.d.ts.map +1 -1
  49. package/dist/logging/winstonSetup.js +61 -3
  50. package/dist/logging/winstonSetup.js.map +1 -1
  51. package/dist/managers/AuthManager.d.ts +2 -2
  52. package/dist/managers/AuthManager.d.ts.map +1 -1
  53. package/dist/managers/AuthManager.js +167 -31
  54. package/dist/managers/AuthManager.js.map +1 -1
  55. package/dist/managers/CorsManager.d.ts.map +1 -1
  56. package/dist/managers/CorsManager.js +46 -11
  57. package/dist/managers/CorsManager.js.map +1 -1
  58. package/dist/managers/HashManager.d.ts +1 -1
  59. package/dist/managers/HashManager.d.ts.map +1 -1
  60. package/dist/managers/HashManager.js +127 -17
  61. package/dist/managers/HashManager.js.map +1 -1
  62. package/dist/managers/JsonManager.d.ts +1 -1
  63. package/dist/managers/JsonManager.d.ts.map +1 -1
  64. package/dist/managers/JsonManager.js +99 -16
  65. package/dist/managers/JsonManager.js.map +1 -1
  66. package/dist/managers/RateLimitManager.d.ts +1 -1
  67. package/dist/managers/RateLimitManager.d.ts.map +1 -1
  68. package/dist/managers/RateLimitManager.js +46 -22
  69. package/dist/managers/RateLimitManager.js.map +1 -1
  70. package/dist/managers/SanitizerManager.d.ts.map +1 -1
  71. package/dist/managers/SanitizerManager.js +112 -15
  72. package/dist/managers/SanitizerManager.js.map +1 -1
  73. package/dist/managers/ValidatorManager.d.ts.map +1 -1
  74. package/dist/managers/ValidatorManager.js +90 -7
  75. package/dist/managers/ValidatorManager.js.map +1 -1
  76. package/package.json +19 -1
  77. package/readme.md +3 -6
  78. package/src/adapters/ArgonAdapter.ts +55 -6
  79. package/src/adapters/BcryptAdapter.ts +56 -8
  80. package/src/adapters/ExpressRLAdapter.ts +62 -9
  81. package/src/adapters/ExpressValidatorAdapter.ts +67 -11
  82. package/src/adapters/GoogleAdapter.ts +106 -21
  83. package/src/adapters/JWTAdapter.ts +129 -21
  84. package/src/adapters/RLFlexibleAdapter.ts +113 -16
  85. package/src/adapters/SanitizeHtmlAdapter.ts +111 -18
  86. package/src/adapters/XSSAdapter.ts +183 -39
  87. package/src/adapters/ZodAdapter.ts +56 -10
  88. package/src/core/HiSecure.ts +496 -162
  89. package/src/index.ts +4 -0
  90. package/src/logging/index.ts +6 -0
  91. package/src/logging/morganSetup.ts +36 -1
  92. package/src/logging/winstonSetup.ts +97 -8
  93. package/src/managers/AuthManager.ts +205 -34
  94. package/src/managers/CorsManager.ts +63 -16
  95. package/src/managers/HashManager.ts +156 -19
  96. package/src/managers/JsonManager.ts +119 -15
  97. package/src/managers/RateLimitManager.ts +174 -29
  98. package/src/managers/SanitizerManager.ts +150 -25
  99. package/src/managers/ValidatorManager.ts +115 -15
@@ -1,3 +1,52 @@
1
+ // import bcrypt from "bcryptjs";
2
+ // import { AdapterError } from "../core/errors/AdapterError";
3
+ // import { logger } from "../logging";
4
+
5
+ // export class BcryptAdapter {
6
+ // constructor(private saltRounds: number = 10) {}
7
+
8
+ // async hash(value: string): Promise<string> {
9
+ // try {
10
+ // if (typeof value !== "string") {
11
+ // throw new AdapterError("Value to hash must be a string.");
12
+ // }
13
+
14
+ // return await bcrypt.hash(value, this.saltRounds);
15
+ // } catch (err: any) {
16
+ // logger.error("Bcrypt hashing failed", {
17
+ // error: err?.message || err,
18
+ // saltRounds: this.saltRounds
19
+ // });
20
+
21
+ // throw new AdapterError("Bcrypt hashing failed.");
22
+ // }
23
+ // }
24
+
25
+ // async verify(value: string, hashed: string): Promise<boolean> {
26
+ // try {
27
+ // if (typeof value !== "string") {
28
+ // throw new AdapterError("Value to verify must be a string.");
29
+ // }
30
+
31
+ // if (!hashed || typeof hashed !== "string") {
32
+ // throw new AdapterError("Invalid hashed string provided.");
33
+ // }
34
+
35
+ // return await bcrypt.compare(value, hashed);
36
+ // } catch (err: any) {
37
+ // logger.error("Bcrypt verify failed", {
38
+ // error: err?.message || err
39
+ // });
40
+
41
+ // throw new AdapterError("Bcrypt verify failed.");
42
+ // }
43
+ // }
44
+ // }
45
+
46
+
47
+
48
+
49
+
1
50
  import bcrypt from "bcryptjs";
2
51
  import { AdapterError } from "../core/errors/AdapterError";
3
52
  import { logger } from "../logging";
@@ -14,8 +63,10 @@ export class BcryptAdapter {
14
63
  return await bcrypt.hash(value, this.saltRounds);
15
64
  } catch (err: any) {
16
65
  logger.error("Bcrypt hashing failed", {
17
- error: err?.message || err,
18
- saltRounds: this.saltRounds
66
+ adapter: "bcrypt",
67
+ operation: "hash",
68
+ saltRounds: this.saltRounds,
69
+ reason: err?.message
19
70
  });
20
71
 
21
72
  throw new AdapterError("Bcrypt hashing failed.");
@@ -35,15 +86,12 @@ export class BcryptAdapter {
35
86
  return await bcrypt.compare(value, hashed);
36
87
  } catch (err: any) {
37
88
  logger.error("Bcrypt verify failed", {
38
- error: err?.message || err
89
+ adapter: "bcrypt",
90
+ operation: "verify",
91
+ reason: err?.message
39
92
  });
40
93
 
41
94
  throw new AdapterError("Bcrypt verify failed.");
42
95
  }
43
96
  }
44
97
  }
45
-
46
-
47
-
48
-
49
-
@@ -1,6 +1,54 @@
1
+ // import rateLimit from "express-rate-limit";
2
+ // import { logger } from "../logging/index.js";
3
+ // import { AdapterError } from "../core/errors/AdapterError.js";
4
+
5
+ // export interface RateLimitOptions {
6
+ // windowMs?: number;
7
+ // max?: number;
8
+ // message?: any;
9
+ // skipFailedRequests?: boolean;
10
+ // standardHeaders?: boolean;
11
+ // legacyHeaders?: boolean;
12
+ // [key: string]: any;
13
+ // }
14
+
15
+ // export class ExpressRLAdapter {
16
+ // getMiddleware(options: RateLimitOptions = {}) {
17
+ // try {
18
+ // const defaultOptions = {
19
+ // windowMs: 15 * 60 * 1000,
20
+ // max: 100,
21
+ // message: { error: "Too many requests" },
22
+ // standardHeaders: true,
23
+ // legacyHeaders: false,
24
+ // skipFailedRequests: false
25
+ // };
26
+
27
+ // const finalOptions = { ...defaultOptions, ...options };
28
+
29
+ // const limiter = rateLimit(finalOptions);
30
+
31
+ // logger.debug("Express rate limiter configured", {
32
+ // windowMs: finalOptions.windowMs,
33
+ // max: finalOptions.max
34
+ // });
35
+
36
+ // return limiter;
37
+
38
+ // } catch (err: any) {
39
+ // logger.error("ExpressRLAdapter: failed to create limiter", {
40
+ // error: err?.message || err
41
+ // });
42
+ // throw new AdapterError("Express rate limiter creation failed.");
43
+ // }
44
+ // }
45
+ // }
46
+
47
+
48
+
1
49
  import rateLimit from "express-rate-limit";
2
- import { logger } from "../logging/index.js";
3
- import { AdapterError } from "../core/errors/AdapterError.js";
50
+ import { logger } from "../logging";
51
+ import { AdapterError } from "../core/errors/AdapterError";
4
52
 
5
53
  export interface RateLimitOptions {
6
54
  windowMs?: number;
@@ -16,7 +64,7 @@ export class ExpressRLAdapter {
16
64
  getMiddleware(options: RateLimitOptions = {}) {
17
65
  try {
18
66
  const defaultOptions = {
19
- windowMs: 15 * 60 * 1000,
67
+ windowMs: 15 * 60 * 1000,
20
68
  max: 100,
21
69
  message: { error: "Too many requests" },
22
70
  standardHeaders: true,
@@ -25,21 +73,26 @@ export class ExpressRLAdapter {
25
73
  };
26
74
 
27
75
  const finalOptions = { ...defaultOptions, ...options };
28
-
76
+
29
77
  const limiter = rateLimit(finalOptions);
78
+
30
79
 
31
- logger.debug("Express rate limiter configured", {
80
+ logger.info("Express rate limiter configured", {
81
+ adapter: "express-rate-limit",
82
+ operation: "configure",
32
83
  windowMs: finalOptions.windowMs,
33
84
  max: finalOptions.max
34
85
  });
35
86
 
36
87
  return limiter;
37
-
38
88
  } catch (err: any) {
39
- logger.error("ExpressRLAdapter: failed to create limiter", {
40
- error: err?.message || err
89
+ logger.error("Express rate limiter setup failed", {
90
+ adapter: "express-rate-limit",
91
+ operation: "configure",
92
+ reason: err?.message
41
93
  });
94
+
42
95
  throw new AdapterError("Express rate limiter creation failed.");
43
96
  }
44
97
  }
45
- }
98
+ }
@@ -1,6 +1,56 @@
1
+ // import { validationResult } from "express-validator";
2
+ // import { ValidationError } from "../core/errors/ValidationError.js";
3
+ // import { logger } from "../logging/index.js";
4
+
5
+ // export class ExpressValidatorAdapter {
6
+ // private globalSchema?: any[];
7
+
8
+ // constructor(globalSchema?: any[]) {
9
+ // this.globalSchema = globalSchema;
10
+ // }
11
+
12
+ // validate(dynamicSchema?: any[]) {
13
+ // const schema = dynamicSchema || this.globalSchema;
14
+
15
+ // if (!schema || !Array.isArray(schema)) {
16
+ // return (req: any, res: any, next: any) => next();
17
+ // }
18
+
19
+ // return [
20
+ // ...schema,
21
+
22
+ // (req: any, res: any, next: any) => {
23
+ // const errors = validationResult(req);
24
+
25
+ // if (!errors.isEmpty()) {
26
+ // const formatted = errors.array().map(err => ({
27
+ // message: err.msg,
28
+ // // param: err.param ,
29
+ // // location: err.location
30
+ // }));
31
+
32
+ // logger.warn("express-validator failed", {
33
+ // path: req.path,
34
+ // method: req.method,
35
+ // errors: formatted,
36
+ // preview: JSON.stringify(req.body).slice(0, 200)
37
+ // });
38
+
39
+ // return next(new ValidationError("Validation failed.", formatted as any));
40
+ // }
41
+
42
+ // next();
43
+ // }
44
+ // ];
45
+ // }
46
+ // }
47
+
48
+
49
+
50
+
1
51
  import { validationResult } from "express-validator";
2
- import { ValidationError } from "../core/errors/ValidationError.js";
3
- import { logger } from "../logging/index.js";
52
+ import { ValidationError } from "../core/errors/ValidationError";
53
+ import { logger } from "../logging";
4
54
 
5
55
  export class ExpressValidatorAdapter {
6
56
  private globalSchema?: any[];
@@ -23,24 +73,30 @@ export class ExpressValidatorAdapter {
23
73
  const errors = validationResult(req);
24
74
 
25
75
  if (!errors.isEmpty()) {
26
- const formatted = errors.array().map(err => ({
76
+ const formattedErrors = errors.array().map(err => ({
27
77
  message: err.msg,
28
- // param: err.param ,
29
- // location: err.location
78
+ field: err.type
30
79
  }));
31
80
 
32
- logger.warn("express-validator failed", {
33
- path: req.path,
81
+ logger.warn("Request validation failed", {
82
+ adapter: "express-validator",
83
+ operation: "validate",
34
84
  method: req.method,
35
- errors: formatted,
36
- preview: JSON.stringify(req.body).slice(0, 200)
85
+ path: req.path,
86
+ errorCount: formattedErrors.length,
87
+ errors: formattedErrors,
88
+ bodyPreview: req.body
89
+ ? JSON.stringify(req.body).slice(0, 150)
90
+ : undefined
37
91
  });
38
92
 
39
- return next(new ValidationError("Validation failed.", formatted as any));
93
+ return next(
94
+ new ValidationError("Validation failed.", formattedErrors as any)
95
+ );
40
96
  }
41
97
 
42
98
  next();
43
99
  }
44
100
  ];
45
101
  }
46
- }
102
+ }
@@ -1,7 +1,88 @@
1
- import { OAuth2Client, LoginTicket } from "google-auth-library";
2
- import { AdapterError } from "../core/errors/AdapterError.js";
1
+ // import { OAuth2Client, LoginTicket } from "google-auth-library";
2
+ // import { AdapterError } from "../core/errors/AdapterError.js";
3
+
4
+ // import {logger} from '../logging';
5
+
6
+ // export interface GoogleTokenPayload {
7
+ // sub: string;
8
+ // email: string;
9
+ // email_verified: boolean;
10
+ // name?: string;
11
+ // picture?: string;
12
+ // [key: string]: any;
13
+ // }
14
+
15
+ // export class GoogleAdapter {
16
+ // private client: OAuth2Client;
17
+ // private clientId?: string;
18
+
19
+ // constructor(clientId?: string) {
20
+ // if (clientId && clientId.trim().length === 0) {
21
+ // throw new AdapterError("Google clientId cannot be empty string");
22
+ // }
23
+
24
+ // this.client = new OAuth2Client(clientId);
25
+ // this.clientId = clientId;
26
+ // }
27
+
28
+ // async verifyIdToken(idToken: string): Promise<GoogleTokenPayload> {
29
+ // try {
30
+ // if (!idToken || typeof idToken !== 'string') {
31
+ // throw new AdapterError("Invalid ID token provided");
32
+ // }
33
+
34
+ // const options: { idToken: string; audience?: string | string[] } = {
35
+ // idToken
36
+ // };
37
+
38
+ // // audience only if clientId is provided and not empty
39
+ // if (this.clientId && this.clientId.trim().length > 0) {
40
+ // options.audience = this.clientId;
41
+ // }
42
+
43
+ // const ticket: LoginTicket = await this.client.verifyIdToken(options);
44
+ // const payload = ticket.getPayload();
45
+
46
+ // if (!payload) {
47
+ // logger.warn("GoogleAdapter: Empty payload");
48
+ // throw new AdapterError("Invalid Google ID token payload.");
49
+ // }
50
+
51
+ // // result object
52
+ // const result: GoogleTokenPayload = {
53
+ // sub: payload.sub,
54
+ // email: payload.email || '',
55
+ // email_verified: payload.email_verified || false,
56
+ // name: payload.name,
57
+ // picture: payload.picture
58
+ // };
59
+
60
+ // // remaining properties from payload
61
+ // const { sub, email, email_verified, name, picture, ...rest } = payload;
62
+ // Object.assign(result, rest);
63
+
64
+ // return result;
65
+
66
+ // } catch (err: any) {
67
+ // logger.error("GoogleAdapter.verifyIdToken failed", {
68
+ // error: err?.message,
69
+ // hasClientId: !!this.clientId
70
+ // });
71
+
72
+ // if (err.message?.includes('audience')) {
73
+ // throw new AdapterError("Invalid Google client ID configured.");
74
+ // }
75
+
76
+ // throw new AdapterError(err?.message || "Google token verification failed");
77
+ // }
78
+ // }
79
+ // }
80
+
81
+
3
82
 
4
- import {logger} from '../logging';
83
+ import { OAuth2Client, LoginTicket } from "google-auth-library";
84
+ import { AdapterError } from "../core/errors/AdapterError";
85
+ import { logger } from "../logging";
5
86
 
6
87
  export interface GoogleTokenPayload {
7
88
  sub: string;
@@ -20,60 +101,64 @@ export class GoogleAdapter {
20
101
  if (clientId && clientId.trim().length === 0) {
21
102
  throw new AdapterError("Google clientId cannot be empty string");
22
103
  }
23
-
104
+
24
105
  this.client = new OAuth2Client(clientId);
25
106
  this.clientId = clientId;
26
107
  }
27
108
 
28
109
  async verifyIdToken(idToken: string): Promise<GoogleTokenPayload> {
29
110
  try {
30
- if (!idToken || typeof idToken !== 'string') {
111
+ if (!idToken || typeof idToken !== "string") {
31
112
  throw new AdapterError("Invalid ID token provided");
32
113
  }
33
114
 
34
- const options: { idToken: string; audience?: string | string[] } = {
35
- idToken
115
+ const options: { idToken: string; audience?: string | string[] } = {
116
+ idToken
36
117
  };
37
118
 
38
- // audience only if clientId is provided and not empty
39
119
  if (this.clientId && this.clientId.trim().length > 0) {
40
120
  options.audience = this.clientId;
41
121
  }
42
122
 
43
123
  const ticket: LoginTicket = await this.client.verifyIdToken(options);
44
124
  const payload = ticket.getPayload();
45
-
125
+
46
126
  if (!payload) {
47
- logger.warn("GoogleAdapter: Empty payload");
127
+ logger.warn("Google ID token payload empty", {
128
+ adapter: "google-auth",
129
+ operation: "verifyIdToken",
130
+ hasClientId: !!this.clientId
131
+ });
132
+
48
133
  throw new AdapterError("Invalid Google ID token payload.");
49
134
  }
50
135
 
51
- // result object
52
136
  const result: GoogleTokenPayload = {
53
137
  sub: payload.sub,
54
- email: payload.email || '',
138
+ email: payload.email || "",
55
139
  email_verified: payload.email_verified || false,
56
140
  name: payload.name,
57
141
  picture: payload.picture
58
142
  };
59
143
 
60
- // remaining properties from payload
61
144
  const { sub, email, email_verified, name, picture, ...rest } = payload;
62
145
  Object.assign(result, rest);
63
146
 
64
147
  return result;
65
148
 
66
149
  } catch (err: any) {
67
- logger.error("GoogleAdapter.verifyIdToken failed", {
68
- error: err?.message,
69
- hasClientId: !!this.clientId
150
+ logger.error("Google ID token verification failed", {
151
+ adapter: "google-auth",
152
+ operation: "verifyIdToken",
153
+ hasClientId: !!this.clientId,
154
+ reason: err?.message
70
155
  });
71
-
72
- if (err.message?.includes('audience')) {
156
+
157
+ if (err?.message?.includes("audience")) {
73
158
  throw new AdapterError("Invalid Google client ID configured.");
74
159
  }
75
-
76
- throw new AdapterError(err?.message || "Google token verification failed");
160
+
161
+ throw new AdapterError("Google token verification failed.");
77
162
  }
78
163
  }
79
- }
164
+ }
@@ -1,7 +1,102 @@
1
+ // import jwt from "jsonwebtoken";
2
+ // import { randomUUID } from "crypto";
3
+ // import { AdapterError } from "../core/errors/AdapterError.js";
4
+ // import { logError } from "../logging/index.js";
5
+ // import { logger } from "../logging";
6
+
7
+ // export interface JWTAdapterOptions {
8
+ // secret: string;
9
+ // expiresIn?: string | number;
10
+ // algorithm?: jwt.Algorithm;
11
+ // issuer?: string;
12
+ // audience?: string | string[];
13
+ // }
14
+
15
+ // export interface SignOptions {
16
+ // expiresIn?: string | number;
17
+ // jti?: string;
18
+ // subject?: string;
19
+ // issuer?: string;
20
+ // audience?: string | string[];
21
+ // }
22
+
23
+ // export class JWTAdapter {
24
+ // private secret: string;
25
+ // private expiresIn?: string | number;
26
+ // private algorithm: jwt.Algorithm;
27
+ // private issuer?: string;
28
+ // private audience?: string | string[];
29
+
30
+ // constructor(options: JWTAdapterOptions) {
31
+ // if (!options.secret) {
32
+ // throw new AdapterError("JWT secret is required");
33
+ // }
34
+
35
+ // if (options.secret.length < 32) {
36
+ // logger.warn("JWT secret shorter than 32 chars. Consider using stronger secret.");
37
+ // // logError("JWT secret is too short (minimum 32 characters recommended)");
38
+ // }
39
+
40
+ // this.secret = options.secret;
41
+ // this.expiresIn = options.expiresIn;
42
+ // this.algorithm = options.algorithm || 'HS256'; // Default algorithm
43
+ // this.issuer = options.issuer;
44
+ // this.audience = options.audience;
45
+ // }
46
+
47
+ // sign(payload: object, options?: SignOptions) {
48
+ // try {
49
+ // const jwtOptions: jwt.SignOptions = {
50
+ // algorithm: this.algorithm,
51
+ // issuer: options?.issuer || this.issuer,
52
+ // audience: options?.audience || this.audience,
53
+ // jwtid: options?.jti || randomUUID(),
54
+ // subject: options?.subject
55
+ // };
56
+
57
+ // if (options?.expiresIn !== undefined) {
58
+ // jwtOptions.expiresIn = options.expiresIn as number;
59
+ // } else if (this.expiresIn !== undefined) {
60
+ // jwtOptions.expiresIn = this.expiresIn as number;
61
+ // }
62
+
63
+ // return jwt.sign(payload, this.secret, jwtOptions);
64
+
65
+ // } catch (err: any) {
66
+ // logError("JWTAdapter.sign failed", { error: err?.message });
67
+ // throw new AdapterError(err?.message || "JWT sign failed");
68
+ // }
69
+ // }
70
+
71
+ // verify(token: string, options?: { audience?: string | string[] }) {
72
+ // try {
73
+ // const verifyOptions: jwt.VerifyOptions = {
74
+ // algorithms: [this.algorithm],
75
+ // issuer: this.issuer,
76
+ // audience: options?.audience as string || this.audience as string
77
+ // };
78
+
79
+ // return jwt.verify(token, this.secret, verifyOptions);
80
+ // } catch (err: any) {
81
+ // logError("JWTAdapter.verify failed", { error: err?.message });
82
+
83
+
84
+ // if (err.name === 'TokenExpiredError') {
85
+ // throw new AdapterError("JWT token has expired");
86
+ // }
87
+ // if (err.name === 'JsonWebTokenError') {
88
+ // throw new AdapterError("Invalid JWT token");
89
+ // }
90
+
91
+ // throw new AdapterError(err?.message || "JWT verification failed");
92
+ // }
93
+ // }
94
+ // }
95
+
96
+
1
97
  import jwt from "jsonwebtoken";
2
- import { randomUUID } from "crypto";
3
- import { AdapterError } from "../core/errors/AdapterError.js";
4
- import { logError } from "../logging/index.js";
98
+ import { randomUUID } from "crypto";
99
+ import { AdapterError } from "../core/errors/AdapterError";
5
100
  import { logger } from "../logging";
6
101
 
7
102
  export interface JWTAdapterOptions {
@@ -14,7 +109,7 @@ export interface JWTAdapterOptions {
14
109
 
15
110
  export interface SignOptions {
16
111
  expiresIn?: string | number;
17
- jti?: string;
112
+ jti?: string;
18
113
  subject?: string;
19
114
  issuer?: string;
20
115
  audience?: string | string[];
@@ -33,13 +128,16 @@ export class JWTAdapter {
33
128
  }
34
129
 
35
130
  if (options.secret.length < 32) {
36
- logger.warn("JWT secret shorter than 32 chars. Consider using stronger secret.");
37
- // logError("JWT secret is too short (minimum 32 characters recommended)");
131
+ logger.warn("Weak JWT secret detected", {
132
+ adapter: "jwt",
133
+ operation: "init",
134
+ secretLength: options.secret.length
135
+ });
38
136
  }
39
137
 
40
138
  this.secret = options.secret;
41
139
  this.expiresIn = options.expiresIn;
42
- this.algorithm = options.algorithm || 'HS256'; // Default algorithm
140
+ this.algorithm = options.algorithm || "HS256";
43
141
  this.issuer = options.issuer;
44
142
  this.audience = options.audience;
45
143
  }
@@ -50,21 +148,26 @@ export class JWTAdapter {
50
148
  algorithm: this.algorithm,
51
149
  issuer: options?.issuer || this.issuer,
52
150
  audience: options?.audience || this.audience,
53
- jwtid: options?.jti || randomUUID(),
151
+ jwtid: options?.jti || randomUUID(),
54
152
  subject: options?.subject
55
153
  };
56
154
 
57
155
  if (options?.expiresIn !== undefined) {
58
- jwtOptions.expiresIn = options.expiresIn as number;
156
+ jwtOptions.expiresIn = options.expiresIn as any;
59
157
  } else if (this.expiresIn !== undefined) {
60
- jwtOptions.expiresIn = this.expiresIn as number;
158
+ jwtOptions.expiresIn = this.expiresIn as any;
61
159
  }
62
160
 
63
161
  return jwt.sign(payload, this.secret, jwtOptions);
64
162
 
65
163
  } catch (err: any) {
66
- logError("JWTAdapter.sign failed", { error: err?.message });
67
- throw new AdapterError(err?.message || "JWT sign failed");
164
+ logger.error("JWT signing failed", {
165
+ adapter: "jwt",
166
+ operation: "sign",
167
+ reason: err?.message
168
+ });
169
+
170
+ throw new AdapterError("JWT sign failed");
68
171
  }
69
172
  }
70
173
 
@@ -73,22 +176,27 @@ export class JWTAdapter {
73
176
  const verifyOptions: jwt.VerifyOptions = {
74
177
  algorithms: [this.algorithm],
75
178
  issuer: this.issuer,
76
- audience: options?.audience as string || this.audience as string
179
+ audience: (options?.audience || this.audience) as string
77
180
  };
78
181
 
79
182
  return jwt.verify(token, this.secret, verifyOptions);
183
+
80
184
  } catch (err: any) {
81
- logError("JWTAdapter.verify failed", { error: err?.message });
82
-
83
-
84
- if (err.name === 'TokenExpiredError') {
185
+ logger.error("JWT verification failed", {
186
+ adapter: "jwt",
187
+ operation: "verify",
188
+ reason: err?.message
189
+ });
190
+
191
+ if (err?.name === "TokenExpiredError") {
85
192
  throw new AdapterError("JWT token has expired");
86
193
  }
87
- if (err.name === 'JsonWebTokenError') {
194
+
195
+ if (err?.name === "JsonWebTokenError") {
88
196
  throw new AdapterError("Invalid JWT token");
89
197
  }
90
-
91
- throw new AdapterError(err?.message || "JWT verification failed");
198
+
199
+ throw new AdapterError("JWT verification failed");
92
200
  }
93
201
  }
94
- }
202
+ }