hi-secure 1.0.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/adapters/ArgonAdapter.d.ts +8 -0
- package/dist/adapters/ArgonAdapter.d.ts.map +1 -0
- package/dist/adapters/ArgonAdapter.js +45 -0
- package/dist/adapters/ArgonAdapter.js.map +1 -0
- package/dist/adapters/BcryptAdapter.d.ts +7 -0
- package/dist/adapters/BcryptAdapter.d.ts.map +1 -0
- package/dist/adapters/BcryptAdapter.js +48 -0
- package/dist/adapters/BcryptAdapter.js.map +1 -0
- package/dist/adapters/DomPurifyAdapter.d.ts +13 -0
- package/dist/adapters/DomPurifyAdapter.d.ts.map +1 -0
- package/dist/adapters/DomPurifyAdapter.js +61 -0
- package/dist/adapters/DomPurifyAdapter.js.map +1 -0
- package/dist/adapters/ExpressRLAdapter.d.ts +13 -0
- package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -0
- package/dist/adapters/ExpressRLAdapter.js +68 -0
- package/dist/adapters/ExpressRLAdapter.js.map +1 -0
- package/dist/adapters/ExpressValidatorAdapter.d.ts +6 -0
- package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -0
- package/dist/adapters/ExpressValidatorAdapter.js +78 -0
- package/dist/adapters/ExpressValidatorAdapter.js.map +1 -0
- package/dist/adapters/GoggleAdapter.d.ts +15 -0
- package/dist/adapters/GoggleAdapter.d.ts.map +1 -0
- package/dist/adapters/GoggleAdapter.js +91 -0
- package/dist/adapters/GoggleAdapter.js.map +1 -0
- package/dist/adapters/GoogleAdapter.d.ts +15 -0
- package/dist/adapters/GoogleAdapter.d.ts.map +1 -0
- package/dist/adapters/GoogleAdapter.js +159 -0
- package/dist/adapters/GoogleAdapter.js.map +1 -0
- package/dist/adapters/JWTAdapter.d.ts +28 -0
- package/dist/adapters/JWTAdapter.d.ts.map +1 -0
- package/dist/adapters/JWTAdapter.js +276 -0
- package/dist/adapters/JWTAdapter.js.map +1 -0
- package/dist/adapters/RLFlexibleAdapter.d.ts +11 -0
- package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -0
- package/dist/adapters/RLFlexibleAdapter.js +115 -0
- package/dist/adapters/RLFlexibleAdapter.js.map +1 -0
- package/dist/adapters/SanitizeHtmlAdapter.d.ts +12 -0
- package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -0
- package/dist/adapters/SanitizeHtmlAdapter.js +141 -0
- package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -0
- package/dist/adapters/XSSAdapter.d.ts +33 -0
- package/dist/adapters/XSSAdapter.d.ts.map +1 -0
- package/dist/adapters/XSSAdapter.js +127 -0
- package/dist/adapters/XSSAdapter.js.map +1 -0
- package/dist/adapters/ZodAdapter.d.ts +7 -0
- package/dist/adapters/ZodAdapter.d.ts.map +1 -0
- package/dist/adapters/ZodAdapter.js +39 -0
- package/dist/adapters/ZodAdapter.js.map +1 -0
- package/dist/core/HiSecure.d.ts +62 -0
- package/dist/core/HiSecure.d.ts.map +1 -0
- package/dist/core/HiSecure.js +273 -0
- package/dist/core/HiSecure.js.map +1 -0
- package/dist/core/config.d.ts +3 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +53 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/constants.d.ts +37 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +67 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/errors/AdapterError.d.ts +5 -0
- package/dist/core/errors/AdapterError.d.ts.map +1 -0
- package/dist/core/errors/AdapterError.js +15 -0
- package/dist/core/errors/AdapterError.js.map +1 -0
- package/dist/core/errors/HttpErrror.d.ts +17 -0
- package/dist/core/errors/HttpErrror.d.ts.map +1 -0
- package/dist/core/errors/HttpErrror.js +36 -0
- package/dist/core/errors/HttpErrror.js.map +1 -0
- package/dist/core/errors/SanitizerError.d.ts +5 -0
- package/dist/core/errors/SanitizerError.d.ts.map +1 -0
- package/dist/core/errors/SanitizerError.js +14 -0
- package/dist/core/errors/SanitizerError.js.map +1 -0
- package/dist/core/errors/SecurityError.d.ts +5 -0
- package/dist/core/errors/SecurityError.d.ts.map +1 -0
- package/dist/core/errors/SecurityError.js +14 -0
- package/dist/core/errors/SecurityError.js.map +1 -0
- package/dist/core/errors/ValidationError.d.ts +5 -0
- package/dist/core/errors/ValidationError.d.ts.map +1 -0
- package/dist/core/errors/ValidationError.js +14 -0
- package/dist/core/errors/ValidationError.js.map +1 -0
- package/dist/core/types/HiSecureConfig.d.ts +47 -0
- package/dist/core/types/HiSecureConfig.d.ts.map +1 -0
- package/dist/core/types/HiSecureConfig.js +3 -0
- package/dist/core/types/HiSecureConfig.js.map +1 -0
- package/dist/core/types/SecureOptions.d.ts +30 -0
- package/dist/core/types/SecureOptions.d.ts.map +1 -0
- package/dist/core/types/SecureOptions.js +4 -0
- package/dist/core/types/SecureOptions.js.map +1 -0
- package/dist/core/useSecure.d.ts +10 -0
- package/dist/core/useSecure.d.ts.map +1 -0
- package/dist/core/useSecure.js +85 -0
- package/dist/core/useSecure.js.map +1 -0
- package/dist/examples/e1.d.ts +1 -0
- package/dist/examples/e1.d.ts.map +1 -0
- package/dist/examples/e1.js +3 -0
- package/dist/examples/e1.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/index.d.ts +3 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +19 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/morganSetup.d.ts +2 -0
- package/dist/logging/morganSetup.d.ts.map +1 -0
- package/dist/logging/morganSetup.js +9 -0
- package/dist/logging/morganSetup.js.map +1 -0
- package/dist/logging/winstonSetup.d.ts +6 -0
- package/dist/logging/winstonSetup.d.ts.map +1 -0
- package/dist/logging/winstonSetup.js +22 -0
- package/dist/logging/winstonSetup.js.map +1 -0
- package/dist/managers/AuthManager.d.ts +23 -0
- package/dist/managers/AuthManager.d.ts.map +1 -0
- package/dist/managers/AuthManager.js +190 -0
- package/dist/managers/AuthManager.js.map +1 -0
- package/dist/managers/CorsManager.d.ts +9 -0
- package/dist/managers/CorsManager.d.ts.map +1 -0
- package/dist/managers/CorsManager.js +55 -0
- package/dist/managers/CorsManager.js.map +1 -0
- package/dist/managers/HashManager.d.ts +22 -0
- package/dist/managers/HashManager.d.ts.map +1 -0
- package/dist/managers/HashManager.js +319 -0
- package/dist/managers/HashManager.js.map +1 -0
- package/dist/managers/JsonManager.d.ts +6 -0
- package/dist/managers/JsonManager.d.ts.map +1 -0
- package/dist/managers/JsonManager.js +142 -0
- package/dist/managers/JsonManager.js.map +1 -0
- package/dist/managers/RateLimitManager.d.ts +16 -0
- package/dist/managers/RateLimitManager.d.ts.map +1 -0
- package/dist/managers/RateLimitManager.js +108 -0
- package/dist/managers/RateLimitManager.js.map +1 -0
- package/dist/managers/SanitizerManager.d.ts +18 -0
- package/dist/managers/SanitizerManager.d.ts.map +1 -0
- package/dist/managers/SanitizerManager.js +296 -0
- package/dist/managers/SanitizerManager.js.map +1 -0
- package/dist/managers/ValidatorManager.d.ts +13 -0
- package/dist/managers/ValidatorManager.d.ts.map +1 -0
- package/dist/managers/ValidatorManager.js +218 -0
- package/dist/managers/ValidatorManager.js.map +1 -0
- package/dist/middlewares/errorHandler.d.ts +3 -0
- package/dist/middlewares/errorHandler.d.ts.map +1 -0
- package/dist/middlewares/errorHandler.js +94 -0
- package/dist/middlewares/errorHandler.js.map +1 -0
- package/dist/middlewares/index.d.ts +3 -0
- package/dist/middlewares/index.d.ts.map +1 -0
- package/dist/middlewares/index.js +19 -0
- package/dist/middlewares/index.js.map +1 -0
- package/dist/middlewares/requestLogger.d.ts +2 -0
- package/dist/middlewares/requestLogger.d.ts.map +1 -0
- package/dist/middlewares/requestLogger.js +8 -0
- package/dist/middlewares/requestLogger.js.map +1 -0
- package/dist/test/t1.d.ts +1 -0
- package/dist/test/t1.d.ts.map +1 -0
- package/dist/test/t1.js +3 -0
- package/dist/test/t1.js.map +1 -0
- package/dist/utils/deepFreeze.d.ts +2 -0
- package/dist/utils/deepFreeze.d.ts.map +1 -0
- package/dist/utils/deepFreeze.js +69 -0
- package/dist/utils/deepFreeze.js.map +1 -0
- package/dist/utils/deepMerge.d.ts +5 -0
- package/dist/utils/deepMerge.d.ts.map +1 -0
- package/dist/utils/deepMerge.js +68 -0
- package/dist/utils/deepMerge.js.map +1 -0
- package/dist/utils/normalizeOptions.d.ts +38 -0
- package/dist/utils/normalizeOptions.d.ts.map +1 -0
- package/dist/utils/normalizeOptions.js +119 -0
- package/dist/utils/normalizeOptions.js.map +1 -0
- package/package.json +50 -0
- package/src/adapters/ArgonAdapter.ts +41 -0
- package/src/adapters/BcryptAdapter.ts +49 -0
- package/src/adapters/ExpressRLAdapter.ts +84 -0
- package/src/adapters/ExpressValidatorAdapter.ts +99 -0
- package/src/adapters/GoogleAdapter.ts +206 -0
- package/src/adapters/JWTAdapter.ts +346 -0
- package/src/adapters/RLFlexibleAdapter.ts +139 -0
- package/src/adapters/SanitizeHtmlAdapter.ts +162 -0
- package/src/adapters/XSSAdapter.ts +153 -0
- package/src/adapters/ZodAdapter.ts +91 -0
- package/src/core/HiSecure.ts +955 -0
- package/src/core/config.ts +156 -0
- package/src/core/constants.ts +73 -0
- package/src/core/errors/AdapterError.ts +14 -0
- package/src/core/errors/HttpErrror.ts +46 -0
- package/src/core/errors/SanitizerError.ts +13 -0
- package/src/core/errors/SecurityError.ts +13 -0
- package/src/core/errors/ValidationError.ts +13 -0
- package/src/core/types/HiSecureConfig.ts +62 -0
- package/src/core/types/SecureOptions.ts +61 -0
- package/src/core/useSecure.ts +111 -0
- package/src/examples/e1.ts +1 -0
- package/src/index.ts +17 -0
- package/src/logging/index.ts +2 -0
- package/src/logging/morganSetup.ts +3 -0
- package/src/logging/winstonSetup.ts +17 -0
- package/src/managers/AuthManager.ts +237 -0
- package/src/managers/CorsManager.ts +58 -0
- package/src/managers/HashManager.ts +390 -0
- package/src/managers/JsonManager.ts +149 -0
- package/src/managers/RateLimitManager.ts +368 -0
- package/src/managers/SanitizerManager.ts +359 -0
- package/src/managers/ValidatorManager.ts +269 -0
- package/src/middlewares/errorHandler.ts +265 -0
- package/src/middlewares/index.ts +2 -0
- package/src/middlewares/requestLogger.ts +5 -0
- package/src/test/t1.ts +1 -0
- package/src/utils/deepFreeze.ts +76 -0
- package/src/utils/deepMerge.ts +87 -0
- package/src/utils/normalizeOptions.ts +265 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,237 @@
|
|
|
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
|
+
import { JWTAdapter } from "../adapters/JWTAdapter.js";
|
|
106
|
+
import { GoogleAdapter } from "../adapters/GoogleAdapter.js";
|
|
107
|
+
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
108
|
+
import { HttpError } from "../core/errors/HttpErrror.js";
|
|
109
|
+
import { Request, Response, NextFunction } from "express";
|
|
110
|
+
import { logError, logWarn, logInfo } from "../logging";
|
|
111
|
+
|
|
112
|
+
export interface AuthOptions {
|
|
113
|
+
jwtSecret: string;
|
|
114
|
+
jwtExpiresIn?: string | number;
|
|
115
|
+
googleClientId?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface ProtectOptions {
|
|
119
|
+
required?: boolean;
|
|
120
|
+
roles?: string[];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export class AuthManager {
|
|
124
|
+
private jwtAdapter: JWTAdapter;
|
|
125
|
+
private googleAdapter?: GoogleAdapter;
|
|
126
|
+
|
|
127
|
+
constructor(opts: AuthOptions) {
|
|
128
|
+
if (!opts.jwtSecret) {
|
|
129
|
+
throw new AdapterError("jwtSecret required in AuthOptions");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (opts.jwtSecret.length < 32) {
|
|
133
|
+
logWarn("⚠ JWT secret is less than 32 characters - consider using a stronger secret");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
logInfo("AuthManager initialized");
|
|
137
|
+
|
|
138
|
+
this.jwtAdapter = new JWTAdapter({
|
|
139
|
+
secret: opts.jwtSecret,
|
|
140
|
+
expiresIn: opts.jwtExpiresIn ?? "1d",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
if (opts.googleClientId) {
|
|
144
|
+
this.googleAdapter = new GoogleAdapter(opts.googleClientId);
|
|
145
|
+
logInfo("GoogleAdapter enabled");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
sign(payload: object, options?: { expiresIn?: string | number, jti?: string }) {
|
|
150
|
+
logInfo("JWT Sign called");
|
|
151
|
+
return this.jwtAdapter.sign(payload, options);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
verify(token: string) {
|
|
155
|
+
logInfo("JWT Verify called");
|
|
156
|
+
return this.jwtAdapter.verify(token);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async verifyGoogleIdToken(idToken: string) {
|
|
160
|
+
if (!this.googleAdapter) {
|
|
161
|
+
throw new AdapterError("GoogleAdapter not configured.");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
logInfo("Google ID Token verify called");
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
return await this.googleAdapter.verifyIdToken(idToken);
|
|
168
|
+
} catch (err: any) {
|
|
169
|
+
logError("Google ID Token verification failed", { error: err?.message });
|
|
170
|
+
throw HttpError.Unauthorized("Invalid Google ID token");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
protect(options?: ProtectOptions) {
|
|
175
|
+
const required = options?.required ?? true;
|
|
176
|
+
const roles = options?.roles;
|
|
177
|
+
|
|
178
|
+
return (req: Request, res: Response, next: NextFunction) => {
|
|
179
|
+
const header = req.headers["authorization"];
|
|
180
|
+
|
|
181
|
+
// If auth is not required, skip authentication
|
|
182
|
+
if (!required && !header) {
|
|
183
|
+
return next();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// If auth is required but no header
|
|
187
|
+
if (!header) {
|
|
188
|
+
logWarn("Missing Authorization header", {
|
|
189
|
+
path: req.path,
|
|
190
|
+
method: req.method
|
|
191
|
+
});
|
|
192
|
+
return next(HttpError.Unauthorized("Missing Authorization header"));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Parse Bearer token
|
|
196
|
+
const [type, token] = String(header).split(" ");
|
|
197
|
+
if (type !== "Bearer" || !token) {
|
|
198
|
+
logWarn("Invalid Authorization header", {
|
|
199
|
+
path: req.path,
|
|
200
|
+
method: req.method
|
|
201
|
+
});
|
|
202
|
+
return next(HttpError.Unauthorized("Invalid Authorization header"));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
// Verify JWT
|
|
207
|
+
const decoded = this.verify(token);
|
|
208
|
+
|
|
209
|
+
// Attach to request
|
|
210
|
+
(req as any).auth = decoded;
|
|
211
|
+
(req as any).user = decoded; // Common pattern
|
|
212
|
+
|
|
213
|
+
// Role-based authorization
|
|
214
|
+
if (roles && roles.length > 0) {
|
|
215
|
+
const userRole = (decoded as any).role || (decoded as any).roles?.[0];
|
|
216
|
+
if (!userRole || !roles.includes(userRole)) {
|
|
217
|
+
logWarn("Insufficient permissions", {
|
|
218
|
+
path: req.path,
|
|
219
|
+
requiredRoles: roles,
|
|
220
|
+
userRole
|
|
221
|
+
});
|
|
222
|
+
return next(HttpError.Forbidden("Insufficient permissions"));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return next();
|
|
227
|
+
} catch (err: any) {
|
|
228
|
+
logError("JWT verify failed", {
|
|
229
|
+
error: err?.message,
|
|
230
|
+
path: req.path,
|
|
231
|
+
method: req.method
|
|
232
|
+
});
|
|
233
|
+
return next(HttpError.Unauthorized("Invalid or expired token"));
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
import cors from "cors";
|
|
26
|
+
import { logger } from "../logging";
|
|
27
|
+
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
28
|
+
|
|
29
|
+
export class CorsManager {
|
|
30
|
+
|
|
31
|
+
middleware(options?: any) {
|
|
32
|
+
try {
|
|
33
|
+
const defaultOptions = {
|
|
34
|
+
origin: '*',
|
|
35
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
36
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
37
|
+
credentials: false,
|
|
38
|
+
maxAge: 86400 // 24 hours
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const finalOptions = options ? { ...defaultOptions, ...options } : defaultOptions;
|
|
42
|
+
|
|
43
|
+
logger.debug("🔧 CORS configured", {
|
|
44
|
+
origin: finalOptions.origin,
|
|
45
|
+
methods: finalOptions.methods
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return cors(finalOptions);
|
|
49
|
+
|
|
50
|
+
} catch (err: any) {
|
|
51
|
+
logger.error("❌ CORS Manager: failed to create CORS middleware", {
|
|
52
|
+
error: err?.message || err,
|
|
53
|
+
options
|
|
54
|
+
});
|
|
55
|
+
throw new AdapterError("CORS middleware initialization failed.");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,390 @@
|
|
|
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
|
+
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
287
|
+
import { HiSecureConfig } from "../core/types/HiSecureConfig.js";
|
|
288
|
+
import { logger } from "../logging";
|
|
289
|
+
|
|
290
|
+
interface HashAdapter {
|
|
291
|
+
hash(value: string): Promise<string>;
|
|
292
|
+
verify(value: string, hashed: string): Promise<boolean>;
|
|
293
|
+
// ❌ getAlgorithm() REMOVED - Not needed in adapters
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export interface HashResult {
|
|
297
|
+
hash: string;
|
|
298
|
+
algorithm: string;
|
|
299
|
+
usedFallback: boolean;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export class HashManager {
|
|
303
|
+
private config: HiSecureConfig["hashing"];
|
|
304
|
+
private primaryAdapter: HashAdapter;
|
|
305
|
+
private fallbackAdapter: HashAdapter | null;
|
|
306
|
+
|
|
307
|
+
constructor(
|
|
308
|
+
config: HiSecureConfig["hashing"],
|
|
309
|
+
primaryAdapter: HashAdapter,
|
|
310
|
+
fallbackAdapter: HashAdapter | null
|
|
311
|
+
) {
|
|
312
|
+
this.config = config;
|
|
313
|
+
this.primaryAdapter = primaryAdapter;
|
|
314
|
+
this.fallbackAdapter = fallbackAdapter;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async hash(value: string, options?: { allowFallback?: boolean }): Promise<HashResult> {
|
|
318
|
+
try {
|
|
319
|
+
const hash = await this.primaryAdapter.hash(value);
|
|
320
|
+
return {
|
|
321
|
+
hash,
|
|
322
|
+
algorithm: this.config.primary,
|
|
323
|
+
usedFallback: false
|
|
324
|
+
};
|
|
325
|
+
} catch (err: any) {
|
|
326
|
+
logger.warn("⚠ Primary hashing failed", {
|
|
327
|
+
error: err.message,
|
|
328
|
+
algorithm: this.config.primary
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
if (!options?.allowFallback || !this.fallbackAdapter) {
|
|
332
|
+
throw new AdapterError(
|
|
333
|
+
`Primary hashing (${this.config.primary}) failed. Fallback not allowed.`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
const hash = await this.fallbackAdapter.hash(value);
|
|
339
|
+
|
|
340
|
+
// Log security downgrade warning
|
|
341
|
+
logger.warn("⚠ SECURITY DOWNGRADE: Using fallback hashing", {
|
|
342
|
+
from: this.config.primary,
|
|
343
|
+
to: this.config.fallback
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
hash,
|
|
348
|
+
algorithm: this.config.fallback || 'bcrypt',
|
|
349
|
+
usedFallback: true
|
|
350
|
+
};
|
|
351
|
+
} catch (fallbackErr: any) {
|
|
352
|
+
logger.error("❌ Fallback hashing failed", {
|
|
353
|
+
error: fallbackErr?.message,
|
|
354
|
+
});
|
|
355
|
+
throw new AdapterError(
|
|
356
|
+
"Both primary and fallback hashing failed."
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async verify(value: string, hashed: string): Promise<boolean> {
|
|
363
|
+
// Try primary adapter first
|
|
364
|
+
try {
|
|
365
|
+
return await this.primaryAdapter.verify(value, hashed);
|
|
366
|
+
} catch (primaryErr: any) {
|
|
367
|
+
logger.warn("⚠ Primary verify failed", {
|
|
368
|
+
error: primaryErr?.message,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// If fallback exists, try it
|
|
372
|
+
if (this.fallbackAdapter) {
|
|
373
|
+
try {
|
|
374
|
+
return await this.fallbackAdapter.verify(value, hashed);
|
|
375
|
+
} catch (fallbackErr: any) {
|
|
376
|
+
logger.error("❌ Fallback verify failed", {
|
|
377
|
+
error: fallbackErr?.message,
|
|
378
|
+
});
|
|
379
|
+
throw new AdapterError(
|
|
380
|
+
"Both primary and fallback verify failed."
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
throw new AdapterError(
|
|
386
|
+
"Primary verify failed and no fallback adapter configured."
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|