mbkauthe 4.8.2 → 4.8.4

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.
@@ -93,7 +93,7 @@ async function invalidateDbSession(sessionId) {
93
93
  try {
94
94
  await dblogin.query({ name: 'invalidate-app-session', text: 'DELETE FROM "Sessions" WHERE id = $1', values: [sessionId] });
95
95
  } catch (err) {
96
- console.error('[mbkauthe] Error invalidating session:', err);
96
+ console.error(`[mbkauthe] Error invalidating session:`, err);
97
97
  }
98
98
  }
99
99
 
@@ -153,7 +153,7 @@ export async function checkTrustedDevice(req, username) {
153
153
  };
154
154
  }
155
155
  } catch (deviceErr) {
156
- console.error("[mbkauthe] Error checking trusted device:", deviceErr);
156
+ console.error(`[mbkauthe] Error checking trusted device:`, deviceErr);
157
157
  }
158
158
 
159
159
  return null;
@@ -239,7 +239,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
239
239
  await dbClient.query('COMMIT');
240
240
  } catch (err) {
241
241
  await dbClient.query('ROLLBACK').catch(() => {});
242
- console.error('[mbkauthe] Error enforcing session limit or inserting app session:', err);
242
+ console.error(`[mbkauthe] Error enforcing session limit or inserting app session:`, err);
243
243
  throw err;
244
244
  } finally {
245
245
  dbClient.release();
@@ -255,7 +255,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
255
255
  });
256
256
  profileRow = profUpdateRes.rows?.[0] || null;
257
257
  } catch (profileUpdateErr) {
258
- console.error('[mbkauthe] Error updating last_login/returning profile:', profileUpdateErr);
258
+ console.error(`[mbkauthe] Error updating last_login/returning profile:`, profileUpdateErr);
259
259
  }
260
260
 
261
261
  req.session.user = {
@@ -287,7 +287,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
287
287
  if (profileResult.rows[0].Image && profileResult.rows[0].Image.trim() !== '') loginProfileImage = profileResult.rows[0].Image;
288
288
  }
289
289
  } catch (profileErr) {
290
- console.error("[mbkauthe] Error fetching FullName/Image for user:", profileErr);
290
+ console.error(`[mbkauthe] Error fetching FullName/Image for user:`, profileErr);
291
291
  }
292
292
  }
293
293
 
@@ -297,7 +297,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
297
297
 
298
298
  req.session.save(async (err) => {
299
299
  if (err) {
300
- console.error("[mbkauthe] Session save error:", err);
300
+ console.error(`[mbkauthe] Session save error:`, err);
301
301
  return res.status(500).json({ success: false, message: "Internal Server Error" });
302
302
  }
303
303
 
@@ -316,7 +316,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
316
316
  try {
317
317
  res.cookie('lastLoginMethod', method, { ...cachedCookieOptions, httpOnly: false });
318
318
  } catch (err) {
319
- console.error('[mbkauthe] Failed to set lastLoginMethod cookie:', err);
319
+ console.error(`[mbkauthe] Failed to set lastLoginMethod cookie:`, err);
320
320
  }
321
321
  }
322
322
 
@@ -351,7 +351,7 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
351
351
  res.cookie("device_token", deviceToken, getDeviceTokenCookieOptions());
352
352
  console.log(`[mbkauthe] Trusted device token created for user: ${username}`);
353
353
  } catch (deviceErr) {
354
- console.error("[mbkauthe] Error creating trusted device:", deviceErr);
354
+ console.error(`[mbkauthe] Error creating trusted device:`, deviceErr);
355
355
  // Continue with login even if device trust fails
356
356
  }
357
357
  }
@@ -371,14 +371,14 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
371
371
  res.status(200).json(responsePayload);
372
372
  });
373
373
  } catch (err) {
374
- console.error("[mbkauthe] Error during login completion:", err);
374
+ console.error(`[mbkauthe] Error during login completion:`, err);
375
375
  res.status(500).json({ success: false, message: "Internal Server Error" });
376
376
  }
377
377
  }
378
378
 
379
379
  // POST /mbkauthe/api/login
