hi-secure 1.0.7 → 1.0.11
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/adapters/ArgonAdapter.js +1 -1
- package/dist/adapters/ArgonAdapter.js.map +1 -1
- package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressRLAdapter.js +1 -2
- package/dist/adapters/ExpressRLAdapter.js.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.js +1 -39
- package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
- package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
- package/dist/adapters/GoogleAdapter.js +0 -101
- package/dist/adapters/GoogleAdapter.js.map +1 -1
- package/dist/adapters/JWTAdapter.d.ts.map +1 -1
- package/dist/adapters/JWTAdapter.js +3 -210
- package/dist/adapters/JWTAdapter.js.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.js +0 -52
- package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.d.ts +0 -3
- package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.js +2 -71
- package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
- package/dist/adapters/XSSAdapter.d.ts +0 -10
- package/dist/adapters/XSSAdapter.d.ts.map +1 -1
- package/dist/adapters/XSSAdapter.js +2 -19
- package/dist/adapters/XSSAdapter.js.map +1 -1
- package/dist/adapters/ZodAdapter.d.ts.map +1 -1
- package/dist/adapters/ZodAdapter.js +2 -6
- package/dist/adapters/ZodAdapter.js.map +1 -1
- package/dist/core/HiSecure.d.ts +0 -2
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +8 -20
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/core/useSecure.d.ts +0 -3
- package/dist/core/useSecure.d.ts.map +1 -1
- package/dist/core/useSecure.js +1 -5
- package/dist/core/useSecure.js.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/managers/AuthManager.d.ts.map +1 -1
- package/dist/managers/AuthManager.js +1 -89
- package/dist/managers/AuthManager.js.map +1 -1
- package/dist/managers/CorsManager.d.ts.map +1 -1
- package/dist/managers/CorsManager.js +1 -19
- package/dist/managers/CorsManager.js.map +1 -1
- package/dist/managers/HashManager.d.ts.map +1 -1
- package/dist/managers/HashManager.js +0 -243
- package/dist/managers/HashManager.js.map +1 -1
- package/dist/managers/JsonManager.d.ts.map +1 -1
- package/dist/managers/JsonManager.js +1 -77
- package/dist/managers/JsonManager.js.map +1 -1
- package/dist/managers/RateLimitManager.d.ts.map +1 -1
- package/dist/managers/RateLimitManager.js +3 -17
- package/dist/managers/RateLimitManager.js.map +1 -1
- package/dist/managers/SanitizerManager.d.ts +0 -6
- package/dist/managers/SanitizerManager.d.ts.map +1 -1
- package/dist/managers/SanitizerManager.js +1 -213
- package/dist/managers/SanitizerManager.js.map +1 -1
- package/dist/managers/ValidatorManager.d.ts.map +1 -1
- package/dist/managers/ValidatorManager.js +1 -109
- package/dist/managers/ValidatorManager.js.map +1 -1
- package/dist/middlewares/errorHandler.d.ts.map +1 -1
- package/dist/middlewares/errorHandler.js +0 -19
- package/dist/middlewares/errorHandler.js.map +1 -1
- package/dist/utils/deepFreeze.d.ts.map +1 -1
- package/dist/utils/deepFreeze.js +0 -25
- package/dist/utils/deepFreeze.js.map +1 -1
- package/dist/utils/deepMerge.d.ts.map +1 -1
- package/dist/utils/deepMerge.js +0 -26
- package/dist/utils/deepMerge.js.map +1 -1
- package/dist/utils/normalizeOptions.d.ts +1 -3
- package/dist/utils/normalizeOptions.d.ts.map +1 -1
- package/dist/utils/normalizeOptions.js +8 -9
- package/dist/utils/normalizeOptions.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/ArgonAdapter.ts +1 -1
- package/src/adapters/ExpressRLAdapter.ts +1 -2
- package/src/adapters/ExpressValidatorAdapter.ts +1 -54
- package/src/adapters/GoogleAdapter.ts +0 -129
- package/src/adapters/JWTAdapter.ts +5 -259
- package/src/adapters/RLFlexibleAdapter.ts +2 -65
- package/src/adapters/SanitizeHtmlAdapter.ts +3 -87
- package/src/adapters/XSSAdapter.ts +11 -19
- package/src/adapters/ZodAdapter.ts +2 -51
- package/src/core/HiSecure.ts +13 -24
- package/src/core/useSecure.ts +5 -7
- package/src/index.ts +4 -5
- package/src/managers/AuthManager.ts +5 -109
- package/src/managers/CorsManager.ts +1 -25
- package/src/managers/HashManager.ts +0 -286
- package/src/managers/JsonManager.ts +1 -91
- package/src/managers/RateLimitManager.ts +3 -262
- package/src/managers/SanitizerManager.ts +4 -263
- package/src/managers/ValidatorManager.ts +1 -135
- package/src/middlewares/errorHandler.ts +1 -176
- package/src/utils/deepFreeze.ts +0 -32
- package/src/utils/deepMerge.ts +0 -35
- package/src/utils/normalizeOptions.ts +16 -133
- package/src/examples/e1.ts +0 -1
- package/src/test/t1.ts +0 -1
package/src/core/HiSecure.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// src/core/HiSecure.ts - COMPLETELY FIXED
|
|
2
1
|
import { HiSecureConfig } from "./types/HiSecureConfig.js";
|
|
3
2
|
import { defaultConfig } from "./config.js";
|
|
4
3
|
import { LIB_NAME, LIB_VERSION } from "./constants.js";
|
|
@@ -32,7 +31,7 @@ import compression from "compression";
|
|
|
32
31
|
import { errorHandler } from "../middlewares/errorHandler.js";
|
|
33
32
|
|
|
34
33
|
// Types
|
|
35
|
-
import { SecureOptions, ValidationSchema
|
|
34
|
+
import { SecureOptions, ValidationSchema} from "./types/SecureOptions.js";
|
|
36
35
|
|
|
37
36
|
export class HiSecure {
|
|
38
37
|
private static instance: HiSecure | null = null;
|
|
@@ -53,8 +52,6 @@ export class HiSecure {
|
|
|
53
52
|
private hashingFallback: any;
|
|
54
53
|
private rateLimiterPrimary: any;
|
|
55
54
|
private rateLimiterFallback: any;
|
|
56
|
-
private validatorPrimary: any;
|
|
57
|
-
private validatorFallback: any;
|
|
58
55
|
private sanitizerPrimary: any;
|
|
59
56
|
private sanitizerFallback: any;
|
|
60
57
|
|
|
@@ -63,9 +60,7 @@ export class HiSecure {
|
|
|
63
60
|
this.config = deepMerge(defaultConfig, userConfig);
|
|
64
61
|
}
|
|
65
62
|
|
|
66
|
-
// =====================================================
|
|
67
63
|
// SINGLETON & INITIALIZATION
|
|
68
|
-
// =====================================================
|
|
69
64
|
|
|
70
65
|
static getInstance(config?: Partial<HiSecureConfig>): HiSecure {
|
|
71
66
|
if (!HiSecure.instance) {
|
|
@@ -91,7 +86,6 @@ export class HiSecure {
|
|
|
91
86
|
this.setupManagers();
|
|
92
87
|
this.setupDynamicManagers();
|
|
93
88
|
|
|
94
|
-
// Make everything immutable
|
|
95
89
|
deepFreeze(this.config);
|
|
96
90
|
// deepFreeze(this.hashManager);
|
|
97
91
|
// deepFreeze(this.rateLimitManager);
|
|
@@ -109,9 +103,7 @@ export class HiSecure {
|
|
|
109
103
|
return this.initialized;
|
|
110
104
|
}
|
|
111
105
|
|
|
112
|
-
// =====================================================
|
|
113
106
|
// FLUENT API METHODS (Route-level security)
|
|
114
|
-
// =====================================================
|
|
115
107
|
|
|
116
108
|
static auth(options?: { required?: boolean; roles?: string[] }) {
|
|
117
109
|
const instance = this.getInstance();
|
|
@@ -156,9 +148,7 @@ export class HiSecure {
|
|
|
156
148
|
return chain;
|
|
157
149
|
}
|
|
158
150
|
|
|
159
|
-
// =====================================================
|
|
160
151
|
// UTILITY METHODS (Direct usage)
|
|
161
|
-
// =====================================================
|
|
162
152
|
|
|
163
153
|
static async hash(password: string): Promise<string> {
|
|
164
154
|
const instance = this.getInstance();
|
|
@@ -198,9 +188,7 @@ export class HiSecure {
|
|
|
198
188
|
}
|
|
199
189
|
};
|
|
200
190
|
|
|
201
|
-
// =====================================================
|
|
202
191
|
// GLOBAL MIDDLEWARE (app.use())
|
|
203
|
-
// =====================================================
|
|
204
192
|
|
|
205
193
|
static middleware(options?: SecureOptions | "api" | "strict" | "public") {
|
|
206
194
|
const instance = this.getInstance();
|
|
@@ -222,9 +210,8 @@ export class HiSecure {
|
|
|
222
210
|
return instance.createMiddlewareChain(options || {});
|
|
223
211
|
}
|
|
224
212
|
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
// =====================================================
|
|
213
|
+
|
|
214
|
+
// Internal Methods
|
|
228
215
|
|
|
229
216
|
private setupAdapters(): void {
|
|
230
217
|
logger.info("🧩 Setting up adapters...");
|
|
@@ -244,13 +231,16 @@ export class HiSecure {
|
|
|
244
231
|
: new ExpressRLAdapter();
|
|
245
232
|
this.rateLimiterFallback = new ExpressRLAdapter();
|
|
246
233
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
// // Validation
|
|
237
|
+
// this.validatorPrimary = this.config.validation.mode === "zod"
|
|
238
|
+
// ? new ZodAdapter()
|
|
239
|
+
// : new ExpressValidatorAdapter();
|
|
240
|
+
// this.validatorFallback = this.config.validation.fallback === "express-validator"
|
|
241
|
+
// ? new ExpressValidatorAdapter()
|
|
242
|
+
// : null;
|
|
243
|
+
|
|
254
244
|
|
|
255
245
|
// Sanitization
|
|
256
246
|
this.sanitizerPrimary = new SanitizeHtmlAdapter(this.config.sanitizer);
|
|
@@ -301,7 +291,6 @@ export class HiSecure {
|
|
|
301
291
|
jwtSecret,
|
|
302
292
|
jwtExpiresIn: this.config.auth.jwtExpiresIn,
|
|
303
293
|
googleClientId: process.env.GOOGLE_CLIENT_ID || this.config.auth.googleClientId
|
|
304
|
-
// Removed algorithm - handled in AuthManager
|
|
305
294
|
});
|
|
306
295
|
}
|
|
307
296
|
}
|
package/src/core/useSecure.ts
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
// src/core/useSecure.ts - SIMPLER VERSION
|
|
2
|
-
// This is now optional since HiSecure class has fluent API
|
|
3
|
-
|
|
4
|
-
|
|
5
1
|
import { HiSecure } from "./HiSecure.js";
|
|
6
2
|
import { SecureOptions } from "./types/SecureOptions.js";
|
|
7
3
|
|
|
8
4
|
/**
|
|
9
5
|
* @deprecated Use HiSecure.middleware() or fluent API instead
|
|
10
6
|
*/
|
|
7
|
+
|
|
11
8
|
export function useSecure(options?: SecureOptions | "api" | "strict" | "public") {
|
|
12
9
|
console.warn("⚠ useSecure() is deprecated. Use HiSecure.middleware() or fluent API methods.");
|
|
13
10
|
return HiSecure.middleware(options);
|
|
14
11
|
}
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
|
|
14
|
+
// Legacy support - route-level security
|
|
15
|
+
|
|
16
|
+
|
|
19
17
|
export function secureRoute(options?: SecureOptions) {
|
|
20
18
|
const chain: any[] = [];
|
|
21
19
|
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
// src/index.ts - MAIN ENTRY POINT
|
|
2
1
|
import { HiSecure } from "./core/HiSecure.js";
|
|
3
2
|
import { useSecure, secureRoute } from "./core/useSecure.js";
|
|
4
3
|
|
|
5
4
|
const hiSecure = HiSecure.getInstance();
|
|
6
5
|
|
|
7
6
|
export {
|
|
8
|
-
HiSecure,
|
|
9
|
-
hiSecure,
|
|
10
|
-
useSecure,
|
|
11
|
-
secureRoute
|
|
7
|
+
HiSecure,
|
|
8
|
+
hiSecure,
|
|
9
|
+
useSecure,
|
|
10
|
+
secureRoute
|
|
12
11
|
};
|
|
13
12
|
|
|
14
13
|
export default hiSecure;
|
|
@@ -1,113 +1,8 @@
|
|
|
1
|
-
// import { JWTAdapter } from "../adapters/JWTAdapter.js";
|
|
2
|
-
// import { GoogleAdapter } from "../adapters/GoggleAdapter.js";
|
|
3
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
4
|
-
// import { HttpError } from "../core/errors/HttpErrror.js";
|
|
5
|
-
// import { Request, Response, NextFunction } from "express";
|
|
6
|
-
// import { logError, logWarn, logInfo } from "../logging";
|
|
7
|
-
|
|
8
|
-
// export interface AuthOptions {
|
|
9
|
-
// jwtSecret: string;
|
|
10
|
-
// jwtExpiresIn?: string | number | undefined;
|
|
11
|
-
// googleClientId?: string | undefined;
|
|
12
|
-
// }
|
|
13
|
-
|
|
14
|
-
// export class AuthManager {
|
|
15
|
-
// private jwtAdapter: JWTAdapter;
|
|
16
|
-
// private googleAdapter?: GoogleAdapter;
|
|
17
|
-
|
|
18
|
-
// constructor(opts: AuthOptions) {
|
|
19
|
-
// if (!opts.jwtSecret)
|
|
20
|
-
// throw new AdapterError("jwtSecret required in AuthOptions");
|
|
21
|
-
|
|
22
|
-
// logInfo("AuthManager initialized");
|
|
23
|
-
|
|
24
|
-
// this.jwtAdapter = new JWTAdapter({
|
|
25
|
-
// secret: opts.jwtSecret,
|
|
26
|
-
// expiresIn: opts.jwtExpiresIn ?? undefined,
|
|
27
|
-
// });
|
|
28
|
-
|
|
29
|
-
// if (opts.googleClientId) {
|
|
30
|
-
// this.googleAdapter = new GoogleAdapter(opts.googleClientId);
|
|
31
|
-
// logInfo("GoogleAdapter enabled");
|
|
32
|
-
// }
|
|
33
|
-
// }
|
|
34
|
-
|
|
35
|
-
// sign(payload: object, options?: { expiresIn?: string | number }) {
|
|
36
|
-
// logInfo("JWT Sign called");
|
|
37
|
-
// return this.jwtAdapter.sign(payload, options);
|
|
38
|
-
// }
|
|
39
|
-
|
|
40
|
-
// verify(token: string) {
|
|
41
|
-
// logInfo("JWT Verify called");
|
|
42
|
-
// return this.jwtAdapter.verify(token);
|
|
43
|
-
// }
|
|
44
|
-
|
|
45
|
-
// async verifyGoogleIdToken(idToken: string) {
|
|
46
|
-
// if (!this.googleAdapter)
|
|
47
|
-
// throw new AdapterError("GoogleAdapter not configured.");
|
|
48
|
-
|
|
49
|
-
// logInfo("Google ID Token verify called");
|
|
50
|
-
|
|
51
|
-
// try {
|
|
52
|
-
// return await this.googleAdapter.verifyIdToken(idToken);
|
|
53
|
-
// } catch (err: any) {
|
|
54
|
-
// logError("Google ID Token verification failed", { error: err?.message });
|
|
55
|
-
// throw HttpError.Unauthorized("Invalid Google ID token");
|
|
56
|
-
// }
|
|
57
|
-
// }
|
|
58
|
-
|
|
59
|
-
// protect(options?: { required?: boolean }) {
|
|
60
|
-
// const required = options?.required ?? true;
|
|
61
|
-
|
|
62
|
-
// return (req: Request, res: Response, next: NextFunction) => {
|
|
63
|
-
// const header = req.headers["authorization"] || req.headers["Authorization"];
|
|
64
|
-
|
|
65
|
-
// if (!header) {
|
|
66
|
-
// if (required) {
|
|
67
|
-
// logWarn("Missing Authorization header", {
|
|
68
|
-
// path: req.path,
|
|
69
|
-
// method: req.method
|
|
70
|
-
// });
|
|
71
|
-
// return next(HttpError.Unauthorized("Missing Authorization header"));
|
|
72
|
-
// }
|
|
73
|
-
// return next();
|
|
74
|
-
// }
|
|
75
|
-
|
|
76
|
-
// const [type, token] = String(header).split(" ");
|
|
77
|
-
|
|
78
|
-
// if (type !== "Bearer" || !token) {
|
|
79
|
-
// logWarn("Invalid Authorization header", {
|
|
80
|
-
// path: req.path,
|
|
81
|
-
// method: req.method
|
|
82
|
-
// });
|
|
83
|
-
// return next(HttpError.Unauthorized("Invalid Authorization header"));
|
|
84
|
-
// }
|
|
85
|
-
|
|
86
|
-
// try {
|
|
87
|
-
// const decoded = this.verify(token);
|
|
88
|
-
// (req as any).auth = decoded;
|
|
89
|
-
// return next();
|
|
90
|
-
// } catch (err: any) {
|
|
91
|
-
// logError("JWT verify failed", {
|
|
92
|
-
// error: err?.message,
|
|
93
|
-
// path: req.path,
|
|
94
|
-
// method: req.method
|
|
95
|
-
// });
|
|
96
|
-
// return next(HttpError.Unauthorized("Invalid or expired token"));
|
|
97
|
-
// }
|
|
98
|
-
// };
|
|
99
|
-
// }
|
|
100
|
-
// }
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// src/managers/AuthManager.ts - FIXED
|
|
105
1
|
import { JWTAdapter } from "../adapters/JWTAdapter.js";
|
|
106
2
|
import { GoogleAdapter } from "../adapters/GoogleAdapter.js";
|
|
107
3
|
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
108
4
|
import { HttpError } from "../core/errors/HttpError.js";
|
|
109
5
|
import { Request, Response, NextFunction } from "express";
|
|
110
|
-
// import { logError, logWarn, logInfo } from "../logging";
|
|
111
6
|
import { logger } from "../logging";
|
|
112
7
|
|
|
113
8
|
|
|
@@ -180,12 +75,12 @@ export class AuthManager {
|
|
|
180
75
|
return (req: Request, res: Response, next: NextFunction) => {
|
|
181
76
|
const header = req.headers["authorization"];
|
|
182
77
|
|
|
183
|
-
|
|
78
|
+
|
|
184
79
|
if (!required && !header) {
|
|
185
80
|
return next();
|
|
186
81
|
}
|
|
187
82
|
|
|
188
|
-
|
|
83
|
+
|
|
189
84
|
if (!header) {
|
|
190
85
|
logger.warn("Missing Authorization header", {
|
|
191
86
|
path: req.path,
|
|
@@ -194,7 +89,7 @@ export class AuthManager {
|
|
|
194
89
|
return next(HttpError.Unauthorized("Missing Authorization header"));
|
|
195
90
|
}
|
|
196
91
|
|
|
197
|
-
|
|
92
|
+
|
|
198
93
|
const [type, token] = String(header).split(" ");
|
|
199
94
|
if (type !== "Bearer" || !token) {
|
|
200
95
|
logger.warn("Invalid Authorization header", {
|
|
@@ -205,12 +100,13 @@ export class AuthManager {
|
|
|
205
100
|
}
|
|
206
101
|
|
|
207
102
|
try {
|
|
103
|
+
|
|
208
104
|
// Verify JWT
|
|
209
105
|
const decoded = this.verify(token);
|
|
210
106
|
|
|
211
107
|
// Attach to request
|
|
212
108
|
(req as any).auth = decoded;
|
|
213
|
-
(req as any).user = decoded;
|
|
109
|
+
(req as any).user = decoded;
|
|
214
110
|
|
|
215
111
|
// Role-based authorization
|
|
216
112
|
if (roles && roles.length > 0) {
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
// import cors from "cors";
|
|
2
|
-
// import { logger } from "../logging";
|
|
3
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
4
|
-
|
|
5
|
-
// export class CorsManager {
|
|
6
|
-
|
|
7
|
-
// middleware(options?: any) {
|
|
8
|
-
// try {
|
|
9
|
-
// // options = undefined → use default CORS
|
|
10
|
-
// return options ? cors(options) : cors();
|
|
11
|
-
|
|
12
|
-
// } catch (err: any) {
|
|
13
|
-
// logger.error("❌ CORS Manager: failed to create CORS middleware", {
|
|
14
|
-
// error: err?.message || err,
|
|
15
|
-
// options
|
|
16
|
-
// });
|
|
17
|
-
// throw new AdapterError("CORS middleware initialization failed.");
|
|
18
|
-
// }
|
|
19
|
-
// }
|
|
20
|
-
// }
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
// src/managers/CorsManager.ts - IMPROVED
|
|
25
1
|
import cors from "cors";
|
|
26
2
|
import { logger } from "../logging";
|
|
27
3
|
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
@@ -35,7 +11,7 @@ export class CorsManager {
|
|
|
35
11
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
36
12
|
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
37
13
|
credentials: false,
|
|
38
|
-
maxAge: 86400
|
|
14
|
+
maxAge: 86400
|
|
39
15
|
};
|
|
40
16
|
|
|
41
17
|
const finalOptions = options ? { ...defaultOptions, ...options } : defaultOptions;
|
|
@@ -1,288 +1,3 @@
|
|
|
1
|
-
// // // import { AdapterError } from "../core/errors/AdapterError";
|
|
2
|
-
// // // import { HiSecureConfig } from "../core/config";
|
|
3
|
-
// // // import { logger } from "../logging";
|
|
4
|
-
|
|
5
|
-
// // // export class HashManager {
|
|
6
|
-
// // // private config: HiSecureConfig["hashing"];
|
|
7
|
-
// // // private primaryAdapter: {
|
|
8
|
-
// // // hash: (value: string) => Promise<string>;
|
|
9
|
-
// // // verify: (value: string, hashed: string) => Promise<boolean>;
|
|
10
|
-
// // // };
|
|
11
|
-
// // // private fallbackAdapter: {
|
|
12
|
-
// // // hash: (value: string) => Promise<string>;
|
|
13
|
-
// // // verify: (value: string, hashed: string) => Promise<boolean>;
|
|
14
|
-
// // // } | null;
|
|
15
|
-
|
|
16
|
-
// // // constructor(
|
|
17
|
-
// // // config: HiSecureConfig["hashing"],
|
|
18
|
-
// // // primaryAdapter: any,
|
|
19
|
-
// // // fallbackAdapter: any
|
|
20
|
-
// // // ) {
|
|
21
|
-
// // // this.config = config;
|
|
22
|
-
// // // this.primaryAdapter = primaryAdapter;
|
|
23
|
-
// // // this.fallbackAdapter = fallbackAdapter;
|
|
24
|
-
// // // }
|
|
25
|
-
|
|
26
|
-
// // // /**
|
|
27
|
-
// // // * Hash a password using primary adapter (Argon2)
|
|
28
|
-
// // // * If it fails → fallback (Bcrypt)
|
|
29
|
-
// // // */
|
|
30
|
-
// // // async hash(value: string): Promise<string> {
|
|
31
|
-
// // // try {
|
|
32
|
-
// // // return await this.primaryAdapter.hash(value);
|
|
33
|
-
// // // } catch (err: any) {
|
|
34
|
-
// // // logger.warn("⚠ Primary hashing failed — switching to fallback", {
|
|
35
|
-
// // // error: err?.message,
|
|
36
|
-
// // // });
|
|
37
|
-
|
|
38
|
-
// // // if (!this.fallbackAdapter) {
|
|
39
|
-
// // // throw new AdapterError(
|
|
40
|
-
// // // "Primary hashing failed and no fallback adapter is configured."
|
|
41
|
-
// // // );
|
|
42
|
-
// // // }
|
|
43
|
-
|
|
44
|
-
// // // try {
|
|
45
|
-
// // // return await this.fallbackAdapter.hash(value);
|
|
46
|
-
// // // } catch (fallbackErr: any) {
|
|
47
|
-
// // // logger.error("❌ Fallback hashing failed", {
|
|
48
|
-
// // // error: fallbackErr?.message,
|
|
49
|
-
// // // });
|
|
50
|
-
// // // throw new AdapterError(
|
|
51
|
-
// // // "Both primary and fallback hashing failed."
|
|
52
|
-
// // // );
|
|
53
|
-
// // // }
|
|
54
|
-
// // // }
|
|
55
|
-
// // // }
|
|
56
|
-
|
|
57
|
-
// // // /**
|
|
58
|
-
// // // * Verify using primary hashing method.
|
|
59
|
-
// // // * If mismatch OR failure → use fallback.
|
|
60
|
-
// // // */
|
|
61
|
-
// // // async verify(value: string, hashed: string): Promise<boolean> {
|
|
62
|
-
// // // try {
|
|
63
|
-
// // // return await this.primaryAdapter.verify(value, hashed);
|
|
64
|
-
// // // } catch (err: any) {
|
|
65
|
-
// // // logger.warn("⚠ Primary verify failed — trying fallback", {
|
|
66
|
-
// // // error: err?.message,
|
|
67
|
-
// // // });
|
|
68
|
-
|
|
69
|
-
// // // if (!this.fallbackAdapter) {
|
|
70
|
-
// // // throw new AdapterError(
|
|
71
|
-
// // // "Primary verify failed and no fallback adapter is configured."
|
|
72
|
-
// // // );
|
|
73
|
-
// // // }
|
|
74
|
-
|
|
75
|
-
// // // try {
|
|
76
|
-
// // // return await this.fallbackAdapter.verify(value, hashed);
|
|
77
|
-
// // // } catch (fallbackErr: any) {
|
|
78
|
-
// // // logger.error("❌ Fallback verify failed", {
|
|
79
|
-
// // // error: fallbackErr?.message,
|
|
80
|
-
// // // });
|
|
81
|
-
|
|
82
|
-
// // // throw new AdapterError(
|
|
83
|
-
// // // "Both primary and fallback verify failed."
|
|
84
|
-
// // // );
|
|
85
|
-
// // // }
|
|
86
|
-
// // // }
|
|
87
|
-
// // // }
|
|
88
|
-
// // // }
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// // import { AdapterError } from "../core/errors/AdapterError.js";
|
|
97
|
-
// // import { HiSecureConfig } from "../core/config.js";
|
|
98
|
-
// // import { logger } from "../logging";
|
|
99
|
-
|
|
100
|
-
// // interface HashAdapter {
|
|
101
|
-
// // hash(value: string): Promise<string>;
|
|
102
|
-
// // verify(value: string, hashed: string): Promise<boolean>;
|
|
103
|
-
// // }
|
|
104
|
-
|
|
105
|
-
// // export class HashManager {
|
|
106
|
-
// // private config: HiSecureConfig["hashing"];
|
|
107
|
-
// // private primaryAdapter: HashAdapter;
|
|
108
|
-
// // private fallbackAdapter: HashAdapter | null;
|
|
109
|
-
|
|
110
|
-
// // constructor(
|
|
111
|
-
// // config: HiSecureConfig["hashing"],
|
|
112
|
-
// // primaryAdapter: HashAdapter,
|
|
113
|
-
// // fallbackAdapter: HashAdapter | null
|
|
114
|
-
// // ) {
|
|
115
|
-
// // this.config = config;
|
|
116
|
-
// // this.primaryAdapter = primaryAdapter;
|
|
117
|
-
// // this.fallbackAdapter = fallbackAdapter;
|
|
118
|
-
// // }
|
|
119
|
-
|
|
120
|
-
// // async hash(value: string): Promise<string> {
|
|
121
|
-
// // try {
|
|
122
|
-
// // return await this.primaryAdapter.hash(value);
|
|
123
|
-
// // } catch (err: any) {
|
|
124
|
-
// // logger.warn("⚠ Primary hashing failed — trying fallback", {
|
|
125
|
-
// // error: err?.message,
|
|
126
|
-
// // });
|
|
127
|
-
|
|
128
|
-
// // if (!this.fallbackAdapter) {
|
|
129
|
-
// // throw new AdapterError(
|
|
130
|
-
// // "Primary hashing failed and no fallback adapter configured."
|
|
131
|
-
// // );
|
|
132
|
-
// // }
|
|
133
|
-
|
|
134
|
-
// // try {
|
|
135
|
-
// // return await this.fallbackAdapter.hash(value);
|
|
136
|
-
// // } catch (fallbackErr: any) {
|
|
137
|
-
// // logger.error("❌ Fallback hashing failed", {
|
|
138
|
-
// // error: fallbackErr?.message,
|
|
139
|
-
// // });
|
|
140
|
-
// // throw new AdapterError(
|
|
141
|
-
// // "Both primary and fallback hashing failed."
|
|
142
|
-
// // );
|
|
143
|
-
// // }
|
|
144
|
-
// // }
|
|
145
|
-
// // }
|
|
146
|
-
|
|
147
|
-
// // async verify(value: string, hashed: string): Promise<boolean> {
|
|
148
|
-
// // try {
|
|
149
|
-
// // return await this.primaryAdapter.verify(value, hashed);
|
|
150
|
-
// // } catch (err: any) {
|
|
151
|
-
// // logger.warn("⚠ Primary verify failed — trying fallback", {
|
|
152
|
-
// // error: err?.message,
|
|
153
|
-
// // });
|
|
154
|
-
|
|
155
|
-
// // if (!this.fallbackAdapter) {
|
|
156
|
-
// // throw new AdapterError(
|
|
157
|
-
// // "Primary verify failed and no fallback adapter configured."
|
|
158
|
-
// // );
|
|
159
|
-
// // }
|
|
160
|
-
|
|
161
|
-
// // try {
|
|
162
|
-
// // return await this.fallbackAdapter.verify(value, hashed);
|
|
163
|
-
// // } catch (fallbackErr: any) {
|
|
164
|
-
// // logger.error("❌ Fallback verify failed", {
|
|
165
|
-
// // error: fallbackErr?.message,
|
|
166
|
-
// // });
|
|
167
|
-
// // throw new AdapterError(
|
|
168
|
-
// // "Both primary and fallback verify failed."
|
|
169
|
-
// // );
|
|
170
|
-
// // }
|
|
171
|
-
// // }
|
|
172
|
-
// // }
|
|
173
|
-
// // }
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// // src/managers/HashManager.ts - FIXED
|
|
178
|
-
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
179
|
-
// import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
|
|
180
|
-
// import { logger } from "../logging";
|
|
181
|
-
|
|
182
|
-
// interface HashAdapter {
|
|
183
|
-
// hash(value: string): Promise<string>;
|
|
184
|
-
// verify(value: string, hashed: string): Promise<boolean>;
|
|
185
|
-
// getAlgorithm(): string;
|
|
186
|
-
// }
|
|
187
|
-
|
|
188
|
-
// export interface HashResult {
|
|
189
|
-
// hash: string;
|
|
190
|
-
// algorithm: string;
|
|
191
|
-
// usedFallback: boolean;
|
|
192
|
-
// }
|
|
193
|
-
|
|
194
|
-
// export class HashManager {
|
|
195
|
-
// private config: HiSecureConfig["hashing"];
|
|
196
|
-
// private primaryAdapter: HashAdapter;
|
|
197
|
-
// private fallbackAdapter: HashAdapter | null;
|
|
198
|
-
|
|
199
|
-
// constructor(
|
|
200
|
-
// config: HiSecureConfig["hashing"],
|
|
201
|
-
// primaryAdapter: HashAdapter,
|
|
202
|
-
// fallbackAdapter: HashAdapter | null
|
|
203
|
-
// ) {
|
|
204
|
-
// this.config = config;
|
|
205
|
-
// this.primaryAdapter = primaryAdapter;
|
|
206
|
-
// this.fallbackAdapter = fallbackAdapter;
|
|
207
|
-
// }
|
|
208
|
-
|
|
209
|
-
// async hash(value: string, options?: { allowFallback?: boolean }): Promise<HashResult> {
|
|
210
|
-
// try {
|
|
211
|
-
// const hash = await this.primaryAdapter.hash(value);
|
|
212
|
-
// return {
|
|
213
|
-
// hash,
|
|
214
|
-
// algorithm: this.config.primary,
|
|
215
|
-
// usedFallback: false
|
|
216
|
-
// };
|
|
217
|
-
// } catch (err: any) {
|
|
218
|
-
// logger.warn("⚠ Primary hashing failed", {
|
|
219
|
-
// error: err.message,
|
|
220
|
-
// algorithm: this.config.primary
|
|
221
|
-
// });
|
|
222
|
-
|
|
223
|
-
// if (!options?.allowFallback || !this.fallbackAdapter) {
|
|
224
|
-
// throw new AdapterError(
|
|
225
|
-
// `Primary hashing (${this.config.primary}) failed. Fallback not allowed.`
|
|
226
|
-
// );
|
|
227
|
-
// }
|
|
228
|
-
|
|
229
|
-
// try {
|
|
230
|
-
// const hash = await this.fallbackAdapter.hash(value);
|
|
231
|
-
|
|
232
|
-
// // Log security downgrade warning
|
|
233
|
-
// logger.warn("⚠ SECURITY DOWNGRADE: Using fallback hashing", {
|
|
234
|
-
// from: this.config.primary,
|
|
235
|
-
// to: this.config.fallback
|
|
236
|
-
// });
|
|
237
|
-
|
|
238
|
-
// return {
|
|
239
|
-
// hash,
|
|
240
|
-
// algorithm: this.config.fallback || 'bcrypt',
|
|
241
|
-
// usedFallback: true
|
|
242
|
-
// };
|
|
243
|
-
// } catch (fallbackErr: any) {
|
|
244
|
-
// logger.error("❌ Fallback hashing failed", {
|
|
245
|
-
// error: fallbackErr?.message,
|
|
246
|
-
// });
|
|
247
|
-
// throw new AdapterError(
|
|
248
|
-
// "Both primary and fallback hashing failed."
|
|
249
|
-
// );
|
|
250
|
-
// }
|
|
251
|
-
// }
|
|
252
|
-
// }
|
|
253
|
-
|
|
254
|
-
// async verify(value: string, hashed: string): Promise<boolean> {
|
|
255
|
-
// // Try primary adapter first
|
|
256
|
-
// try {
|
|
257
|
-
// return await this.primaryAdapter.verify(value, hashed);
|
|
258
|
-
// } catch (primaryErr: any) {
|
|
259
|
-
// logger.warn("⚠ Primary verify failed", {
|
|
260
|
-
// error: primaryErr?.message,
|
|
261
|
-
// });
|
|
262
|
-
|
|
263
|
-
// // If fallback exists, try it
|
|
264
|
-
// if (this.fallbackAdapter) {
|
|
265
|
-
// try {
|
|
266
|
-
// return await this.fallbackAdapter.verify(value, hashed);
|
|
267
|
-
// } catch (fallbackErr: any) {
|
|
268
|
-
// logger.error("❌ Fallback verify failed", {
|
|
269
|
-
// error: fallbackErr?.message,
|
|
270
|
-
// });
|
|
271
|
-
// throw new AdapterError(
|
|
272
|
-
// "Both primary and fallback verify failed."
|
|
273
|
-
// );
|
|
274
|
-
// }
|
|
275
|
-
// }
|
|
276
|
-
|
|
277
|
-
// throw new AdapterError(
|
|
278
|
-
// "Primary verify failed and no fallback adapter configured."
|
|
279
|
-
// );
|
|
280
|
-
// }
|
|
281
|
-
// }
|
|
282
|
-
// }
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// src/managers/HashManager.ts - COMPLETE FIXED
|
|
286
1
|
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
287
2
|
import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
|
|
288
3
|
import { logger } from "../logging";
|
|
@@ -290,7 +5,6 @@ import { logger } from "../logging";
|
|
|
290
5
|
interface HashAdapter {
|
|
291
6
|
hash(value: string): Promise<string>;
|
|
292
7
|
verify(value: string, hashed: string): Promise<boolean>;
|
|
293
|
-
// ❌ getAlgorithm() REMOVED - Not needed in adapters
|
|
294
8
|
}
|
|
295
9
|
|
|
296
10
|
export interface HashResult {
|