hi-secure 1.0.12 → 1.0.14

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 (83) hide show
  1. package/dist/adapters/ArgonAdapter.js +2 -2
  2. package/dist/adapters/ArgonAdapter.js.map +1 -1
  3. package/dist/adapters/BcryptAdapter.js +2 -2
  4. package/dist/adapters/BcryptAdapter.js.map +1 -1
  5. package/dist/adapters/ExpressRLAdapter.js +2 -2
  6. package/dist/adapters/ExpressRLAdapter.js.map +1 -1
  7. package/dist/adapters/ExpressValidatorAdapter.js +1 -1
  8. package/dist/adapters/ExpressValidatorAdapter.js.map +1 -1
  9. package/dist/adapters/GoogleAdapter.js +3 -3
  10. package/dist/adapters/GoogleAdapter.js.map +1 -1
  11. package/dist/adapters/JWTAdapter.js +2 -2
  12. package/dist/adapters/JWTAdapter.js.map +1 -1
  13. package/dist/adapters/RLFlexibleAdapter.js +2 -2
  14. package/dist/adapters/RLFlexibleAdapter.js.map +1 -1
  15. package/dist/adapters/SanitizeHtmlAdapter.js +3 -3
  16. package/dist/adapters/SanitizeHtmlAdapter.js.map +1 -1
  17. package/dist/adapters/XSSAdapter.js +3 -3
  18. package/dist/adapters/XSSAdapter.js.map +1 -1
  19. package/dist/adapters/ZodAdapter.js +1 -1
  20. package/dist/adapters/ZodAdapter.js.map +1 -1
  21. package/dist/core/HiSecure.d.ts.map +1 -1
  22. package/dist/core/HiSecure.js +9 -8
  23. package/dist/core/HiSecure.js.map +1 -1
  24. package/dist/core/config.d.ts.map +1 -1
  25. package/dist/core/config.js +0 -7
  26. package/dist/core/config.js.map +1 -1
  27. package/dist/core/constants.d.ts.map +1 -1
  28. package/dist/core/constants.js +0 -27
  29. package/dist/core/constants.js.map +1 -1
  30. package/dist/core/errors/AdapterError.js +1 -1
  31. package/dist/core/errors/AdapterError.js.map +1 -1
  32. package/dist/core/types/HiSecureConfig.d.ts.map +1 -1
  33. package/dist/core/types/HiSecureConfig.js.map +1 -1
  34. package/dist/core/types/SecureOptions.d.ts.map +1 -1
  35. package/dist/core/types/SecureOptions.js +0 -1
  36. package/dist/core/types/SecureOptions.js.map +1 -1
  37. package/dist/core/useSecure.d.ts.map +1 -1
  38. package/dist/core/useSecure.js +1 -1
  39. package/dist/core/useSecure.js.map +1 -1
  40. package/dist/managers/AuthManager.js +2 -2
  41. package/dist/managers/AuthManager.js.map +1 -1
  42. package/dist/managers/CorsManager.d.ts.map +1 -1
  43. package/dist/managers/CorsManager.js +2 -2
  44. package/dist/managers/CorsManager.js.map +1 -1
  45. package/dist/managers/HashManager.js +7 -7
  46. package/dist/managers/HashManager.js.map +1 -1
  47. package/dist/managers/JsonManager.js +4 -4
  48. package/dist/managers/JsonManager.js.map +1 -1
  49. package/dist/managers/RateLimitManager.js +5 -5
  50. package/dist/managers/RateLimitManager.js.map +1 -1
  51. package/dist/managers/SanitizerManager.js +5 -5
  52. package/dist/managers/SanitizerManager.js.map +1 -1
  53. package/dist/managers/ValidatorManager.js +2 -2
  54. package/dist/managers/ValidatorManager.js.map +1 -1
  55. package/dist/middlewares/errorHandler.js +3 -3
  56. package/dist/middlewares/errorHandler.js.map +1 -1
  57. package/package.json +1 -1
  58. package/readme.md +566 -388
  59. package/src/adapters/ArgonAdapter.ts +2 -2
  60. package/src/adapters/BcryptAdapter.ts +2 -2
  61. package/src/adapters/ExpressRLAdapter.ts +2 -2
  62. package/src/adapters/ExpressValidatorAdapter.ts +1 -1
  63. package/src/adapters/GoogleAdapter.ts +3 -3
  64. package/src/adapters/JWTAdapter.ts +2 -2
  65. package/src/adapters/RLFlexibleAdapter.ts +2 -2
  66. package/src/adapters/SanitizeHtmlAdapter.ts +3 -3
  67. package/src/adapters/XSSAdapter.ts +3 -3
  68. package/src/adapters/ZodAdapter.ts +1 -1
  69. package/src/core/HiSecure.ts +10 -8
  70. package/src/core/config.ts +0 -105
  71. package/src/core/constants.ts +0 -33
  72. package/src/core/errors/AdapterError.ts +1 -1
  73. package/src/core/types/HiSecureConfig.ts +0 -1
  74. package/src/core/types/SecureOptions.ts +0 -27
  75. package/src/core/useSecure.ts +1 -3
  76. package/src/managers/AuthManager.ts +2 -2
  77. package/src/managers/CorsManager.ts +2 -2
  78. package/src/managers/HashManager.ts +7 -7
  79. package/src/managers/JsonManager.ts +4 -4
  80. package/src/managers/RateLimitManager.ts +5 -5
  81. package/src/managers/SanitizerManager.ts +5 -5
  82. package/src/managers/ValidatorManager.ts +2 -2
  83. package/src/middlewares/errorHandler.ts +3 -3
