mbkauthe 1.4.1 → 2.0.0
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/.github/PACKAGE.md +1 -1
- package/.github/workflows/publish.yml +35 -2
- package/README.md +3 -3
- package/docs/api.md +70 -4
- package/env.md +1 -1
- package/lib/main.js +285 -105
- package/lib/pool.js +2 -2
- package/lib/validateSessionAndRole.js +22 -47
- package/package.json +6 -3
- package/public/bg.avif +0 -0
- package/public/main.js +5 -7
- package/views/2fa.handlebars +6 -6
- package/views/Error/dError.handlebars +3 -3
- package/views/info.handlebars +13 -10
- package/views/loginmbkauthe.handlebars +52 -14
- package/views/sharedStyles.handlebars +1 -1
- package/views/showmessage.handlebars +1 -1
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { dblogin } from "./pool.js";
|
|
2
2
|
const mbkautheVar = JSON.parse(process.env.mbkautheVar);
|
|
3
|
-
let pool = dblogin;
|
|
4
3
|
|
|
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,
|
|
8
|
-
secure: mbkautheVar.IS_DEPLOYED === 'true'
|
|
7
|
+
secure: mbkautheVar.IS_DEPLOYED === 'true',
|
|
9
8
|
sameSite: 'lax',
|
|
10
9
|
path: '/',
|
|
11
10
|
httpOnly: true
|
|
@@ -13,44 +12,13 @@ const getCookieOptions = () => ({
|
|
|
13
12
|
|
|
14
13
|
const getClearCookieOptions = () => ({
|
|
15
14
|
domain: mbkautheVar.IS_DEPLOYED === 'true' ? `.${mbkautheVar.DOMAIN}` : undefined,
|
|
16
|
-
secure: mbkautheVar.IS_DEPLOYED === 'true'
|
|
15
|
+
secure: mbkautheVar.IS_DEPLOYED === 'true',
|
|
17
16
|
sameSite: 'lax',
|
|
18
17
|
path: '/',
|
|
19
18
|
httpOnly: true
|
|
20
19
|
});
|
|
21
20
|
|
|
22
21
|
async function validateSession(req, res, next) {
|
|
23
|
-
if (!req.session.user && req.cookies.sessionId) {
|
|
24
|
-
try {
|
|
25
|
-
const sessionId = req.cookies.sessionId;
|
|
26
|
-
|
|
27
|
-
// Validate sessionId format (should be 64 hex characters)
|
|
28
|
-
if (typeof sessionId !== 'string' || !/^[a-f0-9]{64}$/i.test(sessionId)) {
|
|
29
|
-
console.warn("[mbkauthe] Invalid sessionId format detected");
|
|
30
|
-
return next();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const query = `SELECT id, "UserName", "Active", "Role", "SessionId", "AllowedApps" FROM "Users" WHERE "SessionId" = $1 AND "Active" = true`;
|
|
34
|
-
const result = await dblogin.query({ name: 'get-user-by-sessionid', text: query, values: [sessionId] });
|
|
35
|
-
|
|
36
|
-
if (result.rows.length > 0) {
|
|
37
|
-
const user = result.rows[0];
|
|
38
|
-
req.session.user = {
|
|
39
|
-
id: user.id,
|
|
40
|
-
username: user.UserName,
|
|
41
|
-
UserName: user.UserName,
|
|
42
|
-
role: user.Role,
|
|
43
|
-
Role: user.Role,
|
|
44
|
-
sessionId,
|
|
45
|
-
allowedApps: user.AllowedApps,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
} catch (err) {
|
|
49
|
-
console.error("[mbkauthe] Session validation error:", err);
|
|
50
|
-
return res.status(500).json({ success: false, message: "Internal Server Error" });
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
22
|
if (!req.session.user) {
|
|
55
23
|
console.log("[mbkauthe] User not authenticated");
|
|
56
24
|
console.log("[mbkauthe]: ", req.session.user);
|
|
@@ -67,11 +35,14 @@ async function validateSession(req, res, next) {
|
|
|
67
35
|
try {
|
|
68
36
|
const { id, sessionId, role, allowedApps } = req.session.user;
|
|
69
37
|
|
|
70
|
-
//
|
|
38
|
+
// Normalize sessionId to lowercase for consistent comparison
|
|
39
|
+
const normalizedSessionId = sessionId.toLowerCase();
|
|
40
|
+
|
|
41
|
+
// Single optimized query to validate session
|
|
71
42
|
const query = `SELECT "SessionId", "Active" FROM "Users" WHERE "id" = $1`;
|
|
72
|
-
const result = await dblogin.query({ name: '
|
|
43
|
+
const result = await dblogin.query({ name: 'validate-user-session', text: query, values: [id] });
|
|
73
44
|
|
|
74
|
-
if (result.rows.length === 0 || result.rows[0].SessionId !==
|
|
45
|
+
if (result.rows.length === 0 || result.rows[0].SessionId.toLowerCase() !== normalizedSessionId) {
|
|
75
46
|
console.log(`[mbkauthe] Session invalidated for user "${req.session.user.username}"`);
|
|
76
47
|
req.session.destroy();
|
|
77
48
|
const cookieOptions = getClearCookieOptions();
|
|
@@ -101,7 +72,7 @@ async function validateSession(req, res, next) {
|
|
|
101
72
|
error: "Account Inactive",
|
|
102
73
|
message: "Your Account Is Inactive. Please Contact Support.",
|
|
103
74
|
pagename: "Support",
|
|
104
|
-
page: "https://
|
|
75
|
+
page: "https://mbktech.org/Support",
|
|
105
76
|
});
|
|
106
77
|
}
|
|
107
78
|
|
|
@@ -131,12 +102,11 @@ async function validateSession(req, res, next) {
|
|
|
131
102
|
}
|
|
132
103
|
}
|
|
133
104
|
|
|
134
|
-
const checkRolePermission = (
|
|
105
|
+
const checkRolePermission = (requiredRoles, notAllowed) => {
|
|
135
106
|
return async (req, res, next) => {
|
|
136
107
|
try {
|
|
137
108
|
if (!req.session || !req.session.user || !req.session.user.id) {
|
|
138
109
|
console.log("[mbkauthe] User not authenticated");
|
|
139
|
-
console.log("[mbkauthe]: ", req.session);
|
|
140
110
|
return res.render("Error/dError.handlebars", {
|
|
141
111
|
layout: false,
|
|
142
112
|
code: 401,
|
|
@@ -150,10 +120,10 @@ const checkRolePermission = (requiredRole, notAllowed) => {
|
|
|
150
120
|
const userId = req.session.user.id;
|
|
151
121
|
|
|
152
122
|
const query = `SELECT "Role" FROM "Users" WHERE "id" = $1`;
|
|
153
|
-
const result = await dblogin.query({ name: '
|
|
123
|
+
const result = await dblogin.query({ name: 'check-role-permission', text: query, values: [userId] });
|
|
154
124
|
|
|
155
125
|
if (result.rows.length === 0) {
|
|
156
|
-
return res.status(401).json({ success: false, message: "
|
|
126
|
+
return res.status(401).json({ success: false, message: "Authentication failed" });
|
|
157
127
|
}
|
|
158
128
|
|
|
159
129
|
const userRole = result.rows[0].Role;
|
|
@@ -164,22 +134,27 @@ const checkRolePermission = (requiredRole, notAllowed) => {
|
|
|
164
134
|
layout: false,
|
|
165
135
|
code: 403,
|
|
166
136
|
error: "Access Denied",
|
|
167
|
-
message:
|
|
137
|
+
message: "You are not allowed to access this resource",
|
|
168
138
|
pagename: "Home",
|
|
169
139
|
page: `/${mbkautheVar.loginRedirectURL}`
|
|
170
140
|
});
|
|
171
141
|
}
|
|
172
142
|
|
|
173
|
-
|
|
143
|
+
// Convert to array if single role provided
|
|
144
|
+
const rolesArray = Array.isArray(requiredRoles) ? requiredRoles : [requiredRoles];
|
|
145
|
+
|
|
146
|
+
// Check for "Any" or "any" role
|
|
147
|
+
if (rolesArray.includes("Any") || rolesArray.includes("any")) {
|
|
174
148
|
return next();
|
|
175
149
|
}
|
|
176
150
|
|
|
177
|
-
if
|
|
151
|
+
// Check if user role is in allowed roles
|
|
152
|
+
if (!rolesArray.includes(userRole)) {
|
|
178
153
|
return res.render("Error/dError.handlebars", {
|
|
179
154
|
layout: false,
|
|
180
155
|
code: 403,
|
|
181
156
|
error: "Access Denied",
|
|
182
|
-
message:
|
|
157
|
+
message: "You do not have permission to access this resource",
|
|
183
158
|
pagename: "Home",
|
|
184
159
|
page: `/${mbkautheVar.loginRedirectURL}`
|
|
185
160
|
});
|
|
@@ -253,7 +228,7 @@ const authapi = (requiredRole = []) => {
|
|
|
253
228
|
LIMIT 1
|
|
254
229
|
`;
|
|
255
230
|
|
|
256
|
-
const result = await
|
|
231
|
+
const result = await dblogin.query({ name: 'validate-api-key', text: jointQuery, values: [token] });
|
|
257
232
|
|
|
258
233
|
if (result.rows.length === 0) {
|
|
259
234
|
console.warn("[mbkauthe] [authapi] Invalid token or associated user inactive");
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mbkauthe",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "MBKTech's reusable authentication system for Node.js applications.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"dev": "
|
|
8
|
+
"dev": "cross-env test=dev nodemon index.js"
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -41,12 +41,15 @@
|
|
|
41
41
|
"express-session": "^1.18.1",
|
|
42
42
|
"marked": "^15.0.11",
|
|
43
43
|
"node-fetch": "^3.3.2",
|
|
44
|
+
"passport": "^0.7.0",
|
|
45
|
+
"passport-github2": "^0.1.12",
|
|
44
46
|
"path": "^0.12.7",
|
|
45
47
|
"pg": "^8.14.1",
|
|
46
48
|
"speakeasy": "^2.0.0",
|
|
47
49
|
"url": "^0.11.4"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
52
|
+
"cross-env": "^7.0.3",
|
|
50
53
|
"nodemon": "^3.1.11"
|
|
51
54
|
}
|
|
52
55
|
}
|
package/public/bg.avif
ADDED
|
Binary file
|
package/public/main.js
CHANGED
|
@@ -5,9 +5,7 @@ async function logout() {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
try {
|
|
8
|
-
//
|
|
9
|
-
await nuclearCacheClear();
|
|
10
|
-
|
|
8
|
+
// First, logout from server
|
|
11
9
|
const response = await fetch("/mbkauthe/api/logout", {
|
|
12
10
|
method: "POST",
|
|
13
11
|
headers: {
|
|
@@ -20,15 +18,15 @@ async function logout() {
|
|
|
20
18
|
const result = await response.json();
|
|
21
19
|
|
|
22
20
|
if (response.ok) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
// Then clear all caches after successful logout (except rememberedUsername)
|
|
22
|
+
await nuclearCacheClear();
|
|
23
|
+
// nuclearCacheClear already redirects, so no need for additional redirect
|
|
26
24
|
} else {
|
|
27
25
|
alert(result.message);
|
|
28
26
|
}
|
|
29
27
|
} catch (error) {
|
|
30
28
|
console.error("Error during logout:", error);
|
|
31
|
-
alert(
|
|
29
|
+
alert(`Logout failed: ${error.message}`);
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
|
package/views/2fa.handlebars
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<meta name="description"
|
|
8
|
-
content="Log in to portal.
|
|
8
|
+
content="Log in to portal.mbktech.org to access your resources and manage projects securely.">
|
|
9
9
|
<meta name="keywords" content="MBK Tech Studio, Web-Portal, Web, Portal, Admin-Panel, Admin, login">
|
|
10
10
|
<meta property="og:title" content="Login | MBK Tech Studio" />
|
|
11
|
-
<meta property="og:image" content="https://
|
|
11
|
+
<meta property="og:image" content="https://mbktech.org/Assets/Images/Icon/logo.png" />
|
|
12
12
|
<meta property="og:url" content="/mbkauthe/2fa">
|
|
13
13
|
<title>2FA | MBK Tech Studio Portal</title>
|
|
14
|
-
<link rel="icon" type="image/x-icon" href="https://
|
|
14
|
+
<link rel="icon" type="image/x-icon" href="https://mbktech.org/Assets/Images/Icon/dgicon.svg">
|
|
15
15
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
16
16
|
{{> sharedStyles}}
|
|
17
17
|
</head>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</path>
|
|
29
29
|
</g>
|
|
30
30
|
</svg>
|
|
31
|
-
<span class="logo-text">{{appName}} <span class="logo-comp">
|
|
31
|
+
<span class="logo-text">{{appName}} <span class="logo-comp">mbktech</span></span>
|
|
32
32
|
</a>
|
|
33
33
|
</div>
|
|
34
34
|
</header>
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
|
|
64
64
|
<p class="terms-info">
|
|
65
65
|
By logging in, you agree to our
|
|
66
|
-
<a href="https://portal.
|
|
66
|
+
<a href="https://portal.mbktech.org/info/Terms&Conditions" target="_blank"
|
|
67
67
|
class="terms-link">Terms & Conditions</a>
|
|
68
68
|
and
|
|
69
|
-
<a href="https://portal.
|
|
69
|
+
<a href="https://portal.mbktech.org/info/PrivacyPolicy" target="_blank"
|
|
70
70
|
class="terms-link">Privacy Policy</a>.
|
|
71
71
|
</p>
|
|
72
72
|
</form>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>{{code}} - {{error}}</title>
|
|
8
|
-
<link rel="icon" type="image/x-icon" href="https://
|
|
8
|
+
<link rel="icon" type="image/x-icon" href="https://mbktech.org/Assets/Images/Icon/dgicon.svg">
|
|
9
9
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
10
10
|
{{> sharedStyles}}
|
|
11
11
|
<style>
|
|
@@ -186,8 +186,8 @@
|
|
|
186
186
|
</path>
|
|
187
187
|
</g>
|
|
188
188
|
</svg>
|
|
189
|
-
<span class="logo-text">{{#if app}}{{app}}{{else}}
|
|
190
|
-
class="logo-comp">
|
|
189
|
+
<span class="logo-text">{{#if app}}{{app}}{{else}}mbkauthe{{/if}} <span
|
|
190
|
+
class="logo-comp">mbktech</span></span>
|
|
191
191
|
</a>
|
|
192
192
|
</div>
|
|
193
193
|
</header>
|
package/views/info.handlebars
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>Version and Configuration Information</title>
|
|
8
|
-
<link rel="icon" type="image/x-icon" href="https://
|
|
8
|
+
<link rel="icon" type="image/x-icon" href="https://mbktech.org/Assets/Images/Icon/dgicon.svg">
|
|
9
9
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
10
10
|
{{> sharedStyles}}
|
|
11
11
|
<style>
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
</path>
|
|
185
185
|
</g>
|
|
186
186
|
</svg>
|
|
187
|
-
<span class="logo-text">{{mbkautheVar.APP_NAME}} <span class="logo-comp">
|
|
187
|
+
<span class="logo-text">{{mbkautheVar.APP_NAME}} <span class="logo-comp">mbktech</span></span>
|
|
188
188
|
</a>
|
|
189
189
|
</div>
|
|
190
190
|
</header>
|
|
@@ -224,6 +224,16 @@
|
|
|
224
224
|
<div class="info-value">{{mbkautheVar.APP_NAME}}</div>
|
|
225
225
|
</div>
|
|
226
226
|
<div class="info-row">
|
|
227
|
+
<div class="info-label">Domain:</div>
|
|
228
|
+
<div class="info-value">{{mbkautheVar.DOMAIN}}</div>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="info-row">
|
|
231
|
+
<div class="info-label">Login Redirect URL:</div>
|
|
232
|
+
<div class="info-value">{{mbkautheVar.loginRedirectURL}}</div>
|
|
233
|
+
</div>
|
|
234
|
+
{{#if authorized}}
|
|
235
|
+
|
|
236
|
+
<div class="info-row">
|
|
227
237
|
<div class="info-label">Two Factor Authentication:</div>
|
|
228
238
|
<div class="info-value">{{mbkautheVar.MBKAUTH_TWO_FA_ENABLE}}</div>
|
|
229
239
|
</div>
|
|
@@ -235,14 +245,7 @@
|
|
|
235
245
|
<div class="info-label">Deployment Status:</div>
|
|
236
246
|
<div class="info-value">{{mbkautheVar.IS_DEPLOYED}}</div>
|
|
237
247
|
</div>
|
|
238
|
-
|
|
239
|
-
<div class="info-label">Domain:</div>
|
|
240
|
-
<div class="info-value">{{mbkautheVar.DOMAIN}}</div>
|
|
241
|
-
</div>
|
|
242
|
-
<div class="info-row">
|
|
243
|
-
<div class="info-label">Login Redirect URL:</div>
|
|
244
|
-
<div class="info-value">{{mbkautheVar.loginRedirectURL}}</div>
|
|
245
|
-
</div>
|
|
248
|
+
{{/if}}
|
|
246
249
|
</div>
|
|
247
250
|
</div>
|
|
248
251
|
</section>
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<meta name="description"
|
|
8
|
-
content="Log in to portal.
|
|
8
|
+
content="Log in to portal.mbktech.org to access your resources and manage projects securely.">
|
|
9
9
|
<meta name="keywords" content="MBK Tech Studio, Web-Portal, Web, Portal, Admin-Panel, Admin, login">
|
|
10
10
|
<meta property="og:title" content="Login | MBK Tech Studio" />
|
|
11
|
-
<meta property="og:image" content="https://
|
|
11
|
+
<meta property="og:image" content="https://mbktech.org/Assets/Images/Icon/logo.png" />
|
|
12
12
|
<meta property="og:url" content="/mbkauthe/login">
|
|
13
13
|
<title>Login | MBK Tech Studio Portal</title>
|
|
14
|
-
<link rel="icon" type="image/x-icon" href="https://
|
|
14
|
+
<link rel="icon" type="image/x-icon" href="https://mbktech.org/Assets/Images/Icon/dgicon.svg">
|
|
15
15
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
16
16
|
{{> sharedStyles}}
|
|
17
17
|
</head>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</path>
|
|
29
29
|
</g>
|
|
30
30
|
</svg>
|
|
31
|
-
<span class="logo-text">{{appName}} <span class="logo-comp">
|
|
31
|
+
<span class="logo-text">{{appName}} <span class="logo-comp">mbktech</span></span>
|
|
32
32
|
</a>
|
|
33
33
|
</div>
|
|
34
34
|
</header>
|
|
@@ -68,17 +68,16 @@
|
|
|
68
68
|
<button type="submit" class="btn-login" id="loginButton">
|
|
69
69
|
<span id="loginButtonText">Login</span>
|
|
70
70
|
</button>
|
|
71
|
-
{{#if githubLoginEnabled }}
|
|
72
71
|
<div class="social-login">
|
|
73
72
|
<div class="divider">
|
|
74
73
|
<span>or</span>
|
|
75
74
|
</div>
|
|
76
|
-
|
|
75
|
+
<!-- Use JS to initiate GitHub login and pass redirect param to backend -->
|
|
76
|
+
<a type="button" id="githubLoginBtn" class="btn-github">
|
|
77
77
|
<i class="fab fa-github"></i>
|
|
78
78
|
<span>Continue with GitHub</span>
|
|
79
79
|
</a>
|
|
80
80
|
</div>
|
|
81
|
-
{{/if }}
|
|
82
81
|
|
|
83
82
|
<div class="remember-me">
|
|
84
83
|
<input type="checkbox" id="rememberMe" name="rememberMe">
|
|
@@ -94,16 +93,16 @@
|
|
|
94
93
|
{{/if }}
|
|
95
94
|
|
|
96
95
|
<div class="login-links">
|
|
97
|
-
<a href="https://portal.
|
|
98
|
-
<a href="https://
|
|
96
|
+
<a href="https://portal.mbktech.org/forgot-password" class="login-link">Forgot Password?</a>
|
|
97
|
+
<a href="https://mbktech.org/Support" target="_blank" class="login-link">Need Help?</a>
|
|
99
98
|
</div>
|
|
100
99
|
|
|
101
100
|
<p class="terms-info">
|
|
102
101
|
By logging in, you agree to our
|
|
103
|
-
<a href="https://portal.
|
|
102
|
+
<a href="https://portal.mbktech.org/info/Terms&Conditions" target="_blank"
|
|
104
103
|
class="terms-link">Terms & Conditions</a>
|
|
105
104
|
and
|
|
106
|
-
<a href="https://portal.
|
|
105
|
+
<a href="https://portal.mbktech.org/info/PrivacyPolicy" target="_blank"
|
|
107
106
|
class="terms-link">Privacy Policy</a>.
|
|
108
107
|
</p>
|
|
109
108
|
</form>
|
|
@@ -128,13 +127,13 @@
|
|
|
128
127
|
});
|
|
129
128
|
|
|
130
129
|
function fpass() {
|
|
131
|
-
showMessage(`If you have forgotten your password, please contact support at <a href="https://
|
|
130
|
+
showMessage(`If you have forgotten your password, please contact support at <a href="https://mbktech.org/Support" target="_blank">https://mbktech.org/Support</a> to reset it.`, `Forgot Password`);
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
// Info dialogs
|
|
135
134
|
function usernameinfo() {
|
|
136
|
-
showMessage(`Your username is the part of your MBK Tech Studio email before the @ (e.g., abc.xyz@
|
|
137
|
-
→ abc.xyz). For guests or if you’ve forgotten your credentials, contact <a href="https://
|
|
135
|
+
showMessage(`Your username is the part of your MBK Tech Studio email before the @ (e.g., abc.xyz@mbktech.org
|
|
136
|
+
→ abc.xyz). For guests or if you’ve forgotten your credentials, contact <a href="https://mbktech.org/Support">Support</a>.`, `What is my username?`);
|
|
138
137
|
}
|
|
139
138
|
|
|
140
139
|
function tokeninfo() {
|
|
@@ -272,6 +271,45 @@
|
|
|
272
271
|
document.getElementById('loginPassword').focus();
|
|
273
272
|
}
|
|
274
273
|
});
|
|
274
|
+
|
|
275
|
+
// GitHub login: Attempt to POST redirect to backend, fallback to direct navigation
|
|
276
|
+
async function startGithubLogin() {
|
|
277
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
278
|
+
const redirect = urlParams.get('redirect') || '{{customURL}}';
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
// Try POSTing to the backend so it can establish any session state
|
|
282
|
+
const resp = await fetch('/mbkauthe/api/github/login', {
|
|
283
|
+
method: 'POST',
|
|
284
|
+
headers: { 'Content-Type': 'application/json' },
|
|
285
|
+
credentials: 'include',
|
|
286
|
+
body: JSON.stringify({ redirect })
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// If backend responds with a JSON containing redirectUrl, navigate there
|
|
290
|
+
if (resp.ok) {
|
|
291
|
+
// If server redirected directly (resp.redirected), follow the final URL
|
|
292
|
+
if (resp.redirected) {
|
|
293
|
+
window.location.href = resp.url;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const data = await resp.json().catch(() => null);
|
|
297
|
+
if (data && data.redirectUrl) {
|
|
298
|
+
window.location.href = data.redirectUrl;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
} catch (error) {
|
|
303
|
+
// swallow and fallback to direct navigation
|
|
304
|
+
console.warn('[mbkauthe] GitHub login POST failed, falling back to direct redirect', error);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Fallback: navigate to the backend GET endpoint with redirect query
|
|
308
|
+
window.location.href = `/mbkauthe/api/github/login?redirect=${encodeURIComponent(redirect)}`;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const githubBtn = document.getElementById('githubLoginBtn');
|
|
312
|
+
if (githubBtn) githubBtn.addEventListener('click', startGithubLogin);
|
|
275
313
|
</script>
|
|
276
314
|
</body>
|
|
277
315
|
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
left: 0;
|
|
99
99
|
width: 100%;
|
|
100
100
|
height: 100%;
|
|
101
|
-
background: url(
|
|
101
|
+
background: url(/mbkauthe/bg.avif) center/cover no-repeat;
|
|
102
102
|
opacity: .1;
|
|
103
103
|
z-index: 0;
|
|
104
104
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
document.querySelector(".showmessageWindow .error-code").style.display = "none";
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
document.querySelector(".showmessageWindow .error-code").href = `https://
|
|
23
|
+
document.querySelector(".showmessageWindow .error-code").href = `https://mbktech.org/ErrorCode/#${errorCode}`;
|
|
24
24
|
*/
|
|
25
25
|
document
|
|
26
26
|
.querySelector(".showMessageblurWindow")
|