mbkauthe 1.1.9 → 1.1.11

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/lib/info.js CHANGED
@@ -15,7 +15,7 @@ const mbkautheVar = JSON.parse(process.env.mbkautheVar);
15
15
 
16
16
  const router = express.Router();
17
17
 
18
- router.get(["/mbkauthe/login"], (req, res) => {
18
+ router.get("/mbkauthe/login", (req, res) => {
19
19
  return res.render("loginmbkauthe", {
20
20
  layout: false,
21
21
  customURL: mbkautheVar.loginRedirectURL || '/home',
package/lib/main.js CHANGED
@@ -211,7 +211,7 @@ router.post("/mbkauthe/api/login", LoginLimit, async (req, res) => {
211
211
 
212
212
  if (user.Role !== "SuperAdmin") {
213
213
  const allowedApps = user.AllowedApps;
214
- if (!allowedApps || !allowedApps.includes(mbkautheVar.APP_NAME)) {
214
+ if (!allowedApps || !allowedApps.some(app => app.toLowerCase() === mbkautheVar.APP_NAME.toLowerCase())) {
215
215
  console.warn(`User \"${user.UserName}\" is not authorized to use the application \"${mbkautheVar.APP_NAME}\"`);
216
216
  return res.status(403).json({ success: false, message: `You Are Not Authorized To Use The Application \"${mbkautheVar.APP_NAME}\"` });
217
217
  }
@@ -76,7 +76,7 @@ async function validateSession(req, res, next) {
76
76
 
77
77
  if (userResult.Role !== "SuperAdmin") {
78
78
  const allowedApps = userResult.AllowedApps;
79
- if (!allowedApps || !allowedApps.includes(mbkautheVar.APP_NAME)) {
79
+ if (!allowedApps || !allowedApps.some(app => app.toLowerCase() === mbkautheVar.APP_NAME.toLowerCase())) {
80
80
  console.warn(`User \"${req.session.user.username}\" is not authorized to use the application \"${mbkautheVar.APP_NAME}\"`);
81
81
  req.session.destroy();
82
82
  const cookieOptions = getCookieOptions();
@@ -212,100 +212,100 @@ const authenticate = (authentication) => {
212
212
  };
213
213
 
214
214
  const authapi = (requiredRole = []) => {
215
- return (req, res, next) => {
216
- const token = req.headers["authorization"];
215
+ return (req, res, next) => {
216
+ const token = req.headers["authorization"];
217
217
 
218
- if (typeof token === 'string') {
219
- console.log("[authapi] Received request with token:", token[0] + token[1] + token[2], ".....", token[63]);
220
- } else {
221
- console.log("[authapi] Token is not a valid string:", token);
222
- }
218
+ if (typeof token === 'string') {
219
+ console.log("[authapi] Received request with token:", token[0] + token[1] + token[2], ".....", token[63]);
220
+ } else {
221
+ console.log("[authapi] Token is not a valid string:", token);
222
+ }
223
223
 
224
- if (!token) {
225
- console.log("[authapi] No token provided in the request headers");
226
- return res.status(401).json({
227
- success: false,
228
- message: "Authorization token is required"
229
- });
230
- }
224
+ if (!token) {
225
+ console.log("[authapi] No token provided in the request headers");
226
+ return res.status(401).json({
227
+ success: false,
228
+ message: "Authorization token is required"
229
+ });
230
+ }
231
+
232
+ console.log("[authapi] Querying database to validate token");
233
+ const tokenQuery = 'SELECT * FROM "UserAuthApiKey" WHERE "key" = $1';
234
+ pool.query(tokenQuery, [token], (err, result) => {
235
+ if (err) {
236
+ console.error("[authapi] Database query error while validating token:", err);
237
+ return res.status(500).json({
238
+ success: false,
239
+ message: "Internal Server Error"
240
+ });
241
+ }
242
+
243
+ if (result.rows.length === 0) {
244
+ console.log("[authapi] Invalid token provided:", token);
245
+ return res.status(401).json({
246
+ success: false,
247
+ message: "The AuthApiToken Is Invalid"
248
+ });
249
+ }
250
+
251
+ const username = result.rows[0].username;
252
+ console.log("[authapi] Token is valid. Associated username:", username);
231
253
 
232
- console.log("[authapi] Querying database to validate token");
233
- const tokenQuery = 'SELECT * FROM "UserAuthApiKey" WHERE "key" = $1';
234
- pool.query(tokenQuery, [token], (err, result) => {
235
- if (err) {
236
- console.error("[authapi] Database query error while validating token:", err);
237
- return res.status(500).json({
238
- success: false,
239
- message: "Internal Server Error"
240
- });
241
- }
242
-
243
- if (result.rows.length === 0) {
244
- console.log("[authapi] Invalid token provided:", token);
245
- return res.status(401).json({
246
- success: false,
247
- message: "The AuthApiToken Is Invalid"
248
- });
249
- }
250
-
251
- const username = result.rows[0].username;
252
- console.log("[authapi] Token is valid. Associated username:", username);
253
-
254
- console.log("[authapi] Querying database to validate user and role");
255
- const userQuery = `
254
+ console.log("[authapi] Querying database to validate user and role");
255
+ const userQuery = `
256
256
  SELECT id, "UserName", "Active", "Role" FROM "Users"
257
257
  WHERE "UserName" = $1 AND "Active" = true
258
258
  `;
259
259
 
260
- pool.query(userQuery, [username], (err, userResult) => {
261
- if (err) {
262
- console.error("[authapi] Database query error while validating user:", err);
263
- return res.status(500).json({
264
- success: false,
265
- message: "Internal Server Error"
266
- });
267
- }
268
-
269
- if (userResult.rows.length === 0) {
270
- console.log("[authapi] User does not exist or is not active. Username:", username);
271
- return res.status(401).json({
272
- success: false,
273
- message: "User does not exist or is not active",
274
- });
275
- }
276
-
277
- if (username === "demo") {
278
- console.log("[authapi] Demo user attempted to access an endpoint. Access denied.");
279
- return res.status(401).json({
280
- success: false,
281
- message: "Demo user is not allowed to access endpoints",
282
- });
283
- }
284
-
285
- const user = userResult.rows[0];
286
- console.log("[authapi] User is valid. User details:", user);
287
-
288
- // Check if role is required and if user has it
289
- if ((requiredRole && user.Role !== requiredRole) && user.Role !== "SuperAdmin") {
290
- console.log(`[authapi] User does not have the required role. Required: ${requiredRole}, User's role: ${user.Role}`);
291
- return res.status(403).json({
292
- success: false,
293
- message: `Access denied. Required role: ${requiredRole}`,
294
- });
295
- }
296
-
297
- console.log("[authapi] User has the required role or no specific role is required. Proceeding to next middleware.");
298
- req.user = {
299
- username: user.UserName,
300
- role: user.Role,
301
- // Add other user properties you might need
302
- };
303
-
304
- console.log("[authapi] Token and user validation successful. Passing control to next middleware.");
305
- next();
306
- });
307
- });
308
- };
260
+ pool.query(userQuery, [username], (err, userResult) => {
261
+ if (err) {
262
+ console.error("[authapi] Database query error while validating user:", err);
263
+ return res.status(500).json({
264
+ success: false,
265
+ message: "Internal Server Error"
266
+ });
267
+ }
268
+
269
+ if (userResult.rows.length === 0) {
270
+ console.log("[authapi] User does not exist or is not active. Username:", username);
271
+ return res.status(401).json({
272
+ success: false,
273
+ message: "User does not exist or is not active",
274
+ });
275
+ }
276
+
277
+ if (username === "demo") {
278
+ console.log("[authapi] Demo user attempted to access an endpoint. Access denied.");
279
+ return res.status(401).json({
280
+ success: false,
281
+ message: "Demo user is not allowed to access endpoints",
282
+ });
283
+ }
284
+
285
+ const user = userResult.rows[0];
286
+ console.log("[authapi] User is valid. User details:", user);
287
+
288
+ // Check if role is required and if user has it
289
+ if ((requiredRole && user.Role !== requiredRole) && user.Role !== "SuperAdmin") {
290
+ console.log(`[authapi] User does not have the required role. Required: ${requiredRole}, User's role: ${user.Role}`);
291
+ return res.status(403).json({
292
+ success: false,
293
+ message: `Access denied. Required role: ${requiredRole}`,
294
+ });
295
+ }
296
+
297
+ console.log("[authapi] User has the required role or no specific role is required. Proceeding to next middleware.");
298
+ req.user = {
299
+ username: user.UserName,
300
+ role: user.Role,
301
+ // Add other user properties you might need
302
+ };
303
+
304
+ console.log("[authapi] Token and user validation successful. Passing control to next middleware.");
305
+ next();
306
+ });
307
+ });
308
+ };
309
309
  };
310
310
 
311
311
  export { validateSession, checkRolePermission, validateSessionAndRole, getUserData, authenticate, authapi };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mbkauthe",
3
- "version": "1.1.9",
3
+ "version": "1.1.11",
4
4
  "description": "MBKTechStudio's reusable authentication system for Node.js applications.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -5,8 +5,7 @@
5
5
  <head>
6
6
  <meta charset="UTF-8">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
- <meta name="description"
9
- content="Log in to portal.mbktechstudio.com to access your resources and manage projects securely.">
8
+ <meta name="description" content="Log in to portal.mbktechstudio.com to access your resources and manage projects securely.">
10
9
  <meta name="keywords" content="MBK Tech Studio, Web-Portal, Web, Portal, Admin-Panel, Admin, login">
11
10
  <meta property="og:title" content="Login | MBK Tech Studio" />
12
11
  <meta property="og:image" content="https://www.mbktechstudio.com/Assets/Images/Icon/logo.png" />
@@ -16,8 +15,7 @@
16
15
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
17
16
  <link rel="preconnect" href="https://fonts.googleapis.com">
18
17
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
19
- <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
20
- rel="stylesheet">
18
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
21
19
  <script src="https://www.google.com/recaptcha/api.js" async defer></script>
22
20
  <style>
23
21
  :root {
@@ -66,7 +64,6 @@
66
64
  flex-direction: column;
67
65
  }
68
66
 
69
- /* Header - Consistent with index */
70
67
  header {
71
68
  position: fixed;
72
69
  top: 0;
@@ -80,7 +77,7 @@
80
77
  }
81
78
 
82
79
  nav {
83
- padding: 15px 5%;
80
+ padding: 10px 5%;
84
81
  max-width: 1400px;
85
82
  margin: 0 auto;
86
83
  }
@@ -116,7 +113,6 @@
116
113
  color: transparent;
117
114
  }
118
115
 
119
- /* Login Container */
120
116
  .login-container {
121
117
  flex: 1;
122
118
  display: flex;
@@ -131,11 +127,11 @@
131
127
  .login-box {
132
128
  background: var(--dark-light);
133
129
  border-radius: var(--radius-xl);
134
- padding: 3rem;
130
+ padding: 2rem;
135
131
  width: 100%;
136
132
  max-width: 500px;
137
133
  box-shadow: var(--shadow-lg);
138
- border: 1px solid var(--glass-border);
134
+ border: .125rem solid var(--glass-border);
139
135
  position: relative;
140
136
  z-index: 2;
141
137
  transition: var(--transition);
@@ -165,15 +161,14 @@
165
161
  border-radius: 2px;
166
162
  }
167
163
 
168
- /* Form Elements */
169
164
  .form-group {
170
165
  position: relative;
171
- margin-bottom: 2rem;
166
+ margin-bottom: 1rem;
172
167
  }
173
168
 
174
169
  .form-input {
175
170
  width: 100%;
176
- padding: 15px 20px;
171
+ padding: 12px 20px;
177
172
  background: var(--darker);
178
173
  border: 2px solid var(--glass-border);
179
174
  border-radius: var(--radius-sm);
@@ -223,7 +218,7 @@
223
218
 
224
219
  .btn-login {
225
220
  width: 100%;
226
- padding: 15px;
221
+ padding: 10px;
227
222
  border-radius: var(--radius-sm);
228
223
  background: var(--primary);
229
224
  color: white;
@@ -249,7 +244,6 @@
249
244
  box-shadow: none;
250
245
  }
251
246
 
252
- /* Additional Links */
253
247
  .login-links {
254
248
  display: flex;
255
249
  justify-content: space-between;
@@ -266,7 +260,6 @@
266
260
  color: var(--primary);
267
261
  }
268
262
 
269
- /* Terms Info */
270
263
  .terms-info {
271
264
  margin-top: 2rem;
272
265
  font-size: 0.8rem;
@@ -279,14 +272,12 @@
279
272
  font-weight: 500;
280
273
  }
281
274
 
282
- /* Recaptcha */
283
275
  .recaptcha-container {
284
- margin: 2rem 0;
276
+ margin: 1rem 0;
285
277
  display: flex;
286
278
  justify-content: center;
287
279
  }
288
280
 
289
- /* 2FA Token Container */
290
281
  .token-container {
291
282
  animation: fadeInUp 0.4s ease-out;
292
283
  }
@@ -299,7 +290,6 @@
299
290
  display: block;
300
291
  }
301
292
 
302
- /* Floating Elements */
303
293
  .ai-element {
304
294
  position: absolute;
305
295
  opacity: 0.1;
@@ -359,7 +349,6 @@
359
349
  }
360
350
  }
361
351
 
362
- /* Responsive Styles */
363
352
  @media (max-width: 768px) {
364
353
  .login-box {
365
354
  padding: 2rem;
@@ -382,6 +371,55 @@
382
371
  align-items: center;
383
372
  }
384
373
  }
374
+
375
+ .remember-me {
376
+ display: flex;
377
+ align-items: center;
378
+ justify-content: center;
379
+ width: 100%;
380
+ margin: 1rem 0;
381
+ }
382
+
383
+ .remember-me input[type="checkbox"] {
384
+ appearance: none;
385
+ -webkit-appearance: none;
386
+ width: 18px;
387
+ height: 18px;
388
+ border: 2px solid var(--glass-border);
389
+ border-radius: var(--radius-sm);
390
+ margin-right: 10px;
391
+ cursor: pointer;
392
+ position: relative;
393
+ transition: var(--transition);
394
+ }
395
+
396
+ .remember-me input[type="checkbox"]:checked {
397
+ background-color: var(--primary);
398
+ border-color: var(--primary);
399
+ }
400
+
401
+ .remember-me input[type="checkbox"]:checked::after {
402
+ content: '\f00c';
403
+ font-family: 'Font Awesome 6 Free';
404
+ font-weight: 900;
405
+ position: absolute;
406
+ top: 50%;
407
+ left: 50%;
408
+ transform: translate(-50%, -50%);
409
+ color: white;
410
+ font-size: 10px;
411
+ }
412
+
413
+ .remember-me label {
414
+ color: var(--gray);
415
+ cursor: pointer;
416
+ transition: var(--transition);
417
+ font-size: 0.9rem;
418
+ }
419
+
420
+ .remember-me label:hover {
421
+ color: var(--light);
422
+ }
385
423
  </style>
386
424
  </head>
387
425
 
@@ -398,7 +436,7 @@
398
436
  </header>
399
437
 
400
438
  <section class="login-container">
401
- <!-- Floating AI elements -->
439
+
402
440
  <i class="fas fa-robot ai-element"></i>
403
441
  <i class="fas fa-microchip ai-element"></i>
404
442
  <i class="fas fa-user-astronaut ai-element"></i>
@@ -438,6 +476,11 @@
438
476
  </div>
439
477
  </div>
440
478
 
479
+ <div class="form-group remember-me">
480
+ <input type="checkbox" id="rememberMe" name="rememberMe">
481
+ <label for="rememberMe">Remember me</label>
482
+ </div>
483
+
441
484
  <button type="submit" class="btn-login" id="loginButton">
442
485
  <span id="loginButtonText">Login</span>
443
486
  </button>
@@ -459,7 +502,6 @@
459
502
 
460
503
  <script>
461
504
 
462
-
463
505
  // Toggle password visibility
464
506
  const togglePassword = document.getElementById('togglePassword');
465
507
  const passwordInput = document.getElementById('loginPassword');
@@ -494,6 +536,8 @@
494
536
  const recaptchaResponse = grecaptcha.getResponse();
495
537
  const loginButton = document.getElementById('loginButton');
496
538
  const loginButtonText = document.getElementById('loginButtonText');
539
+ const rememberMe = document.getElementById('rememberMe').checked;
540
+
497
541
 
498
542
  if (!username || !password) {
499
543
  showMessage('Username and password are required', 'Login Error');
@@ -521,6 +565,12 @@
521
565
  loginButtonText.textContent = 'Success! Redirecting...';
522
566
  sessionStorage.setItem('sessionId', data.sessionId);
523
567
 
568
+ if (rememberMe) {
569
+ localStorage.setItem('rememberedUsername', username);
570
+ } else {
571
+ localStorage.removeItem('rememberedUsername');
572
+ }
573
+
524
574
  // Redirect to the appropriate page
525
575
  const redirectUrl = new URLSearchParams(window.location.search).get('redirect');
526
576
  window.location.href = redirectUrl ? decodeURIComponent(redirectUrl) : '{{customURL}}';
@@ -564,6 +614,53 @@
564
614
  document.getElementById('loginPassword').value = passwordFromUrl;
565
615
  }
566
616
  });
617
+ // Auto focus on the first empty field
618
+ document.addEventListener('DOMContentLoaded', function () {
619
+ const urlParams = new URLSearchParams(window.location.search);
620
+ const usernameFromUrl = urlParams.get('username');
621
+ const passwordFromUrl = urlParams.get('password');
622
+ const usernameInput = document.getElementById('loginUsername');
623
+
624
+ if (usernameFromUrl) {
625
+ usernameInput.value = usernameFromUrl;
626
+ }
627
+
628
+ if (passwordFromUrl) {
629
+ document.getElementById('loginPassword').value = passwordFromUrl;
630
+ }
631
+
632
+ // Automatically focus the username field
633
+ usernameInput.focus();
634
+ });
635
+ //Remember me functionality
636
+ document.addEventListener('DOMContentLoaded', function () {
637
+ const urlParams = new URLSearchParams(window.location.search);
638
+ const usernameFromUrl = urlParams.get('username');
639
+ const passwordFromUrl = urlParams.get('password');
640
+ const usernameInput = document.getElementById('loginUsername');
641
+
642
+ // Check for remembered username in localStorage
643
+ const rememberedUsername = localStorage.getItem('rememberedUsername');
644
+ if (rememberedUsername) {
645
+ usernameInput.value = rememberedUsername;
646
+ document.getElementById('rememberMe').checked = true;
647
+ }
648
+
649
+ if (usernameFromUrl) {
650
+ usernameInput.value = usernameFromUrl;
651
+ }
652
+
653
+ if (passwordFromUrl) {
654
+ document.getElementById('loginPassword').value = passwordFromUrl;
655
+ }
656
+
657
+ // Automatically focus the first empty field
658
+ if (!usernameInput.value) {
659
+ usernameInput.focus();
660
+ } else {
661
+ document.getElementById('loginPassword').focus();
662
+ }
663
+ });
567
664
  </script>
568
665
  </body>
569
666