package/readme.md CHANGED
@@ -2,279 +2,445 @@
2
2
  <p align="center"><strong>One-line security for Express.js</strong></p>
3
3
 
4
4
  <p align="center">
5
- HiSecure replaces <strong>10+ common Express security libraries</strong> with one unified API.<br/>
6
- It provides hashing, authentication, validation, sanitization, rate-limiting, CORS,<br/>
7
- security headers, compression, JSON parsing, query parsing and logging — all in a single layer.
5
+ HiSecure unifies authentication, validation, sanitization, rate-limiting, headers and parsing<br/>
6
+ into a single, consistent security layer for Express applications.
8
7
  </p>
9
8
 
10
- <br/>
9
+ <hr/>
11
10
 
12
- <hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
13
-
14
- <h2>🚀 Overview</h2>
11
+ <h2>Overview</h2>
15
12
 
16
13
  <p>
17
- Most Express applications require multiple security packages: hashing, CORS, headers, sanitization,
18
- validation, rate-limits, compression, JSON parsing, query parsing, and authentication.
19
- Managing all of these separately leads to duplication, bugs, and misconfiguration.
14
+ Modern Express applications require multiple security libraries to handle authentication,
15
+ password hashing, validation, sanitization, rate limiting, headers, compression and parsing.
16
+ Managing these separately leads to duplicated logic, configuration drift and subtle bugs.
20
17
  </p>
21
18
 
22
- <p><strong>HiSecure handles all of them for you — with one middleware call.</strong></p>
19
+ <p>
20
+ <strong>HiSecure solves this by acting as a single orchestration layer.</strong>
21
+ </p>
23
22
 
24
23
  <ul>
25
- <li><code>argon2</code> / <code>bcrypt</code> — hashing</li>
26
- <li><code>sanitize-html</code> / <code>xss</code> sanitization</li>
27
- <li><code>express-validator</code> / <code>zod</code> validation</li>
28
- <li><code>helmet</code> / <code>hpp</code> — headers + HPP</li>
29
- <li><code>cors</code> CORS control</li>
30
- <li><code>express-rate-limit</code> + <code>rate-limiter-flexible</code> rate limiting</li>
31
- <li><code>compression</code> gzip</li>
32
- <li><code>json/urlencoded</code> — parsers</li>
33
- <li><code>qs</code> — secure deep query parsing</li>
24
+ <li>Password hashing (Argon2 with bcrypt fallback)</li>
25
+ <li>JWT authentication and route protection</li>
26
+ <li>Google login (ID token verification)</li>
27
+ <li>Request validation and sanitization</li>
28
+ <li>Rate limiting and abuse prevention</li>
29
+ <li>CORS, security headers and compression</li>
30
+ <li>JSON, URL and query parsing</li>
34
31
  </ul>
35
32
 
36
- <p><strong>HiSecure bundles all of these features out-of-the-box.</strong></p>
37
-
38
- <br/>
39
- <hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
33
+ <hr/>
40
34
 
41
- <h2>✨ Feature Matrix</h2>
42
-
43
- <p>
44
- A complete list of what HiSecure does.
45
- Everything is built to work together without configuration.
46
- </p>
35
+ <h2>Feature Matrix</h2>
47
36
 
48
37
  <table width="100%">
49
38
  <tr>
50
39
  <th align="left">Capability</th>
51
40
  <th align="left">Status</th>
52
- <th align="left">Details</th>
41
+ <th align="left">Notes</th>
53
42
  </tr>
54
43
 
55
44
  <tr>
56
- <td>🔐 JWT Authentication</td>
57
- <td>✅ Stable</td>
58
- <td>Built-in issuer, audience, expiry and subject support. Google ID-token adapter included.</td>
45
+ <td>JWT Authentication</td>
46
+ <td>Stable</td>
47
+ <td>Issuer, audience, expiry and subject supported</td>
59
48
  </tr>
60
49
 
61
50
  <tr>
62
- <td>🔑 Password Hashing (Argon2 + bcrypt fallback)</td>
63
- <td>✅ Stable</td>
64
- <td>Argon2-first approach with bcrypt fallback. No salt configuration required.</td>
51
+ <td>Password Hashing</td>
52
+ <td>Stable</td>
53
+ <td>Argon2 primary with bcrypt fallback</td>
65
54
  </tr>
66
55
 
67
56
  <tr>
68
- <td>🛡 Route Protection</td>
69
- <td>✅ Stable</td>
70
- <td>Authentication guard with support for roles (RBAC).</td>
57
+ <td>Google Login</td>
58
+ <td>Stable</td>
59
+ <td>ID token verification adapter included</td>
71
60
  </tr>
72
61
 
73
62
  <tr>
74
- <td>📏 Validation (Zod + express-validator)</td>
75
- <td>✅ Stable</td>
76
- <td>Automatically detects schema type. Provides a clean error format.</td>
63
+ <td>Route Protection (RBAC)</td>
64
+ <td>Stable</td>
65
+ <td>Role-based access via JWT payload</td>
77
66
  </tr>
78
67
 
79
68
  <tr>
80
- <td>🧼 Sanitization</td>
81
- <td>✅ Stable</td>
82
- <td>Protects against HTML injection & XSS using sanitize-html + xss fallback.</td>
69
+ <td>Validation</td>
70
+ <td>Stable</td>
71
+ <td>Zod and express-validator supported</td>
83
72
  </tr>
84
73
 
85
74
  <tr>