380
380
  router.post("/api/login", LoginLimit, async (req, res) => {
381
- console.log("[mbkauthe] Login request received");
381
+ console.log(`[mbkauthe] Login request received`);
382
382
 
383
383
  const { username, password, redirect } = req.body;
384
384
 
@@ -415,7 +415,7 @@ router.post("/api/login", LoginLimit, async (req, res) => {
415
415
  try {
416
416
  // Combined query: fetch user data and 2FA status in one query
417
417
  const userQuery = `
418
- SELECT u.id, u."UserName", u."Password", u."PasswordEnc", u."Active", u."Role", u."AllowedApps",
418
+ SELECT u.id, u."UserName", u."PasswordEnc", u."Active", u."Role", u."AllowedApps",
419
419
  tfa."TwoFAStatus"
420
420
  FROM "Users" u
421
421
  LEFT JOIN "TwoFA" tfa ON u."UserName" = tfa."UserName"
@@ -432,25 +432,13 @@ router.post("/api/login", LoginLimit, async (req, res) => {
432
432
 
433
433
  const user = userResult.rows[0];
434
434
 
435
- // Validate user has password field
436
- if (!user.Password && !user.PasswordEnc) {
437
- console.error("[mbkauthe] User account has no password set");
438
- return res.status(500).json({ success: false, message: "Internal Server Error" });
439
- }
440
-
441
- // Check password based on EncPass configuration - ALWAYS validate password first
435
+ // Password verification (hash-only). We never read/compare plaintext passwords.
442
436
  let passwordMatches = false;
443
- if (mbkautheVar.EncPass === "true" || mbkautheVar.EncPass === true) {
444
- // Use encrypted password comparison
445
- if (user.PasswordEnc) {
446
- const hashedInputPassword = hashPassword(password, user.UserName);
447
- passwordMatches = user.PasswordEnc === hashedInputPassword;
448
- }
449
- } else {
450
- // Use raw password comparison
451
- if (user.Password) {
452
- passwordMatches = user.Password === password;
453
- }
437
+ if (user.PasswordEnc) {
438
+ const hashedInputPassword = hashPassword(password, user.UserName);
439
+ const stored = Buffer.from(String(user.PasswordEnc), 'utf8');
440
+ const computed = Buffer.from(String(hashedInputPassword), 'utf8');
441
+ passwordMatches = stored.length === computed.length && crypto.timingSafeEqual(stored, computed);
454
442
  }
455
443
 
456
444
  if (!passwordMatches) {
@@ -523,7 +511,7 @@ router.post("/api/login", LoginLimit, async (req, res) => {
523
511
  await completeLoginProcess(req, res, userForSession, requestedRedirect, false, 'password');
524
512
 
525
513
  } catch (err) {
526
- console.error("[mbkauthe] Error during login process:", err);
514
+ console.error(`[mbkauthe] Error during login process:`, err);
527
515
  res.status(500).json({ success: false, message: "Internal Server Error" });
528
516
  }
529
517
  });
@@ -627,7 +615,7 @@ router.post("/api/verify-2fa", TwoFALimit, csrfProtection, async (req, res) => {
627
615
  await completeLoginProcess(req, res, userForSession, redirectUrl, shouldTrustDevice, methodToUse);
628
616
 
629
617
  } catch (err) {
630
- console.error("[mbkauthe] Error during 2FA verification:", err);
618
+ console.error(`[mbkauthe] Error during 2FA verification:`, err);
631
619
  res.status(500).json({ success: false, message: "Internal Server Error" });
632
620
  }
633
621
  });
@@ -660,7 +648,7 @@ router.post("/api/logout", LogoutLimit, async (req, res) => {
660
648
 
661
649
  req.session.destroy((err) => {
662
650
  if (err) {
663
- console.error("[mbkauthe] Error destroying session:", err);
651
+ console.error(`[mbkauthe] Error destroying session:`, err);
664
652
  return res.status(500).json({ success: false, message: "Logout failed" });
665
653
  }
666
654
 
@@ -670,7 +658,7 @@ router.post("/api/logout", LogoutLimit, async (req, res) => {
670
658
  res.status(200).json({ success: true, message: "Logout successful" });
671
659
  });
672
660
  } catch (err) {
673
- console.error("[mbkauthe] Database query error during logout:", err);
661
+ console.error(`[mbkauthe] Database query error during logout:`, err);
674
662
  res.status(500).json({ success: false, message: "Internal Server Error" });
675
663
  }
676
664
  } else {
@@ -716,7 +704,7 @@ router.get("/api/account-sessions", LoginLimit, async (req, res) => {
716
704
  if (!acct.image && prof.rows[0].Image && prof.rows[0].Image.trim() !== '') image = prof.rows[0].Image;
717
705
  }
718
706
  } catch (profileErr) {
719
- console.error('[mbkauthe] Error fetching fullname/image for account list:', profileErr);
707
+ console.error(`[mbkauthe] Error fetching fullname/image for account list:`, profileErr);
720
708
  }
721
709
  }
722
710
 
@@ -728,7 +716,7 @@ router.get("/api/account-sessions", LoginLimit, async (req, res) => {
728
716
  isCurrent: currentSessionId && row.sid === currentSessionId
729
717
  });
730
718
  } catch (err) {
731
- console.error('[mbkauthe] Error validating remembered account:', err);
719
+ console.error(`[mbkauthe] Error validating remembered account:`, err);
732
720
  }
733
721
  }
734
722
 
@@ -770,7 +758,7 @@ router.post("/api/switch-session", LoginLimit, async (req, res) => {
770
758
  if (prof.rows[0].Image && prof.rows[0].Image.trim() !== '') switchProfileImage = prof.rows[0].Image;
771
759
  }
772
760
  } catch (profileErr) {
773
- console.error('[mbkauthe] Error fetching fullname/image during switch:', profileErr);
761
+ console.error(`[mbkauthe] Error fetching fullname/image during switch:`, profileErr);
774
762
  }
775
763
 
776
764
  // Regenerate session to avoid fixation
@@ -814,7 +802,7 @@ router.post("/api/switch-session", LoginLimit, async (req, res) => {
814
802
  redirect: safeRedirect
815
803
  });
816
804
  } catch (err) {
817
- console.error('[mbkauthe] Error during session switch:', err);
805
+ console.error(`[mbkauthe] Error during session switch:`, err);
818
806
  return res.status(500).json(createErrorResponse(500, ErrorCodes.INTERNAL_SERVER_ERROR));
819
807
  }
820
808
  });
@@ -846,7 +834,7 @@ router.post("/api/logout-all", LoginLimit, async (req, res) => {
846
834
 
847
835
  return res.json({ success: true, message: 'All accounts logged out' });
848
836
  } catch (err) {
849
- console.error('[mbkauthe] Error during logout-all:', err);
837
+ console.error(`[mbkauthe] Error during logout-all:`, err);
850
838
  return res.status(500).json(createErrorResponse(500, ErrorCodes.INTERNAL_SERVER_ERROR));
851
839
  }
852
840
  });
@@ -45,7 +45,7 @@ router.get(["/db.json"], LogLimit, async (req, res) => {
45
45
 
46
46
  return res.json({ queryCount, queryLimit, queryLog, isDev });
47
47
  } catch (err) {
48
- console.error('[mbkauthe] /db.json route error:', err);
48
+ console.error(`[mbkauthe] /db.json route error:`, err);
49
49
  return res.status(500).json({ success: false, message: 'Could not fetch DB stats.' });
50
50
  }
51
51
  });
@@ -70,7 +70,7 @@ router.post(["/db/reset"], LogLimit, async (req, res) => {
70
70
 
71
71
  return res.json({ success: true, message: 'Query log and count have been reset.' });
72
72
  } catch (err) {
73
- console.error('[mbkauthe] /db/reset route error:', err);
73
+ console.error(`[mbkauthe] /db/reset route error:`, err);
74
74
  return res.status(500).json({ success: false, message: 'Could not reset DB stats.' });
75
75
  }
76
76
  });
@@ -90,7 +90,7 @@ router.get(["/db"], LogLimit, async (req, res) => {
90
90
  disabledMessage: isDev ? null : 'DB logs are disabled.'
91
91
  });
92
92
  } catch (err) {
93
- console.error('[mbkauthe] /db route error:', err);
93
+ console.error(`[mbkauthe] /db route error:`, err);
94
94
  return renderError(res, req, {
95
95
  layout: false,
96
96
  code: 500,
@@ -3,7 +3,7 @@ import fetch from 'node-fetch';
3
3
  import rateLimit from 'express-rate-limit';
4
4
  import { mbkautheVar, packageJson, appVersion } from "#config.js";
5
5
  import { renderError, renderPage } from "#response.js";
6
- import { authenticate, validateSession, validateSessionAndRole } from "../middleware/auth.js";
6
+ import { authenticate, sessVal, sessRole } from "../middleware/auth.js";
7
7
  import { ErrorCodes, ErrorMessages, createErrorResponse } from "../utils/errors.js";
8
8
  import { dblogin } from "#pool.js";
9
9
  import { clearSessionCookies, decryptSessionId, cachedCookieOptions } from "#cookies.js";
@@ -60,7 +60,7 @@ router.get("/bg.webp", (req, res) => {
60
60
  res.setHeader('Cache-Control', 'public, max-age=31536000');
61
61
  const stream = fs.createReadStream(imgPath);
62
62
  stream.on('error', (err) => {
63
- console.error('[mbkauthe] Error streaming bg.webp:', err);
63
+ console.error(`[mbkauthe] Error streaming bg.webp:`, err);
64
64
  res.status(404).send('Image not found');
65
65
  });
66
66
  stream.pipe(res);
@@ -78,7 +78,7 @@ router.get('/user/profilepic', async (req, res) => {
78
78
  }
79
79
  const stream = fs.createReadStream(iconPath);
80
80
  stream.on('error', (err) => {
81
- console.error('[mbkauthe] Error streaming icon.svg:', err);
81
+ console.error(`[mbkauthe] Error streaming icon.svg:`, err);
82
82
  res.status(404).send('Icon not found');
83
83
  });
84
84
  stream.pipe(res);
@@ -152,21 +152,21 @@ router.get('/user/profilepic', async (req, res) => {
152
152
 
153
153
  imageResponse.body.pipe(res);
154
154
  } catch (fetchErr) {
155
- console.error('[mbkauthe] Error fetching external profile picture:', fetchErr);
155
+ console.error(`[mbkauthe] Error fetching external profile picture:`, fetchErr);
156
156
  res.cookie('profileImageUrl', 'default', { ...cachedCookieOptions, httpOnly: false });
157
157
  res.cookie('profileImageUser', username, { ...cachedCookieOptions, httpOnly: false });
158
158
  return serveDefaultIcon();
159
159
  }
160
160
 
161
161
  } catch (err) {
162
- console.error('[mbkauthe] Error fetching profile picture:', err);
162
+ console.error(`[mbkauthe] Error fetching profile picture:`, err);
163
163
  return serveDefaultIcon();
164
164
  }
165
165
  });
166
166
 
167
167
  if (process.env.env === 'dev') {
168
168
  // Dev-only diagnostic endpoint to verify SuperAdmin role enforcement
169
- router.get(['/validate-superadmin'], validateSessionAndRole("SuperAdmin"), LoginLimit, async (req, res) => {
169
+ router.get(['/validate-superadmin'], sessRole("SuperAdmin"), LoginLimit, async (req, res) => {
170
170
  try {
171
171
  const user = req.session?.user || null;
172
172
  return res.json({
@@ -180,14 +180,14 @@ if (process.env.env === 'dev') {
180
180
  } : null
181
181
  });
182
182
  } catch (err) {
183
- console.error('[mbkauthe] debug validate-superadmin error:', err);
183
+ console.error(`[mbkauthe] debug validate-superadmin error:`, err);
184
184
  return res.status(500).json(createErrorResponse(500, ErrorCodes.INTERNAL_SERVER_ERROR));
185
185
  }
186
186
  });
187
187
  }
188
188
 
189
189
  // Test route
190
- router.get(['/test', '/'], validateSession, LoginLimit, async (req, res) => {
190
+ router.get(['/test', '/'], sessVal, LoginLimit, async (req, res) => {
191
191
  const { username, fullname, role, id, sessionId, allowedApps } = req.session.user;
192
192
 
193
193
  const sessionExpiry = req.session.cookie?.expires
@@ -208,7 +208,7 @@ router.get(['/test', '/'], validateSession, LoginLimit, async (req, res) => {
208
208
  });
209
209
  });
210
210
 
211
- router.post('/test', validateSession, LoginLimit, async (req, res) => {
211
+ router.post('/test', sessVal, LoginLimit, async (req, res) => {
212
212
  if (req.session?.user) {
213
213
  return res.json({ success: true, message: "You are logged in" });
214
214
  }
@@ -266,7 +266,7 @@ router.get('/api/checkSession', LoginLimit, async (req, res) => {
266
266
 
267
267
  return res.status(200).json({ sessionValid: true, expiry });
268
268
  } catch (err) {
269
- console.error('[mbkauthe] checkSession error:', err);
269
+ console.error(`[mbkauthe] checkSession error:`, err);
270
270
  return res.status(200).json({ sessionValid: false, expiry: null });
271
271
  }
272
272
  });
@@ -342,7 +342,7 @@ router.post('/api/checkSession', LoginLimit, async (req, res) => {
342
342
  const expiry = row.expires_at ? new Date(row.expires_at).toISOString() : null;
343
343
  return res.status(200).json({ sessionValid: true, expiry });
344
344
  } catch (err) {
345
- console.error('[mbkauthe] checkSession (body) error:', err);
345
+ console.error(`[mbkauthe] checkSession (body) error:`, err);
346
346
  return res.status(200).json({ sessionValid: false, expiry: null });
347
347
  }
348
348
  });
@@ -374,7 +374,7 @@ router.post('/api/verifySession', LoginLimit, async (req, res) => {
374
374
  const expiry = row.expires_at ? new Date(row.expires_at).toISOString() : null;
375
375
  return res.status(200).json({ valid: true, expiry, username: row.UserName, role: row.Role });
376
376
  } catch (err) {
377
- console.error('[mbkauthe] verifySession error:', err);
377
+ console.error(`[mbkauthe] verifySession error:`, err);
378
378
  return res.status(200).json({ valid: false, expiry: null });
379
379
  }
380
380
  });
@@ -465,7 +465,7 @@ router.get("/ErrorCode", (req, res) => {
465
465
  errorCategories: categoriesWithErrors
466
466
  });
467
467
  } catch (err) {
468
- console.error("[mbkauthe] Error rendering error codes page:", err);
468
+ console.error(`[mbkauthe] Error rendering error codes page:`, err);
469
469
  return renderError(res, req, {
470
470
  layout: false,
471
471
  code: 500,
@@ -488,7 +488,7 @@ export async function getLatestVersion() {
488
488
  const latestPackageJson = await response.json();
489
489
  return typeof latestPackageJson.version === 'string' ? latestPackageJson.version : null;
490
490
  } catch (error) {
491
- console.error('[mbkauthe] Error fetching latest version from GitHub');
491
+ console.error(`[mbkauthe] Error fetching latest version from GitHub`, error);
492
492
  return null;
493
493
  }
494
494
  }
@@ -503,7 +503,7 @@ export async function checkVersion() {
503
503
  } else if (hasValidLatest) {
504
504
  console.info(`[mbkauthe] Running latest version (${packageJson.version}).`);
505
505
  } else {
506
- console.info('[mbkauthe] Skipped version check warning: latest version unavailable.');
506
+ console.info(`[mbkauthe] Skipped version check warning: latest version unavailable.`);
507
507
  }
508
508
  } catch (error) {
509
509
  console.warn(`[mbkauthe] Failed to check for updates: ${error.message}`);
@@ -520,7 +520,7 @@ router.get(["/info", "/i"], LoginLimit, async (req, res) => {
520
520
  try {
521
521
  latestVersion = await getLatestVersion();
522
522
  } catch (err) {
523
- console.error("[mbkauthe] Error fetching package-lock.json:", err);
523
+ console.error(`[mbkauthe] Error fetching package-lock.json:`, err);
524
524
  }
525
525
 
526
526
  try {
@@ -531,7 +531,7 @@ router.get(["/info", "/i"], LoginLimit, async (req, res) => {
531
531
  latestVersion
532
532
  });
533
533
  } catch (err) {
534
- console.error("[mbkauthe] Error fetching version information:", err);
534
+ console.error(`[mbkauthe] Error fetching version information:`, err);
535
535
  res.status(500).send(`
536
536
  <html>
537
537
  <head>
@@ -551,13 +551,13 @@ router.get(["/info.json", "/i.json"], LoginLimit, async (req, res) => {
551
551
  try {
552
552
  latestVersion = await getLatestVersion();
553
553
  } catch (err) {
554
- console.error("[mbkauthe] Error fetching package-lock.json:", err);
554
+ console.error(`[mbkauthe] Error fetching package-lock.json:`, err);
555
555
  }
556
556
 
557
557
  try {
558
558
  res.json({ mbkautheVar: safe_mbkautheVar, CurrentVersion: packageJson.version, APP_VERSION: appVersion, latestVersion });
559
559
  } catch (err) {
560
- console.error("[mbkauthe] Error fetching version information:", err);
560
+ console.error(`[mbkauthe] Error fetching version information:`, err);
561
561
  res.status(500).json({ success: false, message: "Failed to fetch version information" });
562
562
  }
563
563
  });
@@ -579,20 +579,20 @@ router.post("/api/terminateAllSessions", AdminOperationLimit, authenticate(mbkau
579
579
 
580
580
  req.session.destroy((err) => {
581
581
  if (err) {
582
- console.log("[mbkauthe] Error destroying session:", err);
582
+ console.log(`[mbkauthe] Error destroying session:`, err);
583
583
  return res.status(500).json({ success: false, message: "Failed to terminate sessions" });
584
584
  }
585
585
 
586
586
  clearSessionCookies(res);
587
587
 
588
- console.log("[mbkauthe] All sessions terminated successfully");
588
+ console.log(`[mbkauthe] All sessions terminated successfully`);
589
589
  res.status(200).json({
590
590
  success: true,
591
591
  message: "All sessions terminated successfully",
592
592
  });
593
593
  });
594
594
  } catch (err) {
595
- console.error("[mbkauthe] Database query error during session termination:", err);
595
+ console.error(`[mbkauthe] Database query error during session termination:`, err);
596
596
  res.status(500).json({ success: false, message: "Internal Server Error" });
597
597
  }
598
598
  });
@@ -0,0 +1,35 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+
3
+ export function extractAuthorizationToken(authorizationHeader) {
4
+ if (typeof authorizationHeader !== "string") return "";
5
+
6
+ const raw = authorizationHeader.trim();
7
+ if (!raw) return "";
8
+
9
+ const bearerMatch = /^bearer\s+(.+)$/i.exec(raw);
10
+ if (bearerMatch) return bearerMatch[1].trim();
11
+
12
+ return raw;
13
+ }
14
+
15
+ function sha256Buffer(value) {
16
+ return createHash("sha256").update(value, "utf8").digest();
17
+ }
18
+
19
+ /**
20
+ * Constant-time comparison of two strings by hashing them first.
21
+ *
22
+ * Notes:
23
+ * - Always computes both hashes (32 bytes each) and uses timingSafeEqual.
24
+ * - Returns false when expectedToken is empty/unset.
25
+ */
26
+ export function timingSafeTokenMatch(providedToken, expectedToken) {
27
+ const provided = typeof providedToken === "string" ? providedToken : "";
28
+ const expected = typeof expectedToken === "string" ? expectedToken : "";
29
+
30
+ const providedHash = sha256Buffer(provided);
31
+ const expectedHash = sha256Buffer(expected);
32
+
33
+ const matches = timingSafeEqual(providedHash, expectedHash);
34
+ return matches && expected.length > 0;
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mbkauthe",
3
- "version": "4.8.2",
3
+ "version": "4.8.4",
4
4
  "description": "MBKTech's reusable authentication system for Node.js applications.",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/public/main.js CHANGED
@@ -25,7 +25,7 @@ async function logout() {
25
25
  alert(result.message);
26
26
  }
27
27
  } catch (error) {
28
- console.error("[mbkauthe] Error during logout:", error);
28
+ console.error(`[mbkauthe] Error during logout:`, error);
29
29
  alert(`Logout failed: ${error.message}`);
30
30
  }
31
31
  }
@@ -67,7 +67,7 @@ async function selectiveCacheClear() {
67
67
  window.location.reload();
68
68
 
69
69
  } catch (error) {
70
- console.error('[mbkauthe] selective cache clear failed:', error);
70
+ console.error(`[mbkauthe] selective cache clear failed:`, error);
71
71
  window.location.reload();
72
72
  }
73
73
  }
@@ -86,7 +86,7 @@ function checkSession() {
86
86
  window.location.reload(); // Reload the page to update the session status
87
87
  }
88
88
  })
