mbkauthe 1.0.26 → 1.1.1

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/README.md CHANGED
@@ -32,12 +32,18 @@
32
32
 
33
33
  ## Features
34
34
 
35
- - **Session Management**: Secure session handling using `express-session` and `connect-pg-simple`.
36
- - **Role-Based Access Control**: Validate user roles and permissions with ease.
37
- - **Two-Factor Authentication (2FA)**: Optional 2FA support for enhanced security.
38
- - **reCAPTCHA Integration**: Protect login endpoints with Google reCAPTCHA.
39
- - **Cookie Management**: Configurable cookie expiration and domain settings.
40
- - **PostgreSQL Integration**: Uses a connection pool for efficient database interactions.
35
+ - **Session Management:** Simplifies session handling with secure session restoration and expiration mechanisms.
36
+ - **User Authentication:** Provides robust authentication, including support for username/password and Two-Factor Authentication (2FA).
37
+ - **Role-Based Access Control (RBAC):** Enables fine-grained access control by validating user roles and permissions.
38
+ - **Integration with PostgreSQL:** Seamlessly integrates with PostgreSQL for user and session data storage.
39
+ - **reCAPTCHA Verification:** Adds an extra layer of security with reCAPTCHA support to prevent automated attacks.
40
+ - **Middleware Functions:** Includes reusable middleware for session validation, role checking, and user authentication.
41
+ - **API Endpoints:** Offers a set of RESTful APIs for login, logout, session termination, and package information retrieval.
42
+ - **Environment Configuration:** Supports flexible configuration through .env files for deployment-specific settings.
43
+ - **Demo Account:** Provides a demo account for hands-on exploration of the authentication system.
44
+ - **Database Schema:** Predefined database structure for user, session, and 2FA data management.
45
+ - **Extensibility:** Designed to be easily integrated into existing Node.js applications.
46
+ - **Secure Cookies:** Ensures secure session handling with cookie expiration and domain-specific settings
41
47
 
42
48
  ## Installation
43
49
 
@@ -87,7 +93,7 @@ mbkautheVar='{
87
93
  "IS_DEPLOYED": "true",
88
94
  "LOGIN_DB": "postgres://username:password@host:port/database",
89
95
  "MBKAUTH_TWO_FA_ENABLE": "false",
90
- "COOKIE_EXPIRE_TIME": "1",
96
+ "COOKIE_EXPIRE_TIME": 2,
91
97
  "DOMAIN": "yourdomain.com"
92
98
  }'
93
99
  ```
package/docs/db.md CHANGED
@@ -34,7 +34,6 @@
34
34
  "Active" BOOLEAN NOT NULL DEFAULT true,
35
35
  "HaveMailAccount" BOOLEAN NOT NULL DEFAULT false,
36
36
  "SessionId" TEXT,
37
- "GuestRole" JSONB DEFAULT '{"allowPages": [""], "NotallowPages": [""]}'::jsonb
38
37
  "AllowedApps" JSONB DEFAULT '["mbkauthe"]'::jsonb
39
38
  );
40
39
  ```