86
- <td>⏱ Rate Limiting</td>
87
- <td>✅ Stable</td>
88
- <td>Presets (strict/relaxed/api) + custom per-route limits. Fallback engine included.</td>
75
+ <td>Sanitization</td>
76
+ <td>Stable</td>
77
+ <td>HTML injection and XSS protection</td>
89
78
  </tr>
90
79
 
91
80
  <tr>
92
- <td>🌐 CORS</td>
93
- <td>✅ Stable</td>
94
- <td>Dynamic origins + full configuration support.</td>
81
+ <td>Rate Limiting</td>
82
+ <td>Stable</td>
83
+ <td>Presets and per-route configuration</td>
95
84
  </tr>
96
85
 
97
86
  <tr>
98
- <td>🧱 Security Headers</td>
99
- <td>✅ Stable</td>
100
- <td>Automatic helmet + HPP integration.</td>
87
+ <td>CORS & Headers</td>
88
+ <td>Stable</td>
89
+ <td>Helmet, HPP and CORS integrated</td>
101
90
  </tr>
102
91
 
103
92
  <tr>
104
- <td>📦 JSON & URL Parsing</td>
105
- <td>✅ Stable</td>
106
- <td>Togglable express.json + urlencoded, simple and safe.</td>
93
+ <td>Compression</td>
94
+ <td>Stable</td>
95
+ <td>gzip via a single flag</td>
107
96
  </tr>
108
97
 
109
98
  <tr>
110
- <td>🔍 Query Parsing</td>
111
- <td>✅ Stable</td>
112
- <td>Secure <code>qs</code>-based deep parsing out of the box.</td>
99
+ <td>Logging</td>
100
+ <td>Beta</td>
101
+ <td>Structured internal logs</td>
113
102
  </tr>
103
+ </table>
114
104
 
115
- <tr>
116
- <td>🌀 Compression</td>
117
- <td>✅ Stable</td>
118
- <td>gzip enabled via a single flag.</td>
119
- </tr>
105
+ <hr/>
120
106
 
121
- <tr>
122
- <td>📊 Structured Logging</td>
123
- <td>⚠️ Beta</td>
124
- <td>Unified log output for debugging & monitoring.</td>
125
- </tr>
107
+ <h2>Developer Experience</h2>
126
108
 
127
- <tr>
128
- <td>🔧 Adapter System</td>
129
- <td>✅ Stable</td>
130
- <td>Swap hashing/validation/sanitization engines easily.</td>
131
- </tr>
132
- </table>
109
+ <ul>
110
+ <li>Single global middleware for security</li>
111
+ <li>No manual wiring of multiple packages</li>
112
+ <li>Consistent error handling</li>
113
+ <li>Safe defaults with escape hatches</li>
114
+ <li>Beginner-friendly, production-ready</li>
115
+ </ul>
116
+
117
+ <hr/>
118
+
119
+ <h2>Quick Start</h2>
120
+
121
+ <pre><code>npm install hi-secure</code></pre>
122
+
123
+ <pre><code>import express from "express";
124
+ import { HiSecure } from "hi-secure";
125
+
126
+ const app = express();
127
+
128
+ app.use(HiSecure.middleware("api"));
129
+
130
+ app.listen(3000);
131
+ </code></pre>
133
132
 
134
- <br/>
135
- <hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
133
+ <hr/>
136
134
 
137
- <h2>⚡ Developer Experience Highlights</h2>
135
+ <h2>Core Helpers</h2>
136
+
137
+ <h3>Password Hashing</h3>
138
+
139
+ <pre><code>const hash = await HiSecure.hash(password);
140
+ const isValid = await HiSecure.verify(password, hash);
141
+ </code></pre>
142
+
143
+
144
+
145
+
146
+ <h3>Input Validation</h3>
147
+
148
+ <pre><code>router.post(
149
+ "/register",
150
+ HiSecure.validate([...]),
151
+ controller
152
+ );
153
+ </code></pre>
154
+
155
+ <h3>Rate Limiting</h3>
156
+
157
+ <pre><code>HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 });
158
+ </code></pre>
159
+
160
+
161
+
162
+ <hr/>
163
+
164
+ <h2>Global CORS Configuration</h2>
138
165
 
139
166
  <p>
140
- HiSecure is designed so even a beginner can set up security in minutes.
141
- Here’s what makes it simple:
167
+ Global CORS defines the baseline access rules for your entire application.
168
+ These rules apply to all routes unless explicitly overridden at the route level.
142
169
  </p>
143
170
 
144
- <ul>
145
- <li><strong>One-line global security</strong> using <code>HiSecure.middleware()</code></li>
171
+ <p>
172
+ This is ideal for standard APIs where most endpoints share the same access policy.
173
+ </p>
174
+
175
+ <hr/>
176
+
177
+ <h3>Basic Global CORS</h3>
178
+
179
+ <p>
180
+ Enable CORS globally using default configuration.
181
+ </p>
182
+
183
+ <pre><code>app.use(
184
+ HiSecure.middleware({
185
+ cors: true
186
+ })
187
+ );
188
+ </code></pre>
146
189
 
147
- <li><strong>Password utilities</strong>
148
- <br/>• <code>HiSecure.hash()</code> — secure Argon2 hashing
149
- <br/>• <code>HiSecure.verify()</code> — easy password comparison
150
- </li>
190
+ <hr/>
151
191
 
152
- <li><strong>JWT utilities</strong>
153
- <br/>• <code>HiSecure.jwt.sign()</code> — create tokens
154
- <br/>• <code>HiSecure.jwt.verify()</code> — verify tokens
155
- </li>
192
+ <h3>Custom Global CORS</h3>
156
193
 
