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.
- package/dist/adapters/ArgonAdapter.d.ts +1 -1
- package/dist/adapters/ArgonAdapter.d.ts.map +1 -1
- package/dist/adapters/ArgonAdapter.js +43 -5
- package/dist/adapters/ArgonAdapter.js.map +1 -1
- package/dist/adapters/BcryptAdapter.d.ts.map +1 -1
- package/dist/adapters/BcryptAdapter.js +43 -3
- package/dist/adapters/BcryptAdapter.js.map +1 -1
- package/dist/adapters/ExpressRLAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressRLAdapter.js +48 -6
- package/dist/adapters/ExpressRLAdapter.js.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.d.ts.map +1 -1
- package/dist/adapters/ExpressValidatorAdapter.js +50 -10
- package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
- package/dist/adapters/GoogleAdapter.d.ts.map +1 -1
- package/dist/adapters/GoogleAdapter.js +82 -16
- package/dist/adapters/GoogleAdapter.js.map +1 -1
- package/dist/adapters/JWTAdapter.d.ts.map +1 -1
- package/dist/adapters/JWTAdapter.js +104 -15
- package/dist/adapters/JWTAdapter.js.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.d.ts.map +1 -1
- package/dist/adapters/RLFlexibleAdapter.js +87 -12
- package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.d.ts.map +1 -1
- package/dist/adapters/SanitizeHtmlAdapter.js +81 -13
- package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
- package/dist/adapters/XSSAdapter.d.ts +1 -1
- package/dist/adapters/XSSAdapter.d.ts.map +1 -1
- package/dist/adapters/XSSAdapter.js +137 -20
- package/dist/adapters/XSSAdapter.js.map +1 -1
- package/dist/adapters/ZodAdapter.d.ts +1 -1
- package/dist/adapters/ZodAdapter.d.ts.map +1 -1
- package/dist/adapters/ZodAdapter.js +13 -8
- package/dist/adapters/ZodAdapter.js.map +1 -1
- package/dist/core/HiSecure.d.ts +3 -4
- package/dist/core/HiSecure.d.ts.map +1 -1
- package/dist/core/HiSecure.js +108 -121
- package/dist/core/HiSecure.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/index.d.ts.map +1 -1
- package/dist/logging/index.js +2 -0
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/morganSetup.d.ts.map +1 -1
- package/dist/logging/morganSetup.js +22 -1
- package/dist/logging/morganSetup.js.map +1 -1
- package/dist/logging/winstonSetup.d.ts.map +1 -1
- package/dist/logging/winstonSetup.js +61 -3
- package/dist/logging/winstonSetup.js.map +1 -1
- package/dist/managers/AuthManager.d.ts +2 -2
- package/dist/managers/AuthManager.d.ts.map +1 -1
- package/dist/managers/AuthManager.js +167 -31
- package/dist/managers/AuthManager.js.map +1 -1
- package/dist/managers/CorsManager.d.ts.map +1 -1
- package/dist/managers/CorsManager.js +46 -11
- package/dist/managers/CorsManager.js.map +1 -1
- package/dist/managers/HashManager.d.ts +1 -1
- package/dist/managers/HashManager.d.ts.map +1 -1
- package/dist/managers/HashManager.js +127 -17
- package/dist/managers/HashManager.js.map +1 -1
- package/dist/managers/JsonManager.d.ts +1 -1
- package/dist/managers/JsonManager.d.ts.map +1 -1
- package/dist/managers/JsonManager.js +99 -16
- package/dist/managers/JsonManager.js.map +1 -1
- package/dist/managers/RateLimitManager.d.ts +1 -1
- package/dist/managers/RateLimitManager.d.ts.map +1 -1
- package/dist/managers/RateLimitManager.js +46 -22
- package/dist/managers/RateLimitManager.js.map +1 -1
- package/dist/managers/SanitizerManager.d.ts.map +1 -1
- package/dist/managers/SanitizerManager.js +112 -15
- package/dist/managers/SanitizerManager.js.map +1 -1
- package/dist/managers/ValidatorManager.d.ts.map +1 -1
- package/dist/managers/ValidatorManager.js +90 -7
- package/dist/managers/ValidatorManager.js.map +1 -1
- package/package.json +19 -1
- package/readme.md +3 -6
- package/src/adapters/ArgonAdapter.ts +55 -6
- package/src/adapters/BcryptAdapter.ts +56 -8
- package/src/adapters/ExpressRLAdapter.ts +62 -9
- package/src/adapters/ExpressValidatorAdapter.ts +67 -11
- package/src/adapters/GoogleAdapter.ts +106 -21
- package/src/adapters/JWTAdapter.ts +129 -21
- package/src/adapters/RLFlexibleAdapter.ts +113 -16
- package/src/adapters/SanitizeHtmlAdapter.ts +111 -18
- package/src/adapters/XSSAdapter.ts +183 -39
- package/src/adapters/ZodAdapter.ts +56 -10
- package/src/core/HiSecure.ts +496 -162
- package/src/index.ts +4 -0
- package/src/logging/index.ts +6 -0
- package/src/logging/morganSetup.ts +36 -1
- package/src/logging/winstonSetup.ts +97 -8
- package/src/managers/AuthManager.ts +205 -34
- package/src/managers/CorsManager.ts +63 -16
- package/src/managers/HashManager.ts +156 -19
- package/src/managers/JsonManager.ts +119 -15
- package/src/managers/RateLimitManager.ts +174 -29
- package/src/managers/SanitizerManager.ts +150 -25
- package/src/managers/ValidatorManager.ts +115 -15
package/src/index.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { HiSecure } from "./core/HiSecure.js";
|
|
2
2
|
import { useSecure, secureRoute } from "./core/useSecure.js";
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
export { z } from "zod";
|
|
6
|
+
export { body, query, param, header } from "express-validator";
|
|
7
|
+
|
|
4
8
|
const hiSecure = HiSecure.getInstance();
|
|
5
9
|
|
|
6
10
|
export {
|
package/src/logging/index.ts
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
// // import morgan from "morgan";
|
|
2
|
+
|
|
3
|
+
// // export const requestLogger = morgan("combined");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// import morgan from "morgan";
|
|
9
|
+
// import { logger } from "./winstonSetup";
|
|
10
|
+
|
|
11
|
+
// export const requestLogger = morgan(
|
|
12
|
+
// ":method :url :status :response-time ms",
|
|
13
|
+
// {
|
|
14
|
+
// stream: {
|
|
15
|
+
// write: (message) => {
|
|
16
|
+
// logger.http(message.trim());
|
|
17
|
+
// }
|
|
18
|
+
// }
|
|
19
|
+
// }
|
|
20
|
+
// );
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
1
26
|
import morgan from "morgan";
|
|
27
|
+
import { logger } from "./winstonSetup";
|
|
2
28
|
|
|
3
|
-
export const requestLogger = morgan(
|
|
29
|
+
export const requestLogger = morgan(
|
|
30
|
+
":method :url :status :response-time ms",
|
|
31
|
+
{
|
|
32
|
+
stream: {
|
|
33
|
+
write: (message) => {
|
|
34
|
+
logger.http(message.trim());
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
);
|
|
@@ -1,17 +1,106 @@
|
|
|
1
|
+
// // import winston from "winston";
|
|
2
|
+
|
|
3
|
+
// // export const logger = winston.createLogger({
|
|
4
|
+
// // level: "info",
|
|
5
|
+
// // format: winston.format.combine(
|
|
6
|
+
// // winston.format.timestamp(),
|
|
7
|
+
// // winston.format.json()
|
|
8
|
+
// // ),
|
|
9
|
+
// // transports: [
|
|
10
|
+
// // new winston.transports.Console()
|
|
11
|
+
// // ]
|
|
12
|
+
// // });
|
|
13
|
+
|
|
14
|
+
// // // Shortcut helpers
|
|
15
|
+
// // export const logInfo = (msg: string, meta: any = {}) => logger.info(msg, meta);
|
|
16
|
+
// // export const logWarn = (msg: string, meta: any = {}) => logger.warn(msg, meta);
|
|
17
|
+
// // export const logError = (msg: string, meta: any = {}) => logger.error(msg, meta);
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
// import winston from "winston";
|
|
23
|
+
|
|
24
|
+
// const { combine, timestamp, printf, colorize, errors } = winston.format;
|
|
25
|
+
|
|
26
|
+
// const logFormat = printf(({ level, message, timestamp, ...meta }) => {
|
|
27
|
+
// const metaString =
|
|
28
|
+
// Object.keys(meta).length > 0 ? ` | ${JSON.stringify(meta)}` : "";
|
|
29
|
+
|
|
30
|
+
// return `${timestamp} ${level}: ${message}${metaString}`;
|
|
31
|
+
// });
|
|
32
|
+
|
|
33
|
+
// export const logger = winston.createLogger({
|
|
34
|
+
// level: "info",
|
|
35
|
+
// format: combine(
|
|
36
|
+
// errors({ stack: true }),
|
|
37
|
+
// timestamp({ format: "HH:mm:ss" })
|
|
38
|
+
// ),
|
|
39
|
+
// transports: [
|
|
40
|
+
// new winston.transports.Console({
|
|
41
|
+
// format: combine(
|
|
42
|
+
// colorize({ all: true }),
|
|
43
|
+
// logFormat
|
|
44
|
+
// )
|
|
45
|
+
// })
|
|
46
|
+
// ]
|
|
47
|
+
// });
|
|
48
|
+
|
|
49
|
+
// // Shortcut helpers
|
|
50
|
+
// export const logInfo = (msg: string, meta: any = {}) =>
|
|
51
|
+
// logger.info(msg, meta);
|
|
52
|
+
|
|
53
|
+
// export const logWarn = (msg: string, meta: any = {}) =>
|
|
54
|
+
// logger.warn(msg, meta);
|
|
55
|
+
|
|
56
|
+
// export const logError = (msg: string, meta: any = {}) =>
|
|
57
|
+
// logger.error(msg, meta);
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
1
63
|
import winston from "winston";
|
|
2
64
|
|
|
65
|
+
const { combine, timestamp, printf, colorize, errors } = winston.format;
|
|
66
|
+
|
|
67
|
+
// Explicit colors (best practice)
|
|
68
|
+
winston.addColors({
|
|
69
|
+
error: "red",
|
|
70
|
+
warn: "yellow",
|
|
71
|
+
info: "green",
|
|
72
|
+
http: "cyan"
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const logFormat = printf(({ level, message, timestamp, ...meta }) => {
|
|
76
|
+
const metaString =
|
|
77
|
+
Object.keys(meta).length > 0 ? ` | ${JSON.stringify(meta)}` : "";
|
|
78
|
+
|
|
79
|
+
return `${timestamp} ${level}: ${message}${metaString}`;
|
|
80
|
+
});
|
|
81
|
+
|
|
3
82
|
export const logger = winston.createLogger({
|
|
4
|
-
level: "
|
|
5
|
-
format:
|
|
6
|
-
|
|
7
|
-
|
|
83
|
+
level: "http", // 🔴 MOST IMPORTANT FIX
|
|
84
|
+
format: combine(
|
|
85
|
+
errors({ stack: true }),
|
|
86
|
+
timestamp({ format: "HH:mm:ss" })
|
|
8
87
|
),
|
|
9
88
|
transports: [
|
|
10
|
-
new winston.transports.Console(
|
|
89
|
+
new winston.transports.Console({
|
|
90
|
+
format: combine(
|
|
91
|
+
colorize({ all: true }),
|
|
92
|
+
logFormat
|
|
93
|
+
)
|
|
94
|
+
})
|
|
11
95
|
]
|
|
12
96
|
});
|
|
13
97
|
|
|
14
98
|
// Shortcut helpers
|
|
15
|
-
export const logInfo = (msg: string, meta: any = {}) =>
|
|
16
|
-
|
|
17
|
-
|
|
99
|
+
export const logInfo = (msg: string, meta: any = {}) =>
|
|
100
|
+
logger.info(msg, meta);
|
|
101
|
+
|
|
102
|
+
export const logWarn = (msg: string, meta: any = {}) =>
|
|
103
|
+
logger.warn(msg, meta);
|
|
104
|
+
|
|
105
|
+
export const logError = (msg: string, meta: any = {}) =>
|
|
106
|
+
logger.error(msg, meta);
|
|
@@ -1,11 +1,151 @@
|
|
|
1
|
-
import { JWTAdapter } from "../adapters/JWTAdapter.js";
|
|
2
|
-
import { GoogleAdapter } from "../adapters/GoogleAdapter.js";
|
|
3
|
-
import { AdapterError } from "../core/errors/AdapterError.js";
|
|
4
|
-
import { HttpError } from "../core/errors/HttpError.js";
|
|
1
|
+
// import { JWTAdapter } from "../adapters/JWTAdapter.js";
|
|
2
|
+
// import { GoogleAdapter } from "../adapters/GoogleAdapter.js";
|
|
3
|
+
// import { AdapterError } from "../core/errors/AdapterError.js";
|
|
4
|
+
// import { HttpError } from "../core/errors/HttpError.js";
|
|
5
|
+
// import { Request, Response, NextFunction } from "express";
|
|
6
|
+
// import { logger } from "../logging";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// export interface AuthOptions {
|
|
10
|
+
// jwtSecret: string;
|
|
11
|
+
// jwtExpiresIn?: string | number;
|
|
12
|
+
// googleClientId?: string;
|
|
13
|
+
// }
|
|
14
|
+
|
|
15
|
+
// export interface ProtectOptions {
|
|
16
|
+
// required?: boolean;
|
|
17
|
+
// roles?: string[];
|
|
18
|
+
// }
|
|
19
|
+
|
|
20
|
+
// export class AuthManager {
|
|
21
|
+
// private jwtAdapter: JWTAdapter;
|
|
22
|
+
// private googleAdapter?: GoogleAdapter;
|
|
23
|
+
|
|
24
|
+
// constructor(opts: AuthOptions) {
|
|
25
|
+
// if (!opts.jwtSecret) {
|
|
26
|
+
// throw new AdapterError("jwtSecret required in AuthOptions");
|
|
27
|
+
// }
|
|
28
|
+
|
|
29
|
+
// if (opts.jwtSecret.length < 32) {
|
|
30
|
+
// logger.warn(" JWT secret is less than 32 characters - consider using a stronger secret");
|
|
31
|
+
// }
|
|
32
|
+
|
|
33
|
+
// logger.info("AuthManager initialized");
|
|
34
|
+
|
|
35
|
+
// this.jwtAdapter = new JWTAdapter({
|
|
36
|
+
// secret: opts.jwtSecret,
|
|
37
|
+
// expiresIn: opts.jwtExpiresIn ?? "1d",
|
|
38
|
+
// });
|
|
39
|
+
|
|
40
|
+
// if (opts.googleClientId) {
|
|
41
|
+
// this.googleAdapter = new GoogleAdapter(opts.googleClientId);
|
|
42
|
+
// logger.info("GoogleAdapter enabled");
|
|
43
|
+
// }
|
|
44
|
+
// }
|
|
45
|
+
|
|
46
|
+
// sign(payload: object, options?: { expiresIn?: string | number, jti?: string }) {
|
|
47
|
+
// logger.info("JWT Sign called");
|
|
48
|
+
// return this.jwtAdapter.sign(payload, options);
|
|
49
|
+
// }
|
|
50
|
+
|
|
51
|
+
// verify(token: string) {
|
|
52
|
+
// logger.info("JWT Verify called");
|
|
53
|
+
// return this.jwtAdapter.verify(token);
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// async verifyGoogleIdToken(idToken: string) {
|
|
57
|
+
// if (!this.googleAdapter) {
|
|
58
|
+
// throw new AdapterError("GoogleAdapter not configured.");
|
|
59
|
+
// }
|
|
60
|
+
|
|
61
|
+
// logger.info("Google ID Token verify called");
|
|
62
|
+
|
|
63
|
+
// try {
|
|
64
|
+
// return await this.googleAdapter.verifyIdToken(idToken);
|
|
65
|
+
// } catch (err: any) {
|
|
66
|
+
// logger.error("Google ID Token verification failed", { error: err?.message });
|
|
67
|
+
// throw HttpError.Unauthorized("Invalid Google ID token");
|
|
68
|
+
// }
|
|
69
|
+
// }
|
|
70
|
+
|
|
71
|
+
// protect(options?: ProtectOptions) {
|
|
72
|
+
// const required = options?.required ?? true;
|
|
73
|
+
// const roles = options?.roles;
|
|
74
|
+
|
|
75
|
+
// return (req: Request, res: Response, next: NextFunction) => {
|
|
76
|
+
// const header = req.headers["authorization"];
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
// if (!required && !header) {
|
|
80
|
+
// return next();
|
|
81
|
+
// }
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// if (!header) {
|
|
85
|
+
// logger.warn("Missing Authorization header", {
|
|
86
|
+
// path: req.path,
|
|
87
|
+
// method: req.method
|
|
88
|
+
// });
|
|
89
|
+
// return next(HttpError.Unauthorized("Missing Authorization header"));
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// const [type, token] = String(header).split(" ");
|
|
94
|
+
// if (type !== "Bearer" || !token) {
|
|
95
|
+
// logger.warn("Invalid Authorization header", {
|
|
96
|
+
// path: req.path,
|
|
97
|
+
// method: req.method
|
|
98
|
+
// });
|
|
99
|
+
// return next(HttpError.Unauthorized("Invalid Authorization header"));
|
|
100
|
+
// }
|
|
101
|
+
|
|
102
|
+
// try {
|
|
103
|
+
|
|
104
|
+
// // Verify JWT
|
|
105
|
+
// const decoded = this.verify(token);
|
|
106
|
+
|
|
107
|
+
// // Attach to request
|
|
108
|
+
// (req as any).auth = decoded;
|
|
109
|
+
// (req as any).user = decoded;
|
|
110
|
+
|
|
111
|
+
// // Role-based authorization - role added Middleware
|
|
112
|
+
// if (roles && roles.length > 0) {
|
|
113
|
+
// const userRole = (decoded as any).role || (decoded as any).roles?.[0];
|
|
114
|
+
// if (!userRole || !roles.includes(userRole)) {
|
|
115
|
+
// logger.warn("Insufficient permissions", {
|
|
116
|
+
// path: req.path,
|
|
117
|
+
// requiredRoles: roles,
|
|
118
|
+
// userRole
|
|
119
|
+
// });
|
|
120
|
+
// return next(HttpError.Forbidden("Insufficient permissions"));
|
|
121
|
+
// }
|
|
122
|
+
// }
|
|
123
|
+
|
|
124
|
+
// return next();
|
|
125
|
+
// } catch (err: any) {
|
|
126
|
+
// logger.error("JWT verify failed", {
|
|
127
|
+
// error: err?.message,
|
|
128
|
+
// path: req.path,
|
|
129
|
+
// method: req.method
|
|
130
|
+
// });
|
|
131
|
+
// return next(HttpError.Unauthorized("Invalid or expired token"));
|
|
132
|
+
// }
|
|
133
|
+
// };
|
|
134
|
+
// }
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
import { JWTAdapter } from "../adapters/JWTAdapter";
|
|
143
|
+
import { GoogleAdapter } from "../adapters/GoogleAdapter";
|
|
144
|
+
import { AdapterError } from "../core/errors/AdapterError";
|
|
145
|
+
import { HttpError } from "../core/errors/HttpError";
|
|
5
146
|
import { Request, Response, NextFunction } from "express";
|
|
6
147
|
import { logger } from "../logging";
|
|
7
148
|
|
|
8
|
-
|
|
9
149
|
export interface AuthOptions {
|
|
10
150
|
jwtSecret: string;
|
|
11
151
|
jwtExpiresIn?: string | number;
|
|
@@ -27,29 +167,47 @@ export class AuthManager {
|
|
|
27
167
|
}
|
|
28
168
|
|
|
29
169
|
if (opts.jwtSecret.length < 32) {
|
|
30
|
-
logger.warn(" JWT secret
|
|
170
|
+
logger.warn("Weak JWT secret detected", {
|
|
171
|
+
layer: "auth-manager",
|
|
172
|
+
operation: "init",
|
|
173
|
+
secretLength: opts.jwtSecret.length
|
|
174
|
+
});
|
|
31
175
|
}
|
|
32
176
|
|
|
33
|
-
logger.info("AuthManager initialized"
|
|
177
|
+
logger.info("AuthManager initialized", {
|
|
178
|
+
layer: "auth-manager",
|
|
179
|
+
jwtExpiresIn: opts.jwtExpiresIn ?? "1d",
|
|
180
|
+
googleEnabled: !!opts.googleClientId
|
|
181
|
+
});
|
|
34
182
|
|
|
35
183
|
this.jwtAdapter = new JWTAdapter({
|
|
36
184
|
secret: opts.jwtSecret,
|
|
37
|
-
expiresIn: opts.jwtExpiresIn ?? "1d"
|
|
185
|
+
expiresIn: opts.jwtExpiresIn ?? "1d"
|
|
38
186
|
});
|
|
39
187
|
|
|
40
188
|
if (opts.googleClientId) {
|
|
41
189
|
this.googleAdapter = new GoogleAdapter(opts.googleClientId);
|
|
42
|
-
logger.info("
|
|
190
|
+
logger.info("Google authentication enabled", {
|
|
191
|
+
layer: "auth-manager"
|
|
192
|
+
});
|
|
43
193
|
}
|
|
44
194
|
}
|
|
45
195
|
|
|
46
|
-
sign(payload: object, options?: { expiresIn?: string | number
|
|
47
|
-
logger.info("JWT
|
|
196
|
+
sign(payload: object, options?: { expiresIn?: string | number; jti?: string }) {
|
|
197
|
+
logger.info("JWT sign requested", {
|
|
198
|
+
layer: "auth-manager",
|
|
199
|
+
operation: "sign"
|
|
200
|
+
});
|
|
201
|
+
|
|
48
202
|
return this.jwtAdapter.sign(payload, options);
|
|
49
203
|
}
|
|
50
204
|
|
|
51
205
|
verify(token: string) {
|
|
52
|
-
logger.info("JWT
|
|
206
|
+
logger.info("JWT verify requested", {
|
|
207
|
+
layer: "auth-manager",
|
|
208
|
+
operation: "verify"
|
|
209
|
+
});
|
|
210
|
+
|
|
53
211
|
return this.jwtAdapter.verify(token);
|
|
54
212
|
}
|
|
55
213
|
|
|
@@ -58,12 +216,20 @@ export class AuthManager {
|
|
|
58
216
|
throw new AdapterError("GoogleAdapter not configured.");
|
|
59
217
|
}
|
|
60
218
|
|
|
61
|
-
logger.info("Google ID
|
|
219
|
+
logger.info("Google ID token verification requested", {
|
|
220
|
+
layer: "auth-manager",
|
|
221
|
+
operation: "google-verify"
|
|
222
|
+
});
|
|
62
223
|
|
|
63
224
|
try {
|
|
64
225
|
return await this.googleAdapter.verifyIdToken(idToken);
|
|
65
226
|
} catch (err: any) {
|
|
66
|
-
logger.error("Google ID
|
|
227
|
+
logger.error("Google ID token verification failed", {
|
|
228
|
+
layer: "auth-manager",
|
|
229
|
+
operation: "google-verify",
|
|
230
|
+
reason: err?.message
|
|
231
|
+
});
|
|
232
|
+
|
|
67
233
|
throw HttpError.Unauthorized("Invalid Google ID token");
|
|
68
234
|
}
|
|
69
235
|
}
|
|
@@ -72,27 +238,28 @@ export class AuthManager {
|
|
|
72
238
|
const required = options?.required ?? true;
|
|
73
239
|
const roles = options?.roles;
|
|
74
240
|
|
|
75
|
-
return (req: Request,
|
|
241
|
+
return (req: Request, _res: Response, next: NextFunction) => {
|
|
76
242
|
const header = req.headers["authorization"];
|
|
77
243
|
|
|
78
|
-
|
|
79
244
|
if (!required && !header) {
|
|
80
245
|
return next();
|
|
81
246
|
}
|
|
82
247
|
|
|
83
|
-
|
|
84
248
|
if (!header) {
|
|
85
|
-
logger.warn("
|
|
249
|
+
logger.warn("Authorization header missing", {
|
|
250
|
+
layer: "auth-manager",
|
|
251
|
+
operation: "protect",
|
|
86
252
|
path: req.path,
|
|
87
253
|
method: req.method
|
|
88
254
|
});
|
|
89
255
|
return next(HttpError.Unauthorized("Missing Authorization header"));
|
|
90
256
|
}
|
|
91
257
|
|
|
92
|
-
|
|
93
258
|
const [type, token] = String(header).split(" ");
|
|
94
259
|
if (type !== "Bearer" || !token) {
|
|
95
|
-
logger.warn("Invalid Authorization header", {
|
|
260
|
+
logger.warn("Invalid Authorization header format", {
|
|
261
|
+
layer: "auth-manager",
|
|
262
|
+
operation: "protect",
|
|
96
263
|
path: req.path,
|
|
97
264
|
method: req.method
|
|
98
265
|
});
|
|
@@ -100,36 +267,40 @@ export class AuthManager {
|
|
|
100
267
|
}
|
|
101
268
|
|
|
102
269
|
try {
|
|
103
|
-
|
|
104
|
-
// Verify JWT
|
|
105
270
|
const decoded = this.verify(token);
|
|
106
|
-
|
|
107
|
-
// Attach to request
|
|
271
|
+
|
|
108
272
|
(req as any).auth = decoded;
|
|
109
|
-
(req as any).user = decoded;
|
|
110
|
-
|
|
111
|
-
// Role-based authorization - role added Middleware
|
|
273
|
+
(req as any).user = decoded;
|
|
274
|
+
|
|
112
275
|
if (roles && roles.length > 0) {
|
|
113
|
-
const userRole =
|
|
276
|
+
const userRole =
|
|
277
|
+
(decoded as any).role || (decoded as any).roles?.[0];
|
|
278
|
+
|
|
114
279
|
if (!userRole || !roles.includes(userRole)) {
|
|
115
|
-
logger.warn("
|
|
280
|
+
logger.warn("Access denied: insufficient role", {
|
|
281
|
+
layer: "auth-manager",
|
|
282
|
+
operation: "authorize",
|
|
116
283
|
path: req.path,
|
|
117
284
|
requiredRoles: roles,
|
|
118
285
|
userRole
|
|
119
286
|
});
|
|
287
|
+
|
|
120
288
|
return next(HttpError.Forbidden("Insufficient permissions"));
|
|
121
289
|
}
|
|
122
290
|
}
|
|
123
|
-
|
|
291
|
+
|
|
124
292
|
return next();
|
|
125
293
|
} catch (err: any) {
|
|
126
|
-
logger.error("JWT
|
|
127
|
-
|
|
294
|
+
logger.error("JWT authentication failed", {
|
|
295
|
+
layer: "auth-manager",
|
|
296
|
+
operation: "protect",
|
|
128
297
|
path: req.path,
|
|
129
|
-
method: req.method
|
|
298
|
+
method: req.method,
|
|
299
|
+
reason: err?.message
|
|
130
300
|
});
|
|
301
|
+
|
|
131
302
|
return next(HttpError.Unauthorized("Invalid or expired token"));
|
|
132
303
|
}
|
|
133
304
|
};
|
|
134
305
|
}
|
|
135
|
-
}
|
|
306
|
+
}
|
|
@@ -1,34 +1,81 @@
|
|
|
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
|
+
// const defaultOptions = {
|
|
10
|
+
// origin: '*',
|
|
11
|
+
// methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
12
|
+
// allowedHeaders: ['Content-Type', 'Authorization'],
|
|
13
|
+
// credentials: false,
|
|
14
|
+
// maxAge: 86400
|
|
15
|
+
// };
|
|
16
|
+
|
|
17
|
+
// const finalOptions = options ? { ...defaultOptions, ...options } : defaultOptions;
|
|
18
|
+
|
|
19
|
+
// logger.debug("CORS configured", {
|
|
20
|
+
// origin: finalOptions.origin,
|
|
21
|
+
// methods: finalOptions.methods
|
|
22
|
+
// });
|
|
23
|
+
|
|
24
|
+
// return cors(finalOptions);
|
|
25
|
+
|
|
26
|
+
// } catch (err: any) {
|
|
27
|
+
// logger.error(" CORS Manager: failed to create CORS middleware", {
|
|
28
|
+
// error: err?.message || err,
|
|
29
|
+
// options
|
|
30
|
+
// });
|
|
31
|
+
// throw new AdapterError("CORS middleware initialization failed.");
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
1
41
|
import cors from "cors";
|
|
2
42
|
import { logger } from "../logging";
|
|
3
|
-
import { AdapterError } from "../core/errors/AdapterError
|
|
43
|
+
import { AdapterError } from "../core/errors/AdapterError";
|
|
4
44
|
|
|
5
45
|
export class CorsManager {
|
|
6
|
-
|
|
7
46
|
middleware(options?: any) {
|
|
8
47
|
try {
|
|
9
48
|
const defaultOptions = {
|
|
10
|
-
origin:
|
|
11
|
-
methods: [
|
|
12
|
-
allowedHeaders: [
|
|
49
|
+
origin: "*",
|
|
50
|
+
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
|
|
51
|
+
allowedHeaders: ["Content-Type", "Authorization"],
|
|
13
52
|
credentials: false,
|
|
14
53
|
maxAge: 86400
|
|
15
54
|
};
|
|
16
|
-
|
|
17
|
-
const finalOptions = options
|
|
18
|
-
|
|
19
|
-
|
|
55
|
+
|
|
56
|
+
const finalOptions = options
|
|
57
|
+
? { ...defaultOptions, ...options }
|
|
58
|
+
: defaultOptions;
|
|
59
|
+
|
|
60
|
+
// ✅ visible + clean log
|
|
61
|
+
logger.info("CORS middleware configured", {
|
|
62
|
+
layer: "cors-manager",
|
|
63
|
+
operation: "init",
|
|
20
64
|
origin: finalOptions.origin,
|
|
21
|
-
methods: finalOptions.methods
|
|
65
|
+
methods: finalOptions.methods,
|
|
66
|
+
credentials: finalOptions.credentials
|
|
22
67
|
});
|
|
23
|
-
|
|
68
|
+
|
|
24
69
|
return cors(finalOptions);
|
|
25
|
-
|
|
70
|
+
|
|
26
71
|
} catch (err: any) {
|
|
27
|
-
logger.error("
|
|
28
|
-
|
|
29
|
-
|
|
72
|
+
logger.error("CORS middleware initialization failed", {
|
|
73
|
+
layer: "cors-manager",
|
|
74
|
+
operation: "init",
|
|
75
|
+
reason: err?.message
|
|
30
76
|
});
|
|
77
|
+
|
|
31
78
|
throw new AdapterError("CORS middleware initialization failed.");
|
|
32
79
|
}
|
|
33
80
|
}
|
|
34
|
-
}
|
|
81
|
+
}
|