89
- .catch((error) => console.error("[mbkauthe] Error checking session:", error));
89
+ .catch((error) => console.error(`[mbkauthe] Error checking session:`, error));
90
90
  }
91
91
  // Call validateSession every 2 minutes (120000 milliseconds)
92
92
  // setInterval(checkSession, validateSessionInterval);
@@ -312,7 +312,7 @@
312
312
  setTimeout(() => { copyBtn.innerHTML = orig; }, 2000);
313
313
  }
314
314
  } catch (err) {
315
- console.error('[mbkauthe] Failed to copy: ', err);
315
+ console.error(`[mbkauthe] Failed to copy:`, err);
316
316
  }
317
317
  });
318
318
  }
@@ -84,6 +84,7 @@
84
84
  try {
85
85
  const response = await fetch('/mbkauthe/api/verify-2fa', {
86
86
  method: 'POST',
87
+ credentials: 'include',
87
88
  headers: {
88
89
  'Content-Type': 'application/json'
89
90
  },
@@ -362,7 +362,7 @@
362
362
  emptyStateLink.href = `/mbkauthe/login${encoded ? `?redirect=${encoded}` : ''}`;
363
363
  }
364
364
  } catch (err) {
365
- console.error('[mbkauthe] Failed to set login hrefs with redirect query param:', err);
365
+ console.error(`[mbkauthe] Failed to set login hrefs with redirect query param:`, err);
366
366
  }
367
367
  })();