157
- <li>Automatic sanitization — no extra middleware needed</li>
194
+ <p>
195
+ Define explicit CORS rules for all routes.
196
+ </p>
158
197
 
159
- <li>Auto-detected validation (Zod or express-validator)</li>
198
+ <pre><code>app.use(
199
+ HiSecure.middleware({
200
+ cors: {
201
+ origin: ["https://app.example.com"],
202
+ methods: ["GET", "POST", "PUT", "DELETE"],
203
+ allowedHeaders: ["Content-Type", "Authorization"],
204
+ credentials: true
205
+ }
206
+ })
207
+ );
208
+ </code></pre>
160
209
 
161
- <li>Clean route protection with <code>HiSecure.auth()</code></li>
210
+ <hr/>
162
211
 
163
- <li>Flexible rate limits for login routes and APIs</li>
212
+ <h3>Multiple Client Applications</h3>
164
213
 
165
- <li>Zero configuration for headers, parsing, gzip, CORS, etc.</li>
214
+ <p>
215
+ Allow multiple frontends (web, admin, mobile) to access the same API.
216
+ </p>
166
217
 
167
- <li>Perfect for beginners and production-grade APIs</li>
168
- </ul>
218
+ <pre><code>app.use(
219
+ HiSecure.middleware({
220
+ cors: {
221
+ origin: [
222
+ "https://web.example.com",
223
+ "https://admin.example.com",
224
+ "https://mobile.example.com"
225
+ ],
226
+ credentials: true
227
+ }
228
+ })
229
+ );
230
+ </code></pre>
169
231
 
170
- <br/>
171
- <hr style="border:0; border-top:2px solid #e5e7eb; margin:32px 0"/>
232
+ <hr/>
172
233
 
173
- <h2>📌 Summary</h2>
234
+ <h3>Public API (Open Read Access)</h3>
174
235
 
175
236
  <p>
176
- HiSecure provides a powerful but easy security layer:
237
+ Use open CORS rules for public or read-only APIs.
177
238
  </p>
178
239
 
179
- <ul>
180
- <li><strong>JWT Authentication</strong></li>
181
- <li><strong>Password Hashing</strong></li>
182
- <li><strong>Route Protection</strong></li>
183
- <li><strong>Validation + Sanitization</strong></li>
184
- <li><strong>Rate Limiting</strong> (primary + fallback)</li>
185
- <li><strong>CORS + Security Headers + Compression</strong></li>
186
- <li><strong>JSON + Query Parsing</strong></li>
187
- </ul>
240
+ <pre><code>app.use(
241
+ HiSecure.middleware({
242
+ cors: {
243
+ origin: "*",
244
+ methods: ["GET"]
245
+ }
246
+ })
247
+ );
248
+ </code></pre>
188
249
 
189
- <p align="center"><strong>
190
- Security without complexity.<br/>
191
- One dependency — complete Express protection.
192
- </strong></p>
250
+ <hr/>
193
251
 
194
- <br/><br/>
252
+ <h2> Route-Level Security (Advanced & Real-World Usage)</h2>
195
253
 
196
- <!-- ─────────────────────────────────────────────────────────────── -->
197
- <h2 align="center">📘 Documentation Sections</h2>
198
- <!-- ─────────────────────────────────────────────────────────────── -->
254
+ <p>
255
+ HiSecure supports fine-grained security control at the route level.
256
+ Each capability can be configured independently without affecting global middleware.
257
+ </p>
199
258
 
200
- <hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
259
+ <p>
260
+ This allows you to apply strict security where needed (auth, payments, admin)
261
+ and relaxed rules for public or internal endpoints.
262
+ </p>
201
263
 
202
- <h2>📘 Part 1 — Quick Start</h2>
264
+ <hr/>
203
265
 
204
- <p>This section is designed for beginners to get started within seconds.</p>
266
+ <h3>Custom CORS (Deep Control)</h3>
205
267
 
206
- <strong>Install</strong>
207
- <pre><code>npm install hi-secure</code></pre>
268
+ <p>
269
+ Route-level CORS is useful when different consumers access different endpoints
270
+ (e.g. web app, admin panel, third-party services).
271
+ </p>
208
272
 
209
- <strong>Basic Usage</strong>
210
- <pre><code>const express = require('express');
211
- const { HiSecure } = require('hi-secure');
273
+ <p><strong>Example: Webhook endpoint (single trusted origin)</strong></p>
212
274
 
213
- const app = express();
275
+ <pre><code>router.post(
276
+ "/webhook",
277
+ HiSecure.cors({
278
+ origin: ["https://trusted-client.com"],
279
+ methods: ["POST"],
280
+ allowedHeaders: ["Content-Type", "Authorization"],
281
+ credentials: true
282
+ }),
283
+ controller
284
+ );
285
+ </code></pre>
214
286
 
215
- // One-line complete security preset
216
- app.use(HiSecure.middleware('api'));
287
+ <p><strong>Example: Admin dashboard with restricted origins</strong></p>
217
288
 
218
- app.listen(3000);
289
+ <pre><code>router.get(
290
+ "/admin/stats",
291
+ HiSecure.cors({
292
+ origin: [
293
+ "https://admin.example.com",
294
+ "https://internal.example.com"
295
+ ],
296
+ credentials: true
297
+ }),
298
+ controller
299
+ );
219
300
  </code></pre>
220
301
 
221
- <p><small>The "api" preset includes CORS, Relaxed Rate Limit, Sanitization and basic headers.</small></p>
302
+ <p><strong>Example: Public API with open read access</strong></p>
222
303
 
