create-authenik8-app 2.0.0 → 2.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/LICENSE +22 -0
- package/README.md +184 -0
- package/dist/bin/index.js +222 -37
- package/dist/bin/index.js.map +1 -1
- package/package.json +2 -2
- package/templates/express-auth/package.json +4 -1
- package/templates/express-auth/src/.env +9 -0
- package/templates/express-auth/src/app.ts +14 -0
- package/templates/express-auth/src/controllers/auth.controller.ts +43 -0
- package/templates/express-auth/src/routes/auth.routes.ts +13 -0
- package/templates/express-auth/src/routes/protected.routes.ts +11 -0
- package/templates/express-auth/src/server.ts +23 -64
- package/templates/express-auth/src/services/auth.services.ts +28 -0
- package/templates/express-auth+/ecosystem.config.ts +15 -0
- package/templates/express-auth+/package.json +27 -0
- package/templates/express-auth+/src/.env +9 -0
- package/templates/express-auth+/src/auth/auth.ts +37 -0
- package/templates/express-auth+/src/auth/oauth.routes.ts +43 -0
- package/templates/express-auth+/src/auth/password.route.ts +43 -0
- package/templates/express-auth+/src/auth/protected.routes.ts +11 -0
- package/templates/express-auth+/src/prisma/client.ts +15 -0
- package/templates/express-auth+/src/server.ts +38 -0
- package/templates/express-auth+/src/utils/hash.ts +12 -0
- package/templates/express-auth+/tsconfig.json +16 -0
- package/templates/express-base/app.ts +15 -0
- package/templates/express-base/controllers/base.controller.ts +32 -0
- package/templates/express-base/ecosystem.config.ts +15 -0
- package/templates/express-base/package.json +4 -1
- package/templates/express-base/routes/base.routes.ts +16 -0
- package/templates/express-base/src/server.ts +21 -41
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 TheSBD
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
|
+
<<<<<<< HEAD
|
|
2
|
+
<<<<<<< HEAD
|
|
1
3
|
|
|
2
4
|
|
|
5
|
+
=======
|
|
6
|
+
Good catch — then your README should reflect that. Don’t undersell what you already built.
|
|
7
|
+
|
|
8
|
+
Let’s fix it properly.
|
|
9
|
+
>>>>>>> 5471da4 (Update file README.md)
|
|
10
|
+
|
|
3
11
|
|
|
4
12
|
---
|
|
5
13
|
|
|
14
|
+
<<<<<<< HEAD
|
|
15
|
+
=======
|
|
16
|
+
✅ Updated npm README (with RBAC included)
|
|
17
|
+
|
|
18
|
+
Replace your README with this version:
|
|
19
|
+
|
|
20
|
+
>>>>>>> 5471da4 (Update file README.md)
|
|
6
21
|
# create-authenik8-app
|
|
7
22
|
|
|
8
23
|
<p align="center">
|
|
9
24
|
<b>Scaffold secure Express authentication APIs in seconds</b>
|
|
10
25
|
</p>
|
|
26
|
+
<<<<<<< HEAD
|
|
11
27
|
|
|
12
28
|
<p align="center">
|
|
13
29
|
JWT • Refresh Tokens • Redis • RBAC • TypeScript • Express
|
|
@@ -171,3 +187,171 @@ Production presets
|
|
|
171
187
|
|
|
172
188
|
|
|
173
189
|
---
|
|
190
|
+
# Create-authenik8-app
|
|
191
|
+
=======
|
|
192
|
+
# create-authenik8-app
|
|
193
|
+
>>>>>>> 01efb21 (Update file README.md)
|
|
194
|
+
|
|
195
|
+
<p align="center">
|
|
196
|
+
<b>Scaffold secure Express authentication APIs in seconds</b>
|
|
197
|
+
</p>
|
|
198
|
+
=======
|
|
199
|
+
>>>>>>> 5471da4 (Update file README.md)
|
|
200
|
+
|
|
201
|
+
<p align="center">
|
|
202
|
+
JWT • Refresh Tokens • Redis • RBAC • TypeScript • Express
|
|
203
|
+
</p>
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Usage
|
|
208
|
+
|
|
209
|
+
Create a new project:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npx create-authenik8-app my-app
|
|
213
|
+
|
|
214
|
+
Then:
|
|
215
|
+
|
|
216
|
+
cd my-app
|
|
217
|
+
npm install
|
|
218
|
+
npm run dev
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## What you get instantly
|
|
224
|
+
|
|
225
|
+
A fully working Express authentication starter with:
|
|
226
|
+
|
|
227
|
+
JWT authentication (access + refresh tokens)
|
|
228
|
+
|
|
229
|
+
Secure refresh token rotation
|
|
230
|
+
|
|
231
|
+
Redis-based token storage
|
|
232
|
+
|
|
233
|
+
Role-Based Access Control (RBAC)
|
|
234
|
+
|
|
235
|
+
TypeScript setup
|
|
236
|
+
|
|
237
|
+
Express server preconfigured
|
|
238
|
+
|
|
239
|
+
Clean scalable folder structure
|
|
240
|
+
|
|
241
|
+
.env file generated automatically
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
🧠 Why Authenik8?
|
|
248
|
+
|
|
249
|
+
Authentication systems usually require:
|
|
250
|
+
|
|
251
|
+
manual JWT setup
|
|
252
|
+
|
|
253
|
+
refresh token handling
|
|
254
|
+
|
|
255
|
+
Redis/session configuration
|
|
256
|
+
|
|
257
|
+
access control logic
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
Authenik8 provides all of this out of the box so you can start building your API immediately.
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
Requirements
|
|
266
|
+
|
|
267
|
+
Node.js 18+
|
|
268
|
+
|
|
269
|
+
Redis (required for refresh tokens)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
Redis Setup
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Local
|
|
279
|
+
|
|
280
|
+
redis-server
|
|
281
|
+
|
|
282
|
+
Docker
|
|
283
|
+
|
|
284
|
+
docker run -p 6379:6379 redis
|
|
285
|
+
```
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
Environment Variables
|
|
289
|
+
|
|
290
|
+
Generated automatically:
|
|
291
|
+
```
|
|
292
|
+
JWT_SECRET=your-secret
|
|
293
|
+
REFRESH_SECRET=your-refresh-secret
|
|
294
|
+
|
|
295
|
+
REDIS_HOST=127.0.0.1
|
|
296
|
+
REDIS_PORT=6379
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
RBAC Example
|
|
302
|
+
|
|
303
|
+
Example of a protected route:
|
|
304
|
+
```
|
|
305
|
+
app.get("/admin", auth.requireAdmin, (req, res) => {
|
|
306
|
+
res.json({ message: "Admin only route" });
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
📦 Powered by
|
|
313
|
+
|
|
314
|
+
authenik8-core
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
📁 Project Structure
|
|
321
|
+
|
|
322
|
+
my-app/
|
|
323
|
+
├── src/
|
|
324
|
+
│ ├
|
|
325
|
+
│ ├
|
|
326
|
+
│ └── server.ts
|
|
327
|
+
├── .env
|
|
328
|
+
├── package.json
|
|
329
|
+
└── tsconfig.json
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
📌 Notes
|
|
335
|
+
|
|
336
|
+
Redis is required for refresh token handling
|
|
337
|
+
|
|
338
|
+
This CLI generates a starter project, not a full framework
|
|
339
|
+
|
|
340
|
+
RBAC is included via middleware (e.g. requireAdmin)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
🧱 Roadmap
|
|
347
|
+
|
|
348
|
+
OAuth providers (Google, GitHub)
|
|
349
|
+
|
|
350
|
+
Advanced RBAC (custom roles/permissions)
|
|
351
|
+
|
|
352
|
+
Docker templates
|
|
353
|
+
|
|
354
|
+
Admin dashboard
|
|
355
|
+
|
|
356
|
+
Production presets
|
|
357
|
+
|
package/dist/bin/index.js
CHANGED
|
@@ -14,10 +14,106 @@ if (!projectName) {
|
|
|
14
14
|
console.log(chalk.red("❌ Please provide a project name"));
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
|
+
const isProduction = process.argv.includes("--production-ready");
|
|
17
18
|
const targetDir = path.join(process.cwd(), projectName);
|
|
18
19
|
let projectCreated = false;
|
|
20
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
21
|
+
const cleanLogo = `
|
|
22
|
+
|
|
23
|
+
█████╗ █████╗
|
|
24
|
+
██╔══██╗ ██╔══██╗
|
|
25
|
+
███████║ ╚█████╔╝
|
|
26
|
+
██╔══██║ ██╔══██╗
|
|
27
|
+
██║ ██║ ╚█████╔╝
|
|
28
|
+
╚═╝ ╚═╝ ╚════╝
|
|
29
|
+
|
|
30
|
+
A8
|
|
31
|
+
Authenik8 CLI
|
|
32
|
+
Build Faster
|
|
33
|
+
More , Secure
|
|
34
|
+
`;
|
|
35
|
+
const glitchFrames = [
|
|
36
|
+
`
|
|
37
|
+
█████╗ █████╗
|
|
38
|
+
██╔══██╗ ██▒▒▒▒██
|
|
39
|
+
███████║ ╚█████╔╝
|
|
40
|
+
██╔══██║ ██▒▒▒▒██
|
|
41
|
+
██║ ██║ ╚█████╔╝
|
|
42
|
+
╚═╝ ╚═╝ ╚════╝
|
|
43
|
+
|
|
44
|
+
A8
|
|
45
|
+
Authenik8 CLI
|
|
46
|
+
|
|
47
|
+
More
|
|
48
|
+
`,
|
|
49
|
+
`
|
|
50
|
+
██▓▓██╗ ██▓▓██╗
|
|
51
|
+
██▒▒██╔╝ ██▒▒██╔╝
|
|
52
|
+
██▒▒▒▒██ ╚█████╔╝
|
|
53
|
+
██▓▓██╔╝ ██▒▒██╗
|
|
54
|
+
██▒▒██║ ╚█████╔╝
|
|
55
|
+
╚═════╝ ╚════╝
|
|
56
|
+
|
|
57
|
+
A8
|
|
58
|
+
Authenik8 CLI
|
|
59
|
+
Faster
|
|
60
|
+
`,
|
|
61
|
+
`
|
|
62
|
+
██▒▒██╗ ██▒▒██╗
|
|
63
|
+
██▓▓██╔╝ ██▓▓██╔╝
|
|
64
|
+
██▒▒▒▒██ ╚█████╔╝
|
|
65
|
+
██▓▓██╔╝ ██▓▓██╗
|
|
66
|
+
██▒▒██║ ╚█████╔╝
|
|
67
|
+
╚═════╝ ╚════╝
|
|
68
|
+
|
|
69
|
+
A8
|
|
70
|
+
Authenik8 CLI
|
|
71
|
+
Build
|
|
72
|
+
`,
|
|
73
|
+
`
|
|
74
|
+
██▓▓██╗ ██▓▓██╗
|
|
75
|
+
██▒▒██╔╝ ██▒▒██╔╝
|
|
76
|
+
██▒▒▒▒██ ╚█████╔╝
|
|
77
|
+
██▓▓██╔╝ ██▒▒██╗
|
|
78
|
+
██▒▒██║ ╚█████╔╝
|
|
79
|
+
╚═════╝ ╚════╝
|
|
80
|
+
|
|
81
|
+
A8
|
|
82
|
+
Authenik8 CLI
|
|
83
|
+
|
|
84
|
+
`
|
|
85
|
+
];
|
|
86
|
+
async function showBootLogo() {
|
|
87
|
+
console.clear();
|
|
88
|
+
const boot = ora("Initializing Authenik8 engine...").start();
|
|
89
|
+
// Phase 1: clean → unstable
|
|
90
|
+
console.clear();
|
|
91
|
+
console.log(chalk.cyan(cleanLogo));
|
|
92
|
+
await sleep(200);
|
|
93
|
+
// Phase 2: glitch burst (irregular feel)
|
|
94
|
+
for (let i = 0; i < 5; i++) {
|
|
95
|
+
console.clear();
|
|
96
|
+
const frame = glitchFrames[Math.floor(Math.random() * glitchFrames.length)];
|
|
97
|
+
console.log(chalk.cyan(frame));
|
|
98
|
+
await sleep(120 + Math.random() * 120);
|
|
99
|
+
}
|
|
100
|
+
// Phase 3: stabilization flicker
|
|
101
|
+
for (let i = 0; i < 2; i++) {
|
|
102
|
+
console.clear();
|
|
103
|
+
console.log(chalk.cyan(cleanLogo));
|
|
104
|
+
await sleep(180);
|
|
105
|
+
console.clear();
|
|
106
|
+
console.log(chalk.gray(cleanLogo));
|
|
107
|
+
await sleep(120);
|
|
108
|
+
}
|
|
109
|
+
// Final render
|
|
110
|
+
console.clear();
|
|
111
|
+
console.log(chalk.cyan.bold(cleanLogo));
|
|
112
|
+
await sleep(800);
|
|
113
|
+
boot.succeed("Engine ready");
|
|
114
|
+
}
|
|
19
115
|
async function main() {
|
|
20
|
-
|
|
116
|
+
await showBootLogo();
|
|
21
117
|
if (process.argv.includes("--help")) {
|
|
22
118
|
console.log(`
|
|
23
119
|
Authenik8 CLI
|
|
@@ -26,14 +122,15 @@ Usage:
|
|
|
26
122
|
create-authenik8-app <project-name>
|
|
27
123
|
|
|
28
124
|
Options:
|
|
29
|
-
--help
|
|
30
|
-
|
|
125
|
+
--help Show this help message
|
|
126
|
+
--production-ready production mode
|
|
31
127
|
Features:
|
|
32
128
|
- Express backend (default)
|
|
33
129
|
- Optional Prisma ORM
|
|
34
130
|
- PostgreSQL (production)
|
|
35
131
|
- SQLite (quick start)
|
|
36
132
|
- Optional Git initialization
|
|
133
|
+
- Optional OAuth
|
|
37
134
|
|
|
38
135
|
Examples:
|
|
39
136
|
create-authenik8-app my-app
|
|
@@ -42,18 +139,23 @@ Examples:
|
|
|
42
139
|
}
|
|
43
140
|
console.log(chalk.gray(`
|
|
44
141
|
Available options:
|
|
142
|
+
Authentication setup:
|
|
143
|
+
• base (JWT only)
|
|
144
|
+
• auth (JWT + Password/Email auth)
|
|
145
|
+
• auth-oauth(JWT+ Password/Email + oauth)
|
|
45
146
|
|
|
46
147
|
Frameworks:
|
|
47
|
-
|
|
48
|
-
|
|
148
|
+
• Express
|
|
149
|
+
• Fastify(coming soon)
|
|
49
150
|
|
|
50
151
|
Database (if Prisma enabled):
|
|
51
|
-
|
|
52
|
-
|
|
152
|
+
• PostgreSQL
|
|
153
|
+
• SQLite (quick start)
|
|
53
154
|
|
|
54
155
|
Features:
|
|
55
|
-
|
|
56
|
-
|
|
156
|
+
• Prisma ORM (optional)
|
|
157
|
+
• Git initialization (optional)
|
|
158
|
+
• OAuth + Auth
|
|
57
159
|
`));
|
|
58
160
|
// 🔥 PROMPTS
|
|
59
161
|
const answers = await inquirer.prompt([
|
|
@@ -84,14 +186,16 @@ Available options:
|
|
|
84
186
|
name: "useGit",
|
|
85
187
|
message: "Initialize git?",
|
|
86
188
|
default: true,
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
189
|
+
}, {
|
|
190
|
+
type: "list",
|
|
191
|
+
name: "authMode",
|
|
192
|
+
message: "Choose authentication setup:",
|
|
193
|
+
choices: [
|
|
194
|
+
{ name: "JWT only (no auth routes)", value: "base" },
|
|
195
|
+
{ name: "Email + Password Auth", value: "auth" },
|
|
196
|
+
{ name: "Full Auth (Password + OAuth)", value: "auth-oauth" },
|
|
197
|
+
],
|
|
198
|
+
}
|
|
95
199
|
]);
|
|
96
200
|
// 🚫 Prevent overwrite
|
|
97
201
|
if (fs.existsSync(targetDir)) {
|
|
@@ -101,9 +205,12 @@ Available options:
|
|
|
101
205
|
console.log(chalk.cyan("\n⚙️ Setting things up...\n"));
|
|
102
206
|
const templateRoot = path.resolve(__dirname, "../../templates");
|
|
103
207
|
let templateName = "express-base";
|
|
104
|
-
if (answers.
|
|
208
|
+
if (answers.authMode === "auth") {
|
|
105
209
|
templateName = "express-auth";
|
|
106
210
|
}
|
|
211
|
+
if (answers.authMode === "auth-oauth") {
|
|
212
|
+
templateName = "express-auth+";
|
|
213
|
+
}
|
|
107
214
|
const templatePath = path.join(templateRoot, templateName);
|
|
108
215
|
// 📁 Create project (SPINNER)
|
|
109
216
|
const createSpinner = ora("Creating project structure...").start();
|
|
@@ -170,7 +277,7 @@ Available options:
|
|
|
170
277
|
try {
|
|
171
278
|
execSync("npx prisma@5.22.0 generate", {
|
|
172
279
|
cwd: targetDir,
|
|
173
|
-
stdio: "
|
|
280
|
+
stdio: "ignore"
|
|
174
281
|
});
|
|
175
282
|
prismaGenSpinner.succeed("Prisma client generated");
|
|
176
283
|
}
|
|
@@ -179,18 +286,33 @@ Available options:
|
|
|
179
286
|
console.error(err);
|
|
180
287
|
}
|
|
181
288
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
289
|
+
if (isProduction) {
|
|
290
|
+
const pm2Spinner = ora("Setting up production mode (PM2)...").start();
|
|
291
|
+
try {
|
|
292
|
+
execSync("npm install pm2", {
|
|
293
|
+
cwd: targetDir,
|
|
294
|
+
stdio: "ignore",
|
|
295
|
+
});
|
|
296
|
+
pm2Spinner.succeed("PM2 installed (production-ready)");
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
pm2Spinner.fail("Failed to install PM2");
|
|
300
|
+
}
|
|
189
301
|
}
|
|
190
|
-
|
|
191
|
-
authSpinner
|
|
192
|
-
|
|
193
|
-
|
|
302
|
+
if (answers.authMode !== "base") {
|
|
303
|
+
const authSpinner = ora("Installing password auth...").start();
|
|
304
|
+
try {
|
|
305
|
+
execSync("npm install argon2", {
|
|
306
|
+
cwd: targetDir,
|
|
307
|
+
stdio: "ignore",
|
|
308
|
+
});
|
|
309
|
+
authSpinner.succeed("Password auth ready (argon2)");
|
|
310
|
+
}
|
|
311
|
+
catch (err) {
|
|
312
|
+
authSpinner.fail("Failed to install password auth");
|
|
313
|
+
console.error(err);
|
|
314
|
+
process.exit(1);
|
|
315
|
+
}
|
|
194
316
|
}
|
|
195
317
|
}
|
|
196
318
|
if (answers.useGit) {
|
|
@@ -207,20 +329,83 @@ Available options:
|
|
|
207
329
|
}
|
|
208
330
|
}
|
|
209
331
|
console.log(chalk.green.bold("\n🎉 Authenik8 app created successfully!\n"));
|
|
332
|
+
if (isProduction) {
|
|
333
|
+
fs.appendFileSync(path.join(targetDir, "README.md"), `
|
|
334
|
+
|
|
335
|
+
## 🚀 Production Mode
|
|
336
|
+
|
|
337
|
+
This project is configured for production using PM2.
|
|
338
|
+
|
|
339
|
+
### Start app in cluster mode:
|
|
340
|
+
npm run pm2:start
|
|
341
|
+
|
|
342
|
+
### View logs:
|
|
343
|
+
npm run pm2:logs
|
|
344
|
+
|
|
345
|
+
### Stop app:
|
|
346
|
+
npm run pm2:stop
|
|
347
|
+
|
|
348
|
+
`);
|
|
349
|
+
}
|
|
210
350
|
console.log(chalk.white(`
|
|
211
351
|
Next steps:
|
|
212
352
|
|
|
213
353
|
cd ${projectName}
|
|
214
|
-
|
|
354
|
+
redis-server --daemonize yes
|
|
215
355
|
npm run dev
|
|
216
356
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
357
|
+
Auth Features:
|
|
358
|
+
${answers.authMode === "base"
|
|
359
|
+
? "✓ JWT only"
|
|
360
|
+
: answers.authMode === "auth"
|
|
361
|
+
? "✓ Email + Password"
|
|
362
|
+
: "✓ Password + OAuth (Google/GitHub)"}
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
🛠 Stack:
|
|
366
|
+
✔ Express
|
|
367
|
+
✔ ${answers.usePrisma ? (answers.database.includes("postgresql") ? "PostgreSQL" : "SQLite") : "No database"}
|
|
368
|
+
✔ ${answers.usePrisma ? "Prisma ORM" : "No ORM"}
|
|
369
|
+
|
|
370
|
+
📡 Endpoints:
|
|
371
|
+
${answers.authMode === "base"
|
|
372
|
+
? `
|
|
373
|
+
GET /public
|
|
374
|
+
GET /guest
|
|
375
|
+
GET /protected
|
|
376
|
+
POST /refresh
|
|
377
|
+
`
|
|
378
|
+
: answers.authMode === "auth"
|
|
379
|
+
? `
|
|
380
|
+
POST /auth/register
|
|
381
|
+
POST /auth/login
|
|
382
|
+
POST /auth/refresh
|
|
383
|
+
GET /protected
|
|
384
|
+
`
|
|
385
|
+
: `
|
|
386
|
+
POST /auth/register
|
|
387
|
+
POST /auth/login
|
|
388
|
+
POST /auth/refresh
|
|
389
|
+
GET /auth/google
|
|
390
|
+
GET /auth/github
|
|
391
|
+
GET /protected
|
|
392
|
+
`}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
🔥 You're ready to build.
|
|
396
|
+
`));
|
|
397
|
+
if (isProduction) {
|
|
398
|
+
console.log(`
|
|
399
|
+
🚀 Production Ready Enabled:
|
|
400
|
+
|
|
401
|
+
✔ PM2 installed
|
|
402
|
+
✔ Cluster mode enabled
|
|
403
|
+
✔ Memory auto-restart (300MB)
|
|
404
|
+
|
|
405
|
+
Run:
|
|
406
|
+
npm run pm2:start
|
|
223
407
|
`);
|
|
408
|
+
}
|
|
224
409
|
}
|
|
225
410
|
process.on("SIGINT", async () => {
|
|
226
411
|
console.log("\n👋 Authenik8 setup cancelled.");
|
package/dist/bin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAG3C,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEpC,IAAI,CAAC,WAAW,EAAE,CAAC;IACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-authenik8-app",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description":"Create production-ready backend APIs in seconds. Authenik8 scaffolds Express + Prisma projects with JWT authentication, database setup (PostgreSQL or SQLite), and scalable architecture out of the box.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-authenik8-app": "dist/bin/index.js"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"author":"Karabo Seeisa",
|
|
30
30
|
"type": "module",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"authenik8-core": "^0.
|
|
32
|
+
"authenik8-core": "^1.0.3",
|
|
33
33
|
"chalk": "^5.6.2",
|
|
34
34
|
"fs-extra": "^11.3.4",
|
|
35
35
|
"inquirer": "^13.3.2",
|
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
"scripts": {
|
|
8
8
|
"dev": "ts-node-dev --respawn --transpile-only src/server.ts",
|
|
9
9
|
"build": "tsc",
|
|
10
|
+
"pm2:start": "pm2 start ecosystem.config.js",
|
|
11
|
+
"pm2:stop": "pm2 stop authenik8-app",
|
|
12
|
+
"pm2:logs": "pm2 logs",
|
|
10
13
|
"start": "node dist/server.js",
|
|
11
14
|
"prisma:generate": "prisma generate",
|
|
12
15
|
"prisma:migrate": "prisma migrate dev"
|
|
13
16
|
},
|
|
14
17
|
"dependencies": {
|
|
15
|
-
"authenik8-core": "0.
|
|
18
|
+
"authenik8-core": "^1.0.3",
|
|
16
19
|
"express": "^4.19.2"
|
|
17
20
|
},
|
|
18
21
|
"devDependencies": {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { createAuthRoutes } from "./routes/auth.routes";
|
|
3
|
+
import { createProtectedRoutes } from "./routes/protected.routes";
|
|
4
|
+
|
|
5
|
+
export const createApp = (auth: any) => {
|
|
6
|
+
const app = express();
|
|
7
|
+
|
|
8
|
+
app.use(express.json());
|
|
9
|
+
|
|
10
|
+
app.use("/auth", createAuthRoutes(auth));
|
|
11
|
+
app.use("/", createProtectedRoutes(auth));
|
|
12
|
+
|
|
13
|
+
return app;
|
|
14
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { AuthService } from "../services/auth.services";
|
|
3
|
+
|
|
4
|
+
export const createAuthController = (auth: any) => ({
|
|
5
|
+
async register(req: Request, res: Response) {
|
|
6
|
+
try {
|
|
7
|
+
const { email, password } = req.body;
|
|
8
|
+
|
|
9
|
+
const user = await AuthService.register(email, password);
|
|
10
|
+
|
|
11
|
+
res.json({ message: "User created", userId: user.id });
|
|
12
|
+
} catch (err) {
|
|
13
|
+
res.status(400).json({ error: (err as Error).message });
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
async login(req: Request, res: Response) {
|
|
18
|
+
try {
|
|
19
|
+
const { email, password } = req.body;
|
|
20
|
+
|
|
21
|
+
const user = await AuthService.login(email, password);
|
|
22
|
+
|
|
23
|
+
const accessToken = auth.signToken({
|
|
24
|
+
userId: user.id,
|
|
25
|
+
email: user.email,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const refreshToken = await auth.generateRefreshToken({
|
|
29
|
+
userId: user.id,
|
|
30
|
+
email: user.email,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
res.json({ accessToken, refreshToken });
|
|
34
|
+
} catch (err) {
|
|
35
|
+
res.status(401).json({ error: (err as Error).message });
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async refresh(req: Request, res: Response) {
|
|
40
|
+
const tokens = await auth.refreshToken(req.body.refreshToken);
|
|
41
|
+
res.json(tokens);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { createAuthController } from "../controllers/auth.controller";
|
|
3
|
+
|
|
4
|
+
export const createAuthRoutes = (auth: any) => {
|
|
5
|
+
const router = Router();
|
|
6
|
+
const controller = createAuthController(auth);
|
|
7
|
+
|
|
8
|
+
router.post("/register", controller.register);
|
|
9
|
+
router.post("/login", controller.login);
|
|
10
|
+
router.post("/refresh", controller.refresh);
|
|
11
|
+
|
|
12
|
+
return router;
|
|
13
|
+
};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
2
|
import { createAuthenik8 } from "authenik8-core";
|
|
3
|
-
import {
|
|
4
|
-
import {prisma} from "./prisma/client"
|
|
3
|
+
import { createApp } from "./app";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
app.use(express.json());
|
|
5
|
+
dotenv.config();
|
|
8
6
|
|
|
9
7
|
async function start() {
|
|
10
8
|
const auth = await createAuthenik8({
|
|
@@ -12,67 +10,28 @@ async function start() {
|
|
|
12
10
|
refreshSecret: process.env.REFRESH_SECRET!,
|
|
13
11
|
});
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
app.post("/register", async (req, res) => {
|
|
17
|
-
const { email, password } = req.body;
|
|
18
|
-
|
|
19
|
-
const hashedPassword = await hashPassword(password);
|
|
20
|
-
|
|
21
|
-
const user = await prisma.user.create({
|
|
22
|
-
data: {
|
|
23
|
-
email,
|
|
24
|
-
password: hashedPassword,
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
res.json({ message: "User created", userId: user.id });
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
app.post("/login", async (req, res) => {
|
|
33
|
-
const { email, password } = req.body;
|
|
34
|
-
|
|
35
|
-
const user = await prisma.user.findUnique({
|
|
36
|
-
where: { email },
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (!user) {
|
|
40
|
-
return res.status(401).json({ error: "Invalid credentials" });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const isValid = await comparePassword(password, user.password);
|
|
44
|
-
|
|
45
|
-
if (!isValid) {
|
|
46
|
-
return res.status(401).json({ error: "Invalid credentials" });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const accessToken = auth.signToken({
|
|
50
|
-
id: user.id,
|
|
51
|
-
email: user.email,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const refreshToken = await auth.generateRefreshToken({
|
|
55
|
-
id: user.id,
|
|
56
|
-
email: user.email,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
res.json({ accessToken, refreshToken });
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
app.post("/refresh", async (req, res) => {
|
|
64
|
-
const tokens = await auth.refreshToken(req.body.refreshToken);
|
|
65
|
-
res.json(tokens);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// ✅ PROTECTED
|
|
69
|
-
app.get("/protected", auth.requireAdmin, (req, res) => {
|
|
70
|
-
res.json({ message: "Protected route" });
|
|
71
|
-
});
|
|
13
|
+
const app = createApp(auth);
|
|
72
14
|
|
|
73
15
|
app.listen(3000, () => {
|
|
74
|
-
console.log("
|
|
16
|
+
console.log(" Server running on http://localhost:3000");
|
|
75
17
|
});
|
|
76
18
|
}
|
|
77
|
-
|
|
19
|
+
process.on("uncaughtException", (err) => {
|
|
20
|
+
console.error(" Uncaught Exception:", err);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
process.on("unhandledRejection", (err) => {
|
|
25
|
+
console.error(" Unhandled Rejection:", err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
|
|
28
|
+
});
|
|
29
|
+
setInterval(() => {
|
|
30
|
+
const used = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
31
|
+
|
|
32
|
+
if (used > 300) {
|
|
33
|
+
console.error(`Memory exceeded: ${used.toFixed(2)} MB`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}, 10000);
|
|
78
37
|
start();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { prisma } from "../prisma/client";
|
|
2
|
+
import { hashPassword, comparePassword } from "../utils/hash";
|
|
3
|
+
|
|
4
|
+
export const AuthService = {
|
|
5
|
+
async register(email: string, password: string) {
|
|
6
|
+
const hashedPassword = await hashPassword(password);
|
|
7
|
+
|
|
8
|
+
const user = await prisma.user.create({
|
|
9
|
+
data: { email, password: hashedPassword },
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
return user;
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
async login(email: string, password: string) {
|
|
16
|
+
const user = await prisma.user.findUnique({
|
|
17
|
+
where: { email },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!user) throw new Error("Invalid credentials");
|
|
21
|
+
|
|
22
|
+
const isValid = await comparePassword(password, user.password);
|
|
23
|
+
|
|
24
|
+
if (!isValid) throw new Error("Invalid credentials");
|
|
25
|
+
|
|
26
|
+
return user;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "authenik8-app",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Authenik8 generated Express auth app",
|
|
5
|
+
"main": "dist/server.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "ts-node-dev --respawn --transpile-only src/server.ts",
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"pm2:start": "pm2 start ecosystem.config.js",
|
|
11
|
+
"pm2:stop": "pm2 stop authenik8-app",
|
|
12
|
+
"pm2:logs": "pm2 logs",
|
|
13
|
+
"start": "node dist/server.js",
|
|
14
|
+
"prisma:generate": "prisma generate",
|
|
15
|
+
"prisma:migrate": "prisma migrate dev"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"authenik8-core": "^1.0.3",
|
|
19
|
+
"express": "^4.19.2"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/express": "^4.17.21",
|
|
23
|
+
"@types/node": "^20.0.0",
|
|
24
|
+
"ts-node-dev": "^2.0.0",
|
|
25
|
+
"typescript": "^5.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createAuthenik8 } from "authenik8-core";
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
let authInstance: any;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export async function initAuth() {
|
|
11
|
+
authInstance= await createAuthenik8({
|
|
12
|
+
jwtSecret: process.env.JWT_SECRET!,
|
|
13
|
+
refreshSecret: process.env.REFRESH_SECRET!,
|
|
14
|
+
|
|
15
|
+
oauth: {
|
|
16
|
+
google: {
|
|
17
|
+
clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
18
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
19
|
+
redirectUri: "http://localhost:3000/auth/google/callback",
|
|
20
|
+
},
|
|
21
|
+
github: {
|
|
22
|
+
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
23
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
24
|
+
redirectUri: "http://localhost:3000/auth/github/callback",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
export function getAuth() {
|
|
31
|
+
if (!authInstance) {
|
|
32
|
+
throw new Error("Auth not initialized. Call initAuth() first.");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return authInstance;
|
|
36
|
+
}
|
|
37
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { auth } from "./auth";
|
|
3
|
+
|
|
4
|
+
const router = express.Router();
|
|
5
|
+
|
|
6
|
+
// GOOGLE
|
|
7
|
+
router.get("/google", (req, res) => {
|
|
8
|
+
auth.oauth?.google?.redirect(req, res);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
router.get("/google/callback", async (req, res) => {
|
|
12
|
+
const result = await auth.oauth?.google?.handleCallback(req);
|
|
13
|
+
|
|
14
|
+
res.json({
|
|
15
|
+
provider: "google",
|
|
16
|
+
...result,
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// GITHUB
|
|
21
|
+
router.get("/github", (req, res) => {
|
|
22
|
+
auth.oauth?.github?.redirect(req, res);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
router.get("/github/callback", async (req, res) => {
|
|
26
|
+
const result = await auth.oauth?.github?.handleCallback(req);
|
|
27
|
+
|
|
28
|
+
res.json({
|
|
29
|
+
provider: "github",
|
|
30
|
+
...result,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
router.get("/google/link", (req, res) => {
|
|
36
|
+
auth.oauth?.google?.redirect(req, res, "link");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
router.get("/github/link", (req, res) => {
|
|
40
|
+
auth.oauth?.github?.redirect(req, res, "link");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export default router;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { auth } from "./auth";
|
|
2
|
+
import { prisma } from "../prisma/client";
|
|
3
|
+
import { hashPassword, comparePassword } from "../utils/hash";
|
|
4
|
+
import express from "express";
|
|
5
|
+
|
|
6
|
+
const router = express.Router();
|
|
7
|
+
|
|
8
|
+
router.post("/register", async (req, res) => {
|
|
9
|
+
const { email, password } = req.body;
|
|
10
|
+
|
|
11
|
+
const user = await prisma.user.create({
|
|
12
|
+
data: {
|
|
13
|
+
email,
|
|
14
|
+
password: await hashPassword(password),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
res.json({ message: "User created", userId: user.id });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
router.post("/login", async (req, res) => {
|
|
22
|
+
const { email, password } = req.body;
|
|
23
|
+
|
|
24
|
+
const user = await prisma.user.findUnique({ where: { email } });
|
|
25
|
+
|
|
26
|
+
if (!user || !(await comparePassword(password, user.password))) {
|
|
27
|
+
return res.status(401).json({ error: "Invalid credentials" });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const accessToken = auth.signToken({
|
|
31
|
+
userId: user.id,
|
|
32
|
+
email: user.email,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const refreshToken = await auth.generateRefreshToken({
|
|
36
|
+
userId: user.id,
|
|
37
|
+
email: user.email,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
res.json({ accessToken, refreshToken });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export default router;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { getAuth } from "./auth";
|
|
3
|
+
|
|
4
|
+
const router = express.Router();
|
|
5
|
+
const auth = getAuth();
|
|
6
|
+
|
|
7
|
+
router.get("/protected", auth.requireAdmin, (req, res) => {
|
|
8
|
+
res.json({ message: "Protected route" });
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PrismaClient } from "@prisma/client";
|
|
2
|
+
|
|
3
|
+
const globalForPrisma = globalThis as unknown as {
|
|
4
|
+
prisma: PrismaClient | undefined;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const prisma =
|
|
8
|
+
globalForPrisma.prisma ??
|
|
9
|
+
new PrismaClient({
|
|
10
|
+
log: ["error", "warn"],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (process.env.NODE_ENV !== "production") {
|
|
14
|
+
globalForPrisma.prisma = prisma;
|
|
15
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import passwordRoutes from "./auth/password.route";
|
|
3
|
+
import oauthRoutes from "./auth/oauth.routes";
|
|
4
|
+
import protectedRoutes from "./auth/protected.routes";
|
|
5
|
+
import { initAuth } from "./auth";
|
|
6
|
+
const app = express();
|
|
7
|
+
app.use(express.json());
|
|
8
|
+
|
|
9
|
+
app.use("/auth", passwordRoutes);
|
|
10
|
+
app.use("/auth", oauthRoutes);
|
|
11
|
+
app.use("/", protectedRoutes);
|
|
12
|
+
|
|
13
|
+
async function start(){
|
|
14
|
+
await initAuth();
|
|
15
|
+
|
|
16
|
+
app.listen(3000, () => {
|
|
17
|
+
console.log("Auth system running on http://localhost:3000");
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
start();
|
|
22
|
+
process.on("uncaughtException", (err) => {
|
|
23
|
+
console.error(" Uncaught Exception:", err);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
process.on("unhandledRejection", (err) => {
|
|
28
|
+
console.error(" Unhandled Rejection:", err);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
31
|
+
setInterval(() => {
|
|
32
|
+
const used = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
33
|
+
|
|
34
|
+
if (used > 300) {
|
|
35
|
+
console.error(` Memory exceeded: ${used.toFixed(2)} MB`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}, 10000);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import argon2 from "argon2";
|
|
2
|
+
|
|
3
|
+
export const hashPassword = async (password: string): Promise<string> => {
|
|
4
|
+
return argon2.hash(password);
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const comparePassword = async (
|
|
8
|
+
password: string,
|
|
9
|
+
hash: string
|
|
10
|
+
): Promise<boolean> => {
|
|
11
|
+
return argon2.verify(hash, password);
|
|
12
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
|
|
12
|
+
"forceConsistentCasingInFileNames": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src"],
|
|
15
|
+
"exclude": ["node_modules", "dist"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { createBaseRoutes } from "./routes/base.routes";
|
|
3
|
+
|
|
4
|
+
export const createApp = (auth: any) => {
|
|
5
|
+
const app = express();
|
|
6
|
+
|
|
7
|
+
app.use(express.json());
|
|
8
|
+
|
|
9
|
+
app.use(auth.helmet);
|
|
10
|
+
app.use(auth.rateLimit);
|
|
11
|
+
|
|
12
|
+
app.use("/", createBaseRoutes(auth));
|
|
13
|
+
|
|
14
|
+
return app;
|
|
15
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
|
|
3
|
+
export const createBaseController = (auth: any) => ({
|
|
4
|
+
publicRoute(req: Request, res: Response) {
|
|
5
|
+
res.json({ message: "Public route" });
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
async guest(req: Request, res: Response) {
|
|
9
|
+
const token = await auth.guestToken({ role: "guest" });
|
|
10
|
+
res.json({ token });
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
async protected(req: Request, res: Response) {
|
|
14
|
+
const token = req.headers.authorization?.split(" ")[1];
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const decoded = await auth.verifyToken(token);
|
|
18
|
+
res.json({ message: "Protected data", user: decoded });
|
|
19
|
+
} catch {
|
|
20
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
async refresh(req: Request, res: Response) {
|
|
25
|
+
const tokens = await auth.refreshToken(req.body.refreshToken);
|
|
26
|
+
res.json(tokens);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
admin(req: Request, res: Response) {
|
|
30
|
+
res.json({ message: "Admin only" });
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
"version": "1.0.5",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "ts-node-dev --respawn --transpile-only ./src/server.ts",
|
|
6
|
+
"pm2:start": "pm2 start ecosystem.config.js",
|
|
7
|
+
"pm2:stop": "pm2 stop authenik8-app",
|
|
8
|
+
"pm2:logs": "pm2 logs",
|
|
6
9
|
"build": "tsc",
|
|
7
10
|
"start": "node dist/server.js"
|
|
8
11
|
},
|
|
9
12
|
"dependencies": {
|
|
10
|
-
"authenik8-core": "^0.
|
|
13
|
+
"authenik8-core": "^1.0.3",
|
|
11
14
|
"dotenv": "^16.0.0",
|
|
12
15
|
"express": "^4.18.2"
|
|
13
16
|
},
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { createBaseController } from "../controllers/base.controller";
|
|
3
|
+
|
|
4
|
+
export const createBaseRoutes = (auth: any) => {
|
|
5
|
+
const router = Router();
|
|
6
|
+
const controller = createBaseController(auth);
|
|
7
|
+
|
|
8
|
+
router.get("/public", controller.publicRoute);
|
|
9
|
+
router.get("/guest", controller.guest);
|
|
10
|
+
router.get("/protected", controller.protected);
|
|
11
|
+
router.post("/refresh", controller.refresh);
|
|
12
|
+
|
|
13
|
+
router.get("/admin", auth.requireAdmin, controller.admin);
|
|
14
|
+
|
|
15
|
+
return router;
|
|
16
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
2
|
import { createAuthenik8 } from "authenik8-core";
|
|
3
|
+
import { createApp } from "../app";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
app.use(express.json());
|
|
5
|
+
dotenv.config();
|
|
6
6
|
|
|
7
7
|
async function start() {
|
|
8
8
|
const auth = await createAuthenik8({
|
|
@@ -10,47 +10,27 @@ async function start() {
|
|
|
10
10
|
refreshSecret: process.env.REFRESH_SECRET!,
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
app
|
|
14
|
-
app.use(auth.rateLimit);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
app.get("/public", (req, res) => {
|
|
18
|
-
res.json({ message: "Public route" });
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
app.get("/guest", async (req, res) => {
|
|
23
|
-
const token = await auth.guestToken({ role: "guest" });
|
|
24
|
-
res.json({ token });
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
app.get("/protected", async (req, res) => {
|
|
30
|
-
const token = req.headers.authorization?.split(" ")[1];
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const decoded = await auth.verifyToken(token);
|
|
34
|
-
res.json({ message: "Protected data", user: decoded });
|
|
35
|
-
} catch {
|
|
36
|
-
res.status(401).json({ error: "Unauthorized" });
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
app.post("/refresh", async (req, res) => {
|
|
42
|
-
const tokens = await auth.refreshToken(req.body.refreshToken);
|
|
43
|
-
res.json(tokens);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// 🛡️ Admin route
|
|
47
|
-
app.get("/admin", auth.requireAdmin, (req, res) => {
|
|
48
|
-
res.json({ message: "Admin only" });
|
|
49
|
-
});
|
|
13
|
+
const app = createApp(auth);
|
|
50
14
|
|
|
51
15
|
app.listen(3000, () => {
|
|
52
16
|
console.log("🚀 Server running on http://localhost:3000");
|
|
53
17
|
});
|
|
54
18
|
}
|
|
55
|
-
|
|
19
|
+
process.on("uncaughtException", (err) => {
|
|
20
|
+
console.error(" Uncaught Exception:", err);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
process.on("unhandledRejection", (err) => {
|
|
25
|
+
console.error(" Unhandled Rejection:", err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
28
|
+
setInterval(() => {
|
|
29
|
+
const used = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
30
|
+
|
|
31
|
+
if (used > 300) {
|
|
32
|
+
console.error(`Memory exceeded: ${used.toFixed(2)} MB`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}, 10000);
|
|
56
36
|
start();
|