368
368
 
@@ -468,7 +468,7 @@
468
468
  });
469
469
 
470
470
  } catch (err) {
471
- console.error('[mbkauthe] Failed to load accounts:', err);
471
+ console.error(`[mbkauthe] Failed to load accounts:`, err);
472
472
  list.innerHTML = '<div class="empty-state">Failed to load accounts.</div>';
473
473
  }
474
474
  }
@@ -501,7 +501,7 @@
501
501
  loadAccounts();
502
502
  }
503
503
  } catch (err) {
504
- console.error('[mbkauthe] Switch failed:', err);
504
+ console.error(`[mbkauthe] Switch failed:`, err);
505
505
  showMessage('Could not switch account right now. Please try again.', 'Switch Account');
506
506
  }
507
507
  }
@@ -521,7 +521,7 @@
521
521
  showMessage(data.message || 'Could not sign out all accounts', 'Sign out');
522
522
  }
523
523
  } catch (err) {
524
- console.error('[mbkauthe] Sign-out-all failed:', err);
524
+ console.error(`[mbkauthe] Sign-out-all failed:`, err);
525
525
  showMessage('Could not sign out all accounts right now. Please try again.', 'Sign out');
526
526
  }
527
527
  }
@@ -287,6 +287,7 @@
287
287
  const pageRedirect = new URLSearchParams(window.location.search).get('redirect');
288
288
  fetch('/mbkauthe/api/login', {
289
289
  method: 'POST',
290
+ credentials: 'include',
290
291
  headers: {
291
292
  'Content-Type': 'application/json'
292
293
  },
@@ -326,7 +327,7 @@
326
327
  .catch(error => {
327
328
  loginButton.disabled = false;
328
329
  loginButtonText.textContent = 'Login';
329
- console.error('[mbkauthe] Error:', error);
330
+ console.error(`[mbkauthe] Error:`, error);
330
331
  showMessage('An error occurred. Please try again.', 'Login Error');
331
332
  });
332
333
  });
@@ -277,7 +277,7 @@
277
277
  alert(result.message || 'Logout failed. Please try again.');
278
278
  }
279
279
  } catch (error) {
280
- console.error('[mbkauthe] Error during logout:', error);
280
+ console.error(`[mbkauthe] Error during logout:`, error);
281
281
  alert('Logout failed. Please try again.');
282
282
  } finally {
283
283
  logoutButton.disabled = false;
@@ -299,7 +299,7 @@
299
299
  switchAccountLink.href = baseHref + encodeURIComponent(currentUrl);
300
300
  } catch (err) {
301
301
  // non-fatal, but log for debugging
302
- console.error('[mbkauthe] Failed to set redirect URL for switch account link', err);
302
+ console.error(`[mbkauthe] Failed to set redirect URL for switch account link`, err);
303
303
  }
304
304
  })();
305
305
  })();