223
- <br/>
224
- <hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
304
+ <pre><code>router.get(
305
+ "/public/feed",
306
+ HiSecure.cors({ origin: "*" }),
307
+ controller
308
+ );
309
+ </code></pre>
225
310
 
226
- <h2>📘 Part 2 — Using Built-In Helpers</h2>
311
+ <hr/>
227
312
 
228
- <h3>2.1 Hashing + Verifying Passwords</h3>
313
+ <h3>Validation (Schema vs Rules — When to Use What)</h3>
229
314
 
230
- <p>Perfect for controllers like register/login.</p>
315
+ <p>
316
+ HiSecure automatically detects validation strategy based on input type.
317
+ Choose the style based on complexity and ownership.
318
+ </p>
231
319
 
232
- <pre><code>const hashed = await HiSecure.hash(password);
233
- const valid = await HiSecure.verify(password, user.password);
234
- </code></pre>
320
+ <ul>
321
+ <li><strong>express-validator</strong> quick, form-like validation</li>
322
+ <li><strong>Zod</strong> — complex schemas, reuse, shared contracts</li>
323
+ </ul>
235
324
 
236
- <h3>2.2 Validating Inputs in Routes</h3>
325
+ <h4>express-validator (Rule-Based, Inline)</h4>
237
326
 
238
- <p>HiSecure automatically detects whether you're providing Zod or express-validator rules.</p>
327
+ <pre><code>import { body } from "express-validator";
239
328
 
240
- <pre><code>router.post(
241
- '/register',
329
+ router.post(
330
+ "/register",
242
331
  HiSecure.validate([
243
- body("name").notEmpty().isLength({ min: 3 }),
244
- body("email").notEmpty().isEmail(),
245
- body("password").notEmpty().isLength({ min: 6 })
332
+ body("email")
333
+ .notEmpty()
334
+ .isEmail(),
335
+
336
+ body("password")
337
+ .isLength({ min: 6 }),
338
+
339
+ body("role")
340
+ .optional()
341
+ .isIn(["user", "admin"])
246
342
  ]),
247
- registerUser
343
+ controller
344
+ );
345
+ </code></pre>
346
+
347
+ <h4>Zod (Schema-Based, Reusable)</h4>
348
+
349
+ <pre><code>import { z } from "zod";
350
+
351
+ const registerSchema = z.object({
352
+ email: z.string().email(),
353
+ password: z.string().min(6),
354
+ role: z.enum(["user", "admin"]).optional()
355
+ });
356
+
357
+ router.post(
358
+ "/register",
359
+ HiSecure.validate(registerSchema),
360
+ controller
248
361
  );
249
362
  </code></pre>
250
363
 
251
- <h3>2.3 Login Route with Rate Limiting</h3>
364
+ <p>
365
+ Both approaches produce a unified error response format.
366
+ </p>
367
+
368
+ <hr/>
369
+
370
+ <h3>Sanitization (Trust Boundaries)</h3>
371
+
372
+ <p>
373
+ Sanitization should reflect trust boundaries.
374
+ Not all routes require the same level of strictness.
375
+ </p>
376
+
377
+ <p><strong>User-generated content (allow formatting)</strong></p>
252
378
 
253
379
  <pre><code>router.post(
254
- '/login',
255
- HiSecure.validate([...]),
256
- HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 }),
257
- loginUser
380
+ "/comment",
381
+ HiSecure.sanitize({
382
+ allowedTags: ["b", "i", "strong", "em", "a"],
383
+ allowedAttributes: {
384
+ a: ["href"]
385
+ }
386
+ }),
387
+ controller
258
388
  );
259
389
  </code></pre>
260
390
 
261
- <h3>2.4 Protecting Routes with Auth Middleware</h3>
391
+ <p><strong>Strict input (no HTML allowed)</strong></p>
262
392
 
263
- <pre><code>router.get(
264
- '/profile',
265
- HiSecure.auth({ required: true }),
266
- getProfile
393
+ <pre><code>router.post(
394
+ "/feedback",
395
+ HiSecure.sanitize({
396
+ allowedTags: [],
397
+ allowedAttributes: {}
398
+ }),
399
+ controller
400
+ );
401
+ </code></pre>
402
+
403
+ <p><strong>Trusted internal pipeline (disable sanitization)</strong></p>
404
+
405
+ <pre><code>router.post(
406
+ "/internal/import",
407
+ HiSecure.sanitize(false),
408
+ controller
409
+ );
410
+ </code></pre>
411
+
412
+ <hr/>
413
+
414
+ <h3>Full Route-Level Security Composition</h3>
415
+
416
+ <p>
417
+ A real-world admin route combining multiple security layers.
418
+ Execution order is deterministic and isolated to the route.
419
+ </p>
420
+
421
+ <pre><code>router.post(
422
+ "/admin/create-user",
423
+ HiSecure.auth({ roles: ["admin"] }),
424
+ HiSecure.rateLimit({ max: 3, windowMs: 10 * 60 * 1000 }),
425
+ HiSecure.cors({
426
+ origin: ["https://admin.example.com"]
427
+ }),
428
+ HiSecure.sanitize(),
429
+ HiSecure.validate([
430
+ body("email").isEmail(),
431
+ body("password").isLength({ min: 8 })
432
+ ]),
433
+ controller
267
434
  );
268
435
  </code></pre>
269
436
 
270
- <br/>
271
- <hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
272
437
 
273
- <h2>📘 Part 3 — JWT Mode (Advanced)</h2>
274
438
 
275
- <p>Enable this mode only if you want full control over JWT signing options.</p>
439
+ <h2>JWT Mode</h2>
276
440
 
277
- <h3>3.1 Configure JWT Engine</h3>
441
+ <p>
442
+ JWT support is optional. Enable it only if you want authentication features.
443
+ </p>
278
444
 
279
445
  <pre><code>HiSecure.resetInstance();
280
446
 
@@ -287,280 +453,292 @@ HiSecure.getInstance({
287
453
  });
288
454
  </code></pre>
289
455
 
290
- <h3>3.2 Global Security Middleware</h3>
456
+ <hr/>
291
457
 
292
- <pre><code>app.use(HiSecure.middleware({
293
- cors: true,
294
- rateLimit: "strict",
295
- sanitize: true,
296
- headers: true,
297
- compression: true,
298
- json: true
299
- }));
300
- </code></pre>
458
+ <h2>Final Authentication Setup</h2>
459
+
460
+ <hr/>
461
+
462
+ <h2>🔐 Final Authentication Setup</h2>
463
+
464
+ <p>
465
+ This section demonstrates a complete, production-ready authentication setup using HiSecure.
466
+ It covers signup, JWT login, Google login, role-based access control, and proper initialization.
467
+ </p>
301
468
 
302
- <br/>
303
- <hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
469
+ <h3>Features Covered</h3>
470
+ <ul>
471
+ <li>Signup using email and password</li>
472
+ <li>Login using email and password (JWT-based)</li>
473
+ <li>Login with Google (ID token verification)</li>
474
+ <li>Role-based protected routes</li>
475
+ <li>Optional authentication support</li>
476
+ <li>Correct HiSecure bootstrap with reset rules</li>
477
+ </ul>
304
478
 
305
- <h2>📘 Part 4 — Full Example Snapshot</h2>
479
+ <hr/>
306
480
 
307
- <p>This gives developers a quick glance at how the entire system fits together.</p>
481
+ <h3>Application Bootstrap (server.js / app.js)</h3>
308
482
 
309
- <pre><code>// server.js
310
- require("dotenv").config();
311
- const express = require("express");
312
- const dbConnect = require("./config/db");
313
- const { HiSecure } = require("hi-secure");
483
+ <pre><code>import express from "express";
484
+ import dotenv from "dotenv";
485
+ import { HiSecure } from "hi-secure";
486
+ import authRoutes from "./routes/auth.routes.js";
314
487
 
315
- const app = express();
316
- const PORT = process.env.PORT || 3000;
488
+ dotenv.config();
317
489
 
318
- dbConnect();
490
+ const app = express();
319
491
 
320
- // ⭐ FORCE NEW INSTANCE WITH CORRECT CONFIG - if use HiSecure.jwt()
321
492
  HiSecure.resetInstance();
322
493
 
323
494
  HiSecure.getInstance({
324
- auth: {
325
- enabled: true,
326
- jwtSecret: process.env.JWT_SECRET || "supersecret123",
327
- jwtExpiresIn: "1d",
328
- }
495
+ auth: {
496
+ enabled: true,
497
+ jwtSecret: process.env.JWT_SECRET || "supersecret_32_chars_minimum",
498
+ jwtExpiresIn: "1d",
499
+ googleClientId: process.env.GOOGLE_CLIENT_ID
500
+ }
329
501
  });
330
502
 
331
- // if u don't use our jwt config
332
- app.use(HiSecure.middleware('api')); // one line setup - along with this u use the HiSecure.validat() and HiSecure.hash() | HiSecure.verify()
333
-
334
- // Global middleware WITHOUT auth override
335
- app.use(
336
- HiSecure.middleware({
337
- cors: true,
338
- rateLimit: "strict",
339
- sanitize: true,
340
- headers: true,
341
- compression: true,
342
- json: true
343
- })
344
- );
503
+ app.use(HiSecure.middleware("api"));
345
504
 
346
- // ROUTES (call builder)
347
- const userRoutes = require("./routes/UserRoutes");
348
- app.use("/api/auth", userRoutes());
505
+ app.use("/auth", authRoutes);
349
506
 
350
- app.listen(PORT, () => {
351
- console.log(`🚀 Server running port ${PORT}`);
352
- });
353
-
507
+ app.listen(3000);
508
+ </code></pre>
509
+
510
+ <p>
511
+ <em>Note:</em> <code>resetInstance()</code> is recommended only for tests or starter templates.
512
+ It should not be used repeatedly in production runtime.
513
+ </p>
514
+
515
+ <hr/>
516
+
517
+ <h3>Authentication Routes</h3>
518
+
519
+ <pre><code>import { Router } from "express";
520
+ import {
521
+ signup,
522
+ loginWithJwt,
523
+ loginWithGoogle
524
+ } from "../controllers/auth.controller.js";
525
+ import { HiSecure } from "hi-secure";
526
+
527
+ const router = Router();
528
+
529
+ router.post("/signup", signup);
530
+ router.post("/login", loginWithJwt);
531
+ router.post("/google", loginWithGoogle);
532
+
533
+ router.get(
534
+ "/me",
535
+ HiSecure.auth(),
536
+ (req, res) => res.json({ user: req.user })
537
+ );
538
+
539
+ export default router;
354
540
  </code></pre>
355
541
 
542
+ <hr/>
356
543
 
357
- <pre><code>// controller
358
- const { HiSecure } = require('hi-secure');
359
- const User = require("../models/User");
544
+ <h3>Authentication Controllers</h3>
360
545
 
361
- const JWT_OPTIONS = {
362
- issuer: 'hi-secure-backend',
363
- audience: ['web-app', 'mobile-app'], // Array format
364
- expiresIn: '7d',
365
- subject: 'user-authentication'
366
- };
546
+ <h4>Signup (Email and Password)</h4>
547
+
548
+ <pre><code>import { HiSecure } from "hi-secure";
549
+ import { HttpError } from "../core/errors/HttpError.js";
550
+ import User from "../models/User.js";
551
+
552
+ export const signup = async (req, res, next) => {
553
+ try {
554
+ const { email, password, name } = req.body;
367
555
 
368
- exports.registerUser = async(req, res) => {
369
- try {
370
- const { name, email, password } = req.body;
371
-
372
- // Check if user exists
373
- const existingUser = await User.findOne({ email });
374
- if (existingUser) {
375
- return res.status(400).json({
376
- error: 'User already exists'
377
- });
378
- }
379
-
380
- // Hash password
381
- const hashedPassword = await HiSecure.hash(password);
382
-
383
- // Create user
384
- const user = await User.create({
385
- name,
386
- email,
387
- password: hashedPassword
388
- });
389
-
390
- // FIXED: JWT sign with ALL required options
391
- const token = HiSecure.jwt.sign({
392
- userId: user._id.toString(),
393
- email: user.email,
394
- name: user.name,
395
- role: 'user'
396
- },
397
- JWT_OPTIONS
398
- );
399
-
400
- res.status(201).json({
401
- message: 'User registered successfully',
402
- token,
403
- user: {
404
- id: user._id,
405
- name: user.name,
406
- email: user.email
407
- }
408
- });
409
-
410
- } catch (error) {
411
- console.error('Registration error:', error);
412
- res.status(500).json({
413
- error: 'Registration failed',
414
- details: error.message
415
- });
556
+ if (!email || !password) {
557
+ throw HttpError.BadRequest("Email and password required");
416
558
  }
417
- };
418
559
 
419
- exports.loginUser = async(req, res) => {
420
- try {
421
- const { email, password } = req.body;
422
-
423
- // Find user
424
- const user = await User.findOne({ email });
425
- if (!user) {
426
- return res.status(401).json({
427
- error: 'Invalid credentials'
428
- });
429
- }
430
-
431
- // Verify password
432
- const isValid = await HiSecure.verify(password, user.password);
433
- if (!isValid) {
434
- return res.status(401).json({
435
- error: 'Invalid credentials'
436
- });
437
- }
438
-
439
- // FIXED: Same JWT options
440
- const token = HiSecure.jwt.sign({
441
- userId: user._id.toString(),
442
- email: user.email,
443
- name: user.name,
444
- role: 'user'
445
- },
446
- JWT_OPTIONS
447
- );
448
-
449
- res.json({
450
- message: 'Login successful',
451
- token,
452
- user: {
453
- id: user._id,
454
- name: user.name,
455
- email: user.email
456
- }
457
- });
458
-
459
- } catch (error) {
460
- console.error('Login error:', error);
461
- res.status(500).json({
462
- error: 'Login failed',
463
- details: error.message
464
- });
560
+ const existing = await User.findOne({ email });
561
+ if (existing) {
562
+ throw HttpError.Conflict("User already exists");
465
563
  }
564
+
565
+ const passwordHash = await HiSecure.hash(password);
566
+
567
+ const user = await User.create({
568
+ email,
569
+ name,
570
+ passwordHash,
571
+ roles: ["user"],
572
+ provider: "local"
573
+ });
574
+
575
+ const token = HiSecure.jwt.sign({
576
+ userId: user.id,
577
+ roles: user.roles
578
+ });
579
+
580
+ res.status(201).json({ token, user });
581
+ } catch (err) {
582
+ next(err);
583
+ }
466
584
  };
585
+ </code></pre>
467
586
 
468
- exports.getProfile = async(req, res) => {
469
- try {
470
- // req.user is set by HiSecure.auth() middleware
471
- const user = await User.findById(req.user.userId).select('-password');
472
-
473
- if (!user) {
474
- return res.status(404).json({
475
- error: 'User not found'
476
- });
477
- }
478
-
479
- res.json({
480
- message: 'Profile data',
481
- user
482
- });
483
- } catch (error) {
484
- console.error('Profile error:', error);
485
- res.status(500).json({
486
- error: 'Failed to fetch profile',
487
- details: error.message
488
- });
587
+ <hr/>
588
+
589
+ <h4>Login (Email and Password)</h4>
590
+
591
+ <pre><code>export const loginWithJwt = async (req, res, next) => {
592
+ try {
593
+ const { email, password } = req.body;
594
+
595
+ const user = await User.findOne({ email });
596
+ if (!user || !user.passwordHash) {
597
+ throw HttpError.Unauthorized("Invalid credentials");
489
598
  }
599
+
600
+ const isValid = await HiSecure.verify(password, user.passwordHash);
601
+ if (!isValid) {
602
+ throw HttpError.Unauthorized("Invalid credentials");
603
+ }
604
+
605
+ const token = HiSecure.jwt.sign({
606
+ userId: user.id,
607
+ roles: user.roles
608
+ });
609
+
610
+ res.json({ token, user });
611
+ } catch (err) {
612
+ next(err);
613
+ }
490
614
  };
491
615
  </code></pre>
492
616
 
617
+ <hr/>
493
618
 
494
- <pre><code>// routes
495
- const express = require('express');
496
- const { body } = require('express-validator');
497
- const { HiSecure } = require('hi-secure');
498
- const { registerUser, loginUser, getProfile } = require('../controllers/UserControllers');
499
-
619
+ <h4>Login with Google</h4>
500
620
 
621
+ <pre><code>export const loginWithGoogle = async (req, res, next) => {
622
+ try {
623
+ const { idToken } = req.body;
624
+ if (!idToken) {
625
+ throw HttpError.BadRequest("Google idToken required");
626
+ }
501
627
 
628
+ const googleUser = await HiSecure.jwt.google.verifyIdToken(idToken);
502
629
 
503
- module.exports = function buildRoutes() {
504
- const router = express.Router();
630
+ if (!googleUser.email_verified) {
631
+ throw HttpError.Unauthorized("Google email not verified");
632
+ }
505
633
 
506
- router.post(
507
- '/register',
634
+ let user = await User.findOne({ email: googleUser.email });
508
635
 
509
- HiSecure.validate([
510
- body("name")
511
- .notEmpty().withMessage("Name is required")
512
- .isLength({ min: 3 }).withMessage("Name must be at least 3 characters"),
636
+ if (!user) {
637
+ user = await User.create({
638
+ email: googleUser.email,
639
+ name: googleUser.name,
640
+ provider: "google",
641
+ providerId: googleUser.sub,
642
+ roles: ["user"]
643
+ });
644
+ }
513
645
 
514
- body("email")
515
- .notEmpty().withMessage("Email is required")
516
- .isEmail().withMessage("Invalid email format"),
646
+ const token = HiSecure.jwt.sign({
647
+ userId: user.id,
648
+ roles: user.roles
649
+ });
517
650
 
518
- body("password")
519
- .notEmpty().withMessage("Password is required")
520
- .isLength({ min: 6 }).withMessage("Password must be at least 6 characters"),
521
- ]),
651
+ res.json({ token, user });
652
+ } catch (err) {
653
+ next(err);
654
+ }
655
+ };
656
+ </code></pre>
522
657
 
523
- registerUser
524
- );
658
+ <hr/>
525
659
 
526
-
527
- router.post(
528
- '/login',
660
+ <h3>Role-Based Protected Routes</h3>
529
661
 
530
- HiSecure.validate([
531
- body("email")
532
- .notEmpty().withMessage("Email is required")
533
- .isEmail().withMessage("Invalid email format"),
662
+ <pre><code>app.get(
663
+ "/admin",
664
+ HiSecure.auth({ roles: ["admin"] }),
665
+ (req, res) => {
666
+ res.json({ message: "Welcome Admin" });
667
+ }
668
+ );
669
+ </code></pre>
534
670
 
535
- body("password")
536
- .notEmpty().withMessage("Password is required")
537
- ]),
671
+ <hr/>
538
672
 
539
- // Apply rate limiter also
540
- HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 }),
673
+ <h3>JWT Options (Optional)</h3>
541
674
 
542
- loginUser
543
- );
675
+ <p>
676
+ HiSecure does not require JWT options for most use cases.
677
+ Default configuration provided during initialization is sufficient.
678
+ </p>
544
679
 
680
+ <pre><code>HiSecure.getInstance({
681
+ auth: {
682
+ enabled: true,
683
+ jwtSecret: process.env.JWT_SECRET,
684
+ jwtExpiresIn: "1d"
685
+ }
686
+ });
687
+ </code></pre>
545
688
 
546
- router.get(
547
- '/profile',
548
- HiSecure.auth({ required: true }),
549
- getProfile
550
- );
689
+ <p>
690
+ Advanced JWT options can be provided only when needed:
691
+ </p>
551
692
 
552
- return router;
553
- };
693
+ <pre><code>HiSecure.jwt.sign(
694
+ {
695
+ userId: user.id,
696
+ roles: user.roles
697
+ },
698
+ {
699
+ issuer: "my-app",
700
+ audience: ["web", "mobile"],
701
+ subject: "user-auth",
702
+ expiresIn: "7d"
703
+ }
704
+ );
554
705
  </code></pre>
555
706
 
556
- <br/>
557
- <hr style="border:0; border-top:2px dashed #d4d4d8; margin:32px 0"/>
707
+ <p>
708
+ JWT options are optional and intended for advanced authentication scenarios.
709
+ </p>
710
+
711
+ <hr/>
558
712
 
559
- <h2 align="center">📝 Additional Documentation</h2>
713
+ <h3>Rules to Remember</h3>
714
+
715
+ <ul>
716
+ <li>Initialize HiSecure once during application startup</li>
717
+ <li>Use resetInstance only for tests or starter templates</li>
718
+ <li>Do not initialize HiSecure inside controllers</li>
719
+ <li>Google login is used for identity verification only</li>
720
+ <li>Authorization is enforced using JWT payload and roles</li>
721
+ </ul>
722
+
723
+ <hr/>
724
+
725
+
726
+ <h2>Summary</h2>
727
+
728
+ <p>
729
+ HiSecure provides a complete, opinionated security layer for Express.
730
+ It focuses on correctness, safety and developer productivity.
731
+ </p>
560
732
 
561
733
  <p align="center">
562
- We are actively working on extended documentation:<br/>
563
- <strong>Advanced patterns, RBAC examples, custom adapters, deployment setups & best practices.</strong>
734
+ <strong>One dependency. One middleware. Complete security.</strong>
564
735
  </p>
565
736
 
566
- <p align="center"><i>Updates coming soon.</i></p>
737
+ <hr/>
738
+
739
+ <h2 align="center">Additional Documentation</h2>
740
+
741
+ <p align="center">
742
+ Advanced patterns, RBAC strategies, adapter extensions and deployment guides
743
+ will be added over time.
744
+ </p>