package/lib/info.js ADDED
@@ -0,0 +1,185 @@
1
+ import express from "express";
2
+ import fetch from 'node-fetch';
3
+ import { createRequire } from "module";
4
+ import fs from "fs";
5
+ import path from "path";
6
+
7
+ const require = createRequire(import.meta.url);
8
+ const packageJson = require("../package.json");
9
+
10
+ import dotenv from "dotenv";
11
+ dotenv.config();
12
+ const mbkautheVar = JSON.parse(process.env.mbkautheVar);
13
+
14
+ const router = express.Router();
15
+
16
+ // Return package.json data of mbkauthe
17
+ router.get("/mbkauthe/package", async (_, res) => {
18
+ try {
19
+ const response = await fetch("https://mbkauthe.mbktechstudio.com/mbkauthe/package");
20
+ const latestPackageData = await response.json();
21
+ res.status(200).send(`
22
+ <html>
23
+ <head>
24
+ <title>Package Information</title>
25
+ </head>
26
+ <body>
27
+ <h1>Package Information</h1>
28
+ <p><strong>Current Version:</strong> ${JSON.stringify(packageJson, null, 2)}</p>
29
+ <p><strong>Latest Version:</strong> ${JSON.stringify(latestPackageData, null, 2)}</p>
30
+ </body>
31
+ </html>
32
+ `);
33
+ } catch (err) {
34
+ res.status(200).send(`
35
+ <html>
36
+ <head>
37
+ <title>Package Information</title>
38
+ </head>
39
+ <body>
40
+ <h1>Package Information</h1>
41
+ <p><strong>Current Version:</strong> ${JSON.stringify(packageJson, null, 2)}</p>
42
+ <p><strong>Latest Version:</strong> Failed to fetch latest package data, Erro:${err.message}</p>
43
+ </body>
44
+ </html>
45
+ `);
46
+ }
47
+ });
48
+
49
+ // Return version number of mbkauthe
50
+ router.get(["/mbkauthe/version", "/mbkauthe/v"], async (_, res) => {
51
+ try {
52
+ const response = await fetch("https://raw.githubusercontent.com/MIbnEKhalid/mbkauthe/refs/heads/main/package.json");
53
+ const latestPackageData = await response.json();
54
+ res.status(200).send(`
55
+ <html>
56
+ <head>
57
+ <title>Version Information</title>
58
+ </head>
59
+ <body>
60
+ <h1>Package Information</h1>
61
+ <p><strong>Current Version:</strong> ${JSON.stringify(packageJson.version, null, 2)}</p>
62
+ <p><strong>Latest Version:</strong> ${JSON.stringify(latestPackageData.version, null, 2)}</p>
63
+ </body>
64
+ </html>
65
+ `);
66
+ } catch (err) {
67
+ res.status(200).send(`
68
+ <html>
69
+ <head>
70
+ <title>Package Information</title>
71
+ </head>
72
+ <body>
73
+ <h1>Package Information</h1>
74
+ <p><strong>Current Version:</strong> ${JSON.stringify(packageJson.version, null, 2)}</p>
75
+ <p><strong>Latest Version:</strong> Failed to fetch latest package data, Erro:${err.message}</p>
76
+ </body>
77
+ </html>
78
+ `);
79
+ }
80
+ });
81
+
82
+ // Return package-lock.json data of mbkauthe from project the package is installed in
83
+ router.get("/mbkauthe/package-lock", (_, res) => {
84
+ console.log("Request for package-lock.json received");
85
+ const packageLockPath = path.resolve(process.cwd(), "package-lock.json");
86
+ fs.readFile(packageLockPath, "utf8", (err, data) => {
87
+ if (err) {
88
+ console.error("Error reading package-lock.json:", err);
89
+ return res.status(500).json({ success: false, message: "Failed to read package-lock.json" });
90
+ }
91
+ try {
92
+ const packageLock = JSON.parse(data);
93
+ const mbkautheData = {
94
+ name: 'mbkauthe',
95
+ version: packageLock.packages['node_modules/mbkauthe'].version,
96
+ resolved: packageLock.packages['node_modules/mbkauthe'].resolved,
97
+ integrity: packageLock.packages['node_modules/mbkauthe'].integrity,
98
+ license: packageLock.packages['node_modules/mbkauthe'].license,
99
+ dependencies: packageLock.packages['node_modules/mbkauthe'].dependencies
100
+ };
101
+ const rootDependency = packageLock.packages[''].dependencies.mbkauthe;
102
+ console.log('mbkauthe package data:', mbkautheData);
103
+ console.log('Root dependency version:', rootDependency);
104
+ res.status(200).json({ mbkautheData, rootDependency });
105
+ } catch (parseError) {
106
+ console.error("Error parsing package-lock.json:", parseError);
107
+ res.status(500).json({ success: false, message: "Failed to parse package-lock.json" });
108
+ }
109
+ });
110
+ });
111
+
112
+ // Return version number of mbkauthe
113
+ router.get(["/mbkauthe", "/mbkauthe/info", "/mbkauthe/i"], async (_, res) => {
114
+ try {
115
+ res.status(200).send(`
116
+ <html>
117
+ <head>
118
+ <title>Version and Configuration Information</title>
119
+ <style>
120
+ body {
121
+ font-family: Arial, sans-serif;
122
+ line-height: 1.6;
123
+ margin: 20px;
124
+ }
125
+ h1 {
126
+ color: #333;
127
+ }
128
+ p {
129
+ margin: 5px 0;
130
+ }
131
+ a {
132
+ display: block;
133
+ margin: 10px 0;
134
+ color: #007BFF;
135
+ text-decoration: none;
136
+ }
137
+ a:hover {
138
+ text-decoration: underline;
139
+ }
140
+ .info-section {
141
+ margin-bottom: 20px;
142
+ }
143
+ </style>
144
+ </head>
145
+ <body>
146
+ <h1>Version and Configuration Information</h1>
147
+ <div class="info-section">
148
+ <h2>Current Version</h2>
149
+ <p><strong>Version:</strong> ${JSON.stringify(packageJson.version, null, 2)}</p>
150
+ </div>
151
+ <div class="info-section">
152
+ <h2>Configuration Information</h2>
153
+ <p><strong>APP_NAME:</strong> ${mbkautheVar.APP_NAME}</p>
154
+ <p><strong>RECAPTCHA_Enabled:</strong> ${mbkautheVar.RECAPTCHA_Enabled}</p>
155
+ <p><strong>MBKAUTH_TWO_FA_ENABLE:</strong> ${mbkautheVar.MBKAUTH_TWO_FA_ENABLE}</p>
156
+ <p><strong>COOKIE_EXPIRE_TIME:</strong> ${mbkautheVar.COOKIE_EXPIRE_TIME} Days</p>
157
+ <p><strong>IS_DEPLOYED:</strong> ${mbkautheVar.IS_DEPLOYED}</p>
158
+ <p><strong>DOMAIN:</strong> ${mbkautheVar.DOMAIN}</p>
159
+ </div>
160
+ <div class="info-section">
161
+ <h2>Useful Links</h2>
162
+ <a href="/mbkauthe/package">View mbkauthe package.json</a>
163
+ <a href="/mbkauthe/package-lock">View mbkauthe version info from installed project package-lock.json</a>
164
+ <a href="/mbkauthe/version">View Current and Latest Package Version</a>
165
+ </div>
166
+ </body>
167
+ </html>
168
+ `);
169
+ } catch (err) {
170
+ console.error("Error fetching version information:", err);
171
+ res.status(500).send(`
172
+ <html>
173
+ <head>
174
+ <title>Error</title>
175
+ </head>
176
+ <body>
177
+ <h1>Error</h1>
178
+ <p>Failed to fetch version information. Please try again later.</p>
179
+ </body>
180
+ </html>
181
+ `);
182
+ }
183
+ });
184
+
185
+ export default router;
package/lib/main.js CHANGED
@@ -1,4 +1,4 @@
1
- import express, { json } from "express";
1
+ import express from "express";
2
2
  import crypto from "crypto";
3
3
  import session from "express-session";
4
4
  import pgSession from "connect-pg-simple";
@@ -9,12 +9,7 @@ import fetch from 'node-fetch';
9
9
  import cookieParser from "cookie-parser";
10
10
  import bcrypt from 'bcrypt';
11
11
  import rateLimit from 'express-rate-limit';
12
-
13
- import { createRequire } from "module";
14
- const require = createRequire(import.meta.url);
15
- const packageJson = require("../package.json");
16
- import fs from "fs";
17
- import path from "path";
12
+ import mbkautheinfo from "./info.js";
18
13
 
19
14
  import dotenv from "dotenv";
20
15
  dotenv.config();
@@ -22,7 +17,6 @@ const mbkautheVar = JSON.parse(process.env.mbkautheVar);
22
17
 
23
18
  const router = express.Router();
24
19
 
25
- // Enable CORS for subdomains
26
20
  router.use((req, res, next) => {
27
21
  const origin = req.headers.origin;
28
22
  if (origin && origin.endsWith(`.${mbkautheVar.DOMAIN}`)) {
@@ -33,12 +27,11 @@ router.use((req, res, next) => {
33
27
  }
34
28
  next();
35
29
  });
36
-
30
+ router.use(mbkautheinfo);
37
31
  router.use(express.json());
38
32
  router.use(express.urlencoded({ extended: true }));
39
33
  router.use(cookieParser());
40
34
 
41
- // Add rate limiting for sensitive operations
42
35
  const LoginLimit = rateLimit({
43
36
  windowMs: 1 * 60 * 1000,
44
37
  max: 8,
@@ -48,7 +41,6 @@ const LoginLimit = rateLimit({
48
41
  }
49
42
  });
50
43
 
51
- // Configure session with proper domain settings for cross-subdomain sharing
52
44
  const sessionConfig = {
53
45
  store: new PgSession({
54
46
  pool: dblogin,
@@ -58,12 +50,12 @@ const sessionConfig = {
58
50
  secret: mbkautheVar.SESSION_SECRET_KEY,
59
51
  resave: false,
60
52
  saveUninitialized: false,
61
- proxy: true, // Trust the reverse proxy
53
+ proxy: true,
62
54
  cookie: {
63
55
  maxAge: mbkautheVar.COOKIE_EXPIRE_TIME * 24 * 60 * 60 * 1000,
64
56
  domain: mbkautheVar.IS_DEPLOYED === 'true' ? `.${mbkautheVar.DOMAIN}` : undefined,
65
57
  httpOnly: true,
66
- secure: mbkautheVar.IS_DEPLOYED === 'true' ? 'auto' : false, // 'auto' respects X-Forwarded-Proto
58
+ secure: mbkautheVar.IS_DEPLOYED === 'true' ? 'auto' : false,
67
59
  sameSite: 'lax',
68
60
  path: '/'
69
61
  },
@@ -72,7 +64,6 @@ const sessionConfig = {
72
64
 
73
65
  router.use(session(sessionConfig));
74
66
 
75
- // Middleware to handle session restoration from sessionId cookie
76
67
  router.use(async (req, res, next) => {
77
68
  if (!req.session.user && req.cookies.sessionId) {
78
69
  try {
@@ -95,7 +86,6 @@ router.use(async (req, res, next) => {
95
86
  next();
96
87
  });
97
88
 
98
- // Set consistent cookie options for all cookies
99
89
  const getCookieOptions = () => ({
100
90
  maxAge: mbkautheVar.COOKIE_EXPIRE_TIME * 24 * 60 * 60 * 1000,
101
91
  domain: mbkautheVar.IS_DEPLOYED === 'true' ? `.${mbkautheVar.DOMAIN}` : undefined,
@@ -125,7 +115,6 @@ router.post("/mbkauthe/api/terminateAllSessions", authenticate(mbkautheVar.Main_
125
115
  return res.status(500).json({ success: false, message: "Failed to terminate sessions" });
126
116
  }
127
117
 
128
- // Clear all cookies with proper domain
129
118
  const cookieOptions = getCookieOptions();
130
119
  res.clearCookie("mbkauthe.sid", cookieOptions);
131
120
  res.clearCookie("sessionId", cookieOptions);
@@ -208,7 +197,6 @@ router.post("/mbkauthe/api/login", LoginLimit, async (req, res) => {
208
197
  return res.status(500).json({ success: false, errorCode: 605, message: `Internal Server Error` });
209
198
  }
210
199
  } else {
211
- // Check if the password matches
212
200
  if (user.Password !== password) {
213
201
  console.log(`Incorrect password for username: ${username}`);
214
202
  return res.status(401).json({ success: false, errorCode: 603, message: "Incorrect Username Or Password" });
@@ -291,10 +279,8 @@ router.post("/mbkauthe/api/logout", async (req, res) => {
291
279
  try {
292
280
  const { id, username } = req.session.user;
293
281
 
294
- // Clear the SessionId in the database first
295
282
  await dblogin.query(`UPDATE "Users" SET "SessionId" = NULL WHERE "id" = $1`, [id]);
296
283
 
297
- // Remove the session from the session table
298
284
  if (req.sessionID) {
299
285
  await dblogin.query('DELETE FROM "session" WHERE sid = $1', [req.sessionID]);
300
286
  }
@@ -305,7 +291,6 @@ router.post("/mbkauthe/api/logout", async (req, res) => {
305
291
  return res.status(500).json({ success: false, message: "Logout failed" });
306
292
  }
307
293
 
308
- // Clear all cookies with proper domain
309
294
  const cookieOptions = getCookieOptions();
310
295
  res.clearCookie("mbkauthe.sid", cookieOptions);
311
296
  res.clearCookie("sessionId", cookieOptions);
@@ -323,100 +308,4 @@ router.post("/mbkauthe/api/logout", async (req, res) => {
323
308
  }
324
309
  });
325
310
 
326
- // Return package.json data of mbkauthe
327
- router.get("/mbkauthe/package", async (_, res) => {
328
- try {
329
- const response = await fetch("https://mbkauthe.mbktechstudio.com/mbkauthe/package");
330
- const latestPackageData = await response.json();
331
- res.status(200).send(`
332
- <html>
333
- <head>
334
- <title>Package Information</title>
335
- </head>
336
- <body>
337
- <h1>Package Information</h1>
338
- <p><strong>Current Version:</strong> ${JSON.stringify(packageJson, null, 2)}</p>
339
- <p><strong>Latest Version:</strong> ${JSON.stringify(latestPackageData, null, 2)}</p>
340
- </body>
341
- </html>
342
- `);
343
- } catch (err) {
344
- res.status(200).send(`
345
- <html>
346
- <head>
347
- <title>Package Information</title>
348
- </head>
349
- <body>
350
- <h1>Package Information</h1>
351
- <p><strong>Current Version:</strong> ${JSON.stringify(packageJson, null, 2)}</p>
352
- <p><strong>Latest Version:</strong> Failed to fetch latest package data, Erro:${err.message}</p>
353
- </body>
354
- </html>
355
- `);
356
- }
357
- });
358
-
359
- // Return version number of mbkauthe
360
- router.get(["/mbkauthe/version", "/mbkauthe/v"], async(_, res) => {
361
- try {
362
- const response = await fetch("https://mbkauthe.mbktechstudio.com/mbkauthe/version");
363
- const latestPackageData = await response.json();
364
- res.status(200).send(`
365
- <html>
366
- <head>
367
- <title>Version Information</title>
368
- </head>
369
- <body>
370
- <h1>Package Information</h1>
371
- <p><strong>Current Version:</strong> ${JSON.stringify(packageJson.version, null, 2)}</p>
372
- <p><strong>Latest Version:</strong> ${JSON.stringify(latestPackageData, null, 2)}</p>
373
- </body>
374
- </html>
375
- `);
376
- } catch (err) {
377
- res.status(200).send(`
378
- <html>
379
- <head>
380
- <title>Package Information</title>
381
- </head>
382
- <body>
383
- <h1>Package Information</h1>
384
- <p><strong>Current Version:</strong> ${JSON.stringify(packageJson.version, null, 2)}</p>
385
- <p><strong>Latest Version:</strong> Failed to fetch latest package data, Erro:${err.message}</p>
386
- </body>
387
- </html>
388
- `);
389
- }
390
- });
391
-
392
- // Return package-lock.json data of mbkauthe from project the package is installed in
393
- router.get("/mbkauthe/package-lock", (_, res) => {
394
- console.log("Request for package-lock.json received");
395
- const packageLockPath = path.resolve(process.cwd(), "package-lock.json");
396
- fs.readFile(packageLockPath, "utf8", (err, data) => {
397
- if (err) {
398
- console.error("Error reading package-lock.json:", err);
399
- return res.status(500).json({ success: false, message: "Failed to read package-lock.json" });
400
- }
401
- try {
402
- const packageLock = JSON.parse(data);
403
- const mbkautheData = {
404
- name: 'mbkauthe',
405
- version: packageLock.packages['node_modules/mbkauthe'].version,
406
- resolved: packageLock.packages['node_modules/mbkauthe'].resolved,
407
- integrity: packageLock.packages['node_modules/mbkauthe'].integrity,
408
- license: packageLock.packages['node_modules/mbkauthe'].license,
409
- dependencies: packageLock.packages['node_modules/mbkauthe'].dependencies
410
- };
411
- const rootDependency = packageLock.packages[''].dependencies.mbkauthe;
412
- console.log('mbkauthe package data:', mbkautheData);
413
- console.log('Root dependency version:', rootDependency);
414
- res.status(200).json({ mbkautheData, rootDependency });
415
- } catch (parseError) {
416
- console.error("Error parsing package-lock.json:", parseError);
417
- res.status(500).json({ success: false, message: "Failed to parse package-lock.json" });
418
- }
419
- });
420
- });
421
-
422
311
  export default router;
package/lib/pool.js CHANGED
@@ -15,28 +15,27 @@ if (!mbkautheVar) {
15
15
  }
16
16
  const requiredKeys = ["APP_NAME", "RECAPTCHA_Enabled", "SESSION_SECRET_KEY", "IS_DEPLOYED", "LOGIN_DB", "MBKAUTH_TWO_FA_ENABLE", "DOMAIN"];
17
17
  requiredKeys.forEach(key => {
18
- if (!mbkautheVar[key]) {
19
- throw new Error(`mbkautheVar.${key} is required`);
20
- }
18
+ if (!mbkautheVar[key]) {
19
+ throw new Error(`mbkautheVar.${key} is required`);
20
+ }
21
21
  });
22
22
  if (mbkautheVar.RECAPTCHA_Enabled === "true") {
23
- if (mbkautheVar.RECAPTCHA_SECRET_KEY === undefined) {
24
- throw new Error("mbkautheVar.RECAPTCHA_SECRET_KEY is required");
25
- }
23
+ if (mbkautheVar.RECAPTCHA_SECRET_KEY === undefined) {
24
+ throw new Error("mbkautheVar.RECAPTCHA_SECRET_KEY is required");
25
+ }
26
26
  }
27
27
  if (mbkautheVar.COOKIE_EXPIRE_TIME !== undefined) {
28
- const expireTime = parseFloat(mbkautheVar.COOKIE_EXPIRE_TIME);
29
- if (isNaN(expireTime) || expireTime <= 0) {
30
- throw new Error("mbkautheVar.COOKIE_EXPIRE_TIME must be a valid positive number");
31
- }
28
+ const expireTime = parseFloat(mbkautheVar.COOKIE_EXPIRE_TIME);
29
+ if (isNaN(expireTime) || expireTime <= 0) {
30
+ throw new Error("mbkautheVar.COOKIE_EXPIRE_TIME must be a valid positive number");
31
+ }
32
32
  }
33
33
  if (mbkautheVar.BypassUsers !== undefined) {
34
- if (!Array.isArray(mbkautheVar.BypassUsers)) {
35
- throw new Error("mbkautheVar.BypassUsers must be a valid array");
36
- }
34
+ if (!Array.isArray(mbkautheVar.BypassUsers)) {
35
+ throw new Error("mbkautheVar.BypassUsers must be a valid array");
36
+ }
37
37
  }
38
38
 
39
- // PostgreSQL connection pool for pool
40
39
  const poolConfig = {
41
40
  connectionString: mbkautheVar.LOGIN_DB,
42
41
  ssl: {
@@ -47,7 +46,6 @@ const poolConfig = {
47
46
 
48
47
  export const dblogin = new Pool(poolConfig);
49
48
 
50
- // Test connection for pool
51
49
  (async () => {
52
50
  try {
53
51
  const client = await dblogin.connect();
@@ -1,7 +1,6 @@
1
1
  import { dblogin } from "./pool.js";
2
2
  const mbkautheVar = JSON.parse(process.env.mbkautheVar);
3
3
 
4
- // Get consistent cookie options
5
4
  const getCookieOptions = () => ({
6
5
  maxAge: mbkautheVar.COOKIE_EXPIRE_TIME * 24 * 60 * 60 * 1000,
7
6
  domain: mbkautheVar.IS_DEPLOYED === 'true' ? `.${mbkautheVar.DOMAIN}` : undefined,
@@ -12,7 +11,6 @@ const getCookieOptions = () => ({
12
11
  });
13
12
 
14
13
  async function validateSession(req, res, next) {
15
- // First check if we have a session cookie
16
14
  if (!req.session.user && req.cookies.sessionId) {
17
15
  try {
18
16
  const sessionId = req.cookies.sessionId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mbkauthe",
3
- "version": "1.0.26",
3
+ "version": "1.1.1",
4
4
  "description": "MBKTechStudio's reusable authentication system for Node.js applications.",
5
5
  "main": "index.js",
6
6
  "type": "module",