hi-secure 1.0.0 β 1.0.2
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/package.json +2 -2
- package/readme.md +230 -0
- package/src/adapters/ExpressRLAdapter.ts +0 -38
package/package.json
CHANGED
package/readme.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
<h1 align="center">π HiSecure</h1>
|
|
2
|
+
<p align="center"><strong>One-line security for Express.js applications</strong></p>
|
|
3
|
+
|
|
4
|
+
<p align="center">
|
|
5
|
+
HiSecure is an all-in-one security framework for Express.js.<br/>
|
|
6
|
+
It bundles hashing, authentication, validation, sanitization, rate-limiting, logging, and security headers β
|
|
7
|
+
all through a <strong>single middleware line</strong>.
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<br/>
|
|
11
|
+
|
|
12
|
+
<!-- π FEATURE SECTION -->
|
|
13
|
+
<div style="border-left:5px solid #6366F1; padding:20px; border-radius:8px; background:#fafafa;">
|
|
14
|
+
|
|
15
|
+
<h2>β¨ Features</h2>
|
|
16
|
+
|
|
17
|
+
<h3 style="color:#10B981;">π Password Security</h3>
|
|
18
|
+
<ul>
|
|
19
|
+
<li><strong>Argon2</strong> β Industry-leading hashing</li>
|
|
20
|
+
<li><strong>Bcrypt fallback</strong> β Auto-fallback system</li>
|
|
21
|
+
<li>Simple hash + verify utilities</li>
|
|
22
|
+
</ul>
|
|
23
|
+
|
|
24
|
+
<h3 style="color:#3B82F6;">π Authentication</h3>
|
|
25
|
+
<ul>
|
|
26
|
+
<li><strong>JWT Authentication</strong> (issuer, audience, expiry)</li>
|
|
27
|
+
<li><strong>Google OAuth</strong> integration</li>
|
|
28
|
+
<li><strong>Route protection middleware</strong></li>
|
|
29
|
+
</ul>
|
|
30
|
+
|
|
31
|
+
<h3 style="color:#F59E0B;">β±οΈ Rate Limiting</h3>
|
|
32
|
+
<ul>
|
|
33
|
+
<li><strong>express-rate-limit</strong> β (Primary)</li>
|
|
34
|
+
<li><strong>rate-limiter-flexible</strong> β (Fallback)</li>
|
|
35
|
+
<li>Modes:
|
|
36
|
+
<ul>
|
|
37
|
+
<li>π <strong>Strict</strong>: 5 req / 10 sec</li>
|
|
38
|
+
<li>π‘ <strong>Relaxed</strong>: 100 req / 15 min</li>
|
|
39
|
+
<li>βοΈ <strong>API</strong>: Custom config</li>
|
|
40
|
+
</ul>
|
|
41
|
+
</li>
|
|
42
|
+
</ul>
|
|
43
|
+
|
|
44
|
+
<h3 style="color:#EC4899;">π§Ό Input Sanitization</h3>
|
|
45
|
+
<ul>
|
|
46
|
+
<li><strong>sanitize-html</strong> β HTML sanitization</li>
|
|
47
|
+
<li><strong>xss</strong> β Fallback for XSS</li>
|
|
48
|
+
<li>Auto-cleans request body, query & params</li>
|
|
49
|
+
</ul>
|
|
50
|
+
|
|
51
|
+
<h3 style="color:#8B5CF6;">π‘οΈ Additional Security Layers</h3>
|
|
52
|
+
<ul>
|
|
53
|
+
<li>CORS β’ Helmet β’ HPP</li>
|
|
54
|
+
<li>Secure JSON parsing</li>
|
|
55
|
+
<li>Query parser hardening</li>
|
|
56
|
+
<li>Gzip compression</li>
|
|
57
|
+
<li>Structured logging</li>
|
|
58
|
+
</ul>
|
|
59
|
+
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<br/>
|
|
63
|
+
|
|
64
|
+
<!-- π QUICK START SECTION -->
|
|
65
|
+
<div style="border-left:5px solid #10B981; padding:20px; border-radius:8px; background:#fafafa;">
|
|
66
|
+
|
|
67
|
+
<h2>π Quick Start</h2>
|
|
68
|
+
|
|
69
|
+
<h3>π¦ Installation</h3>
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm install hi-secure
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
<h3>π₯ Basic Setup</h3>
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
import express from "express";
|
|
79
|
+
import { HiSecure } from "hi-secure";
|
|
80
|
+
|
|
81
|
+
const app = express();
|
|
82
|
+
|
|
83
|
+
app.use(
|
|
84
|
+
HiSecure.middleware('api')
|
|
85
|
+
// { cors: true, rateLimit: "relaxed", sanitize: true }
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
app.listen(3000, () => console.log("Server running"));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
</div> <br/> <!-- π JWT SECTION --> <div style="border-left:5px solid #3B82F6; padding:20px; border-radius:8px; background:#fafafa;">
|
|
93
|
+
<h2>π JWT Authentication Setup</h2> <h3 style="color:#3B82F6;">π¦ Initialize JWT</h3>
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
|
|
97
|
+
require("dotenv").config();
|
|
98
|
+
import { HiSecure } from "hi-secure";
|
|
99
|
+
|
|
100
|
+
HiSecure.getInstance({
|
|
101
|
+
auth: {
|
|
102
|
+
enabled: true,
|
|
103
|
+
jwtSecret: process.env.JWT_SECRET || "dev_secret_12345",
|
|
104
|
+
jwtExpiresIn: "7d",
|
|
105
|
+
jwtIssuer: "hi-secure-backend",
|
|
106
|
+
jwtAudience: "hi-secure-users",
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
import express from "express";
|
|
112
|
+
import userRoutes from "./routes/UserRoutes.js";
|
|
113
|
+
|
|
114
|
+
const app = express();
|
|
115
|
+
const PORT = 3000;
|
|
116
|
+
|
|
117
|
+
app.use(HiSecure.middleware("api"));
|
|
118
|
+
|
|
119
|
+
app.use(
|
|
120
|
+
HiSecure.middleware({
|
|
121
|
+
compression: true,
|
|
122
|
+
json: true,
|
|
123
|
+
sanitize: true,
|
|
124
|
+
validate: true,
|
|
125
|
+
headers: true,
|
|
126
|
+
})
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
app.use("/api/auth", userRoutes);
|
|
130
|
+
|
|
131
|
+
app.listen(PORT, () => console.log(`Running on http://localhost:${PORT}`));
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
</div> <br/> <!-- π§© FULL AUTH SECTION --> <div style="border-left:5px solid #F43F5E; padding:20px; border-radius:8px; background:#fafafa;">
|
|
137
|
+
|
|
138
|
+
<h2>π§© Full Authentication Example</h2>
|
|
139
|
+
|
|
140
|
+
<h3 style="color:#F43F5E;">π Register User</h3>
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
|
|
144
|
+
import { HiSecure } from "hi-secure";
|
|
145
|
+
import User from "../models/User.js";
|
|
146
|
+
|
|
147
|
+
export const registerUser = async (req, res) => {
|
|
148
|
+
const { name, email, password } = req.body;
|
|
149
|
+
|
|
150
|
+
const exists = await User.findOne({ email });
|
|
151
|
+
if (exists) return res.status(400).json({ error: "User exists" });
|
|
152
|
+
|
|
153
|
+
const hashed = await HiSecure.hash(password);
|
|
154
|
+
|
|
155
|
+
const user = await User.create({ name, email, password: hashed });
|
|
156
|
+
|
|
157
|
+
const token = HiSecure.jwt.sign({ userId: user._id }, { expiresIn: "7d" });
|
|
158
|
+
|
|
159
|
+
res.json({ message: "Registered", token });
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
<h3 style="color:#F43F5E;">π Login User</h3>
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
export const loginUser = async (req, res) => {
|
|
168
|
+
const { email, password } = req.body;
|
|
169
|
+
|
|
170
|
+
const user = await User.findOne({ email });
|
|
171
|
+
if (!user) return res.status(401).json({ error: "Invalid credentials" });
|
|
172
|
+
|
|
173
|
+
const valid = await HiSecure.verify(password, user.password);
|
|
174
|
+
if (!valid) return res.status(401).json({ error: "Invalid credentials" });
|
|
175
|
+
|
|
176
|
+
const token = HiSecure.jwt.sign({ userId: user._id }, { expiresIn: "7d" });
|
|
177
|
+
|
|
178
|
+
res.json({ message: "Login successful", token });
|
|
179
|
+
};
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
<h3 style="color:#F43F5E;">π€ Protected Profile Route</h3>
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
export const getProfile = async (req, res) => {
|
|
186
|
+
const user = await User.findById(req.user.userId).select("-password");
|
|
187
|
+
if (!user) return res.status(404).json({ error: "Not found" });
|
|
188
|
+
|
|
189
|
+
res.json({ user });
|
|
190
|
+
};
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
</div> <br/> <!-- ROUTES --> <div style="border-left:5px solid #F59E0B; padding:20px; border-radius:8px; background:#fafafa;">
|
|
194
|
+
<h2>π Routes Example</h2>
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
|
|
198
|
+
import express from "express";
|
|
199
|
+
import { HiSecure } from "hi-secure";
|
|
200
|
+
import {
|
|
201
|
+
registerUser,
|
|
202
|
+
loginUser,
|
|
203
|
+
getProfile,
|
|
204
|
+
} from "../controllers/UserControllers.js";
|
|
205
|
+
|
|
206
|
+
const router = express.Router();
|
|
207
|
+
|
|
208
|
+
router.post("/register", registerUser);
|
|
209
|
+
|
|
210
|
+
router.post(
|
|
211
|
+
"/login",
|
|
212
|
+
HiSecure.rateLimit({ max: 5, windowMs: 15 * 60 * 1000 }),
|
|
213
|
+
loginUser
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
router.get("/profile", HiSecure.auth({ required: true }), getProfile);
|
|
217
|
+
|
|
218
|
+
export default router;
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
</div> <br/> <h2 align="center">π οΈ More features & docs coming soonβ¦</h2>
|
|
223
|
+
<h3 align="center">Made with π for secure Node.js apps</h3>
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
@@ -1,41 +1,3 @@
|
|
|
1
|
-
// import rateLimit from "express-rate-limit";
|
|
2
|
-
// import { logger } from "../logging";
|
|
3
|
-
// import { AdapterError } from "../core/errors/AdapterError";
|
|
4
|
-
|
|
5
|
-
// export class ExpressRLAdapter {
|
|
6
|
-
|
|
7
|
-
// /**
|
|
8
|
-
// * Create express rate-limit middleware dynamically
|
|
9
|
-
// */
|
|
10
|
-
// getMiddleware(options: {
|
|
11
|
-
// windowMs?: number;
|
|
12
|
-
// max?: number;
|
|
13
|
-
// message?: any;
|
|
14
|
-
// } = {}) {
|
|
15
|
-
|
|
16
|
-
// try {
|
|
17
|
-
// const limiter = rateLimit({
|
|
18
|
-
// windowMs: options.windowMs ?? 15 * 60 * 1000, // default
|
|
19
|
-
// max: options.max ?? 100,
|
|
20
|
-
// message: options.message ?? { error: "Too many requests" },
|
|
21
|
-
// standardHeaders: true,
|
|
22
|
-
// legacyHeaders: false,
|
|
23
|
-
// });
|
|
24
|
-
|
|
25
|
-
// return limiter;
|
|
26
|
-
|
|
27
|
-
// } catch (err: any) {
|
|
28
|
-
// logger.error("β ExpressRLAdapter: failed to create limiter", {
|
|
29
|
-
// error: err?.message || err
|
|
30
|
-
// });
|
|
31
|
-
// throw new AdapterError("Express rate limiter creation failed.");
|
|
32
|
-
// }
|
|
33
|
-
// }
|
|
34
|
-
// }
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
1
|
// src/adapters/ExpressRLAdapter.ts - IMPROVED
|
|
40
2
|
import rateLimit from "express-rate-limit";
|
|
41
3
|
import { logger } from "../logging/index.js";
|