mbkauthe 3.0.0 → 3.2.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/docs/db.md CHANGED
@@ -1,7 +1,7 @@
1
- # GitHub Login Setup Guide
1
+ # OAuth Login Setup Guide
2
2
 
3
3
  ## Overview
4
- This GitHub login feature allows users to authenticate using their GitHub account if it's already linked to their account in the system. Users must first connect their GitHub account through the regular account linking process, then they can use GitHub to log in directly.
4
+ This OAuth login feature allows users to authenticate using their GitHub or Google account if it's already linked to their account in the system. Users must first connect their OAuth account through the regular account linking process, then they can use it to log in directly.
5
5
 
6
6
  ## Setup Instructions
7
7
 
@@ -12,6 +12,10 @@ Add these to your `.env` file:
12
12
  # GitHub OAuth App Configuration
13
13
  GITHUB_CLIENT_ID=your_github_client_id
14
14
  GITHUB_CLIENT_SECRET=your_github_client_secret
15
+
16
+ # Google OAuth App Configuration
17
+ GOOGLE_CLIENT_ID=your_google_client_id
18
+ GOOGLE_CLIENT_SECRET=your_google_client_secret
15
19
  ```
16
20
 
17
21
  ### 2. GitHub OAuth App Setup
@@ -20,10 +24,20 @@ GITHUB_CLIENT_SECRET=your_github_client_secret
20
24
  3. Set the Authorization callback URL to: `https://yourdomain.com/mbkauthe/api/github/login/callback`
21
25
  4. Copy the Client ID and Client Secret to your `.env` file
22
26
 
23
- ### 3. Database Schema
24
- Ensure your `user_github` table exists with these columns:
27
+ ### 3. Google OAuth App Setup
28
+ 1. Go to Google Cloud Console (https://console.cloud.google.com/)
29
+ 2. Create a new project or select an existing one
30
+ 3. Enable the Google+ API
31
+ 4. Go to Credentials > Create Credentials > OAuth 2.0 Client ID
32
+ 5. Set the application type to "Web application"
33
+ 6. Add authorized redirect URI: `https://yourdomain.com/mbkauthe/api/google/login/callback`
34
+ 7. Copy the Client ID and Client Secret to your `.env` file
35
+
36
+ ### 4. Database Schema
37
+ Ensure your OAuth tables exist with these columns:
25
38
 
26
39
  ```sql
40
+ -- GitHub users table
27
41
  CREATE TABLE user_github (
28
42
  id SERIAL PRIMARY KEY,
29
43
  user_name VARCHAR(50) REFERENCES "Users"("UserName"),
@@ -37,57 +51,98 @@ CREATE TABLE user_github (
37
51
  -- Add indexes for performance optimization
38
52
  CREATE INDEX IF NOT EXISTS idx_user_github_github_id ON user_github (github_id);
39
53
  CREATE INDEX IF NOT EXISTS idx_user_github_user_name ON user_github (user_name);
54
+
55
+ -- Google users table
56
+ CREATE TABLE user_google (
57
+ id SERIAL PRIMARY KEY,
58
+ user_name VARCHAR(50) REFERENCES "Users"("UserName"),
59
+ google_id VARCHAR(255) UNIQUE,
60
+ google_email VARCHAR(255),
61
+ access_token VARCHAR(255),
62
+ created_at TimeStamp WITH TIME ZONE DEFAULT NOW(),
63
+ updated_at TimeStamp WITH TIME ZONE DEFAULT NOW()
64
+ );
65
+
66
+ -- Add indexes for performance optimization
67
+ CREATE INDEX IF NOT EXISTS idx_user_google_google_id ON user_google (google_id);
68
+ CREATE INDEX IF NOT EXISTS idx_user_google_user_name ON user_google (user_name);
40
69
  ```
41
70
 
42
71
  ## How It Works
43
72
 
44
- ### Login Flow
45
- 1. User clicks "Login with GitHub" on the login page
46
- 2. User is redirected to GitHub for authentication
47
- 3. GitHub redirects back to `/mbkauthe/api/github/login/callback`
48
- 4. System checks if the GitHub ID exists in `user_github` table
73
+ ### Login Flow (GitHub/Google)
74
+ 1. User clicks "Login with GitHub" or "Login with Google" on the login page
75
+ 2. User is redirected to the OAuth provider for authentication
76
+ 3. Provider redirects back to `/mbkauthe/api/{provider}/login/callback`
77
+ 4. System checks if the OAuth ID exists in the respective `user_{provider}` table
49
78
  5. If found and user is active/authorized:
50
79
  - If 2FA is enabled, redirect to 2FA page
51
80
  - If no 2FA, complete login and redirect to home
52
81
  6. If not found, redirect to login page with error
53
82
 
54
83
  ### Account Linking
55
- Users must first link their GitHub account through your existing GitHub connection system (likely in user settings) before they can use GitHub login.
84
+ Users must first link their OAuth account through your existing connection system (likely in user settings) before they can use OAuth login.
56
85
 
57
86
  ## API Routes Added
58
87
 
59
- ### `/mbkauthe/api/github/login`
88
+ ### GitHub Routes
89
+
90
+ #### `/mbkauthe/api/github/login`
60
91
  - **Method**: GET
61
92
  - **Description**: Initiates GitHub OAuth flow
62
93
  - **Redirects to**: GitHub authorization page
63
94
 
64
- ### `/mbkauthe/api/github/login/callback`
95
+ #### `/mbkauthe/api/github/login/callback`
65
96
  - **Method**: GET
66
97
  - **Description**: Handles GitHub OAuth callback
67
98
  - **Parameters**: `code` (from GitHub), `state` (optional)
68
99
  - **Success**: Redirects to home page or configured redirect URL
69
100
  - **Error**: Redirects to login page with error parameter
70
101
 
102
+ ### Google Routes
103
+
104
+ #### `/mbkauthe/api/google/login`
105
+ - **Method**: GET
106
+ - **Description**: Initiates Google OAuth flow
107
+ - **Redirects to**: Google authorization page
108
+
109
+ #### `/mbkauthe/api/google/login/callback`
110
+ - **Method**: GET
111
+ - **Description**: Handles Google OAuth callback
112
+ - **Parameters**: `code` (from Google), `state` (optional)
113
+ - **Success**: Redirects to home page or configured redirect URL
114
+ - **Error**: Redirects to login page with error parameter
115
+
71
116
  ## Error Handling
72
117
 
73
118
  The system handles various error cases:
74
- - `github_auth_failed`: GitHub OAuth failed
75
- - `user_not_found`: GitHub account not linked to any user
119
+ - `github_auth_failed` / `google_auth_failed`: OAuth authentication failed
120
+ - `user_not_found`: OAuth account not linked to any user
121
+ - `account_inactive`: User account is deactivated
122
+ - `not_authorized`: User not authorized for this app
76
123
  - `session_error`: Session save failed
77
124
  - `internal_error`: General server error
78
125
 
79
126
  ## Testing
80
127
 
128
+ ### GitHub Login
81
129
  1. Create a test user in your `Users` table
82
130
  2. Link a GitHub account to that user using your existing connection system
83
131
  3. Try logging in with GitHub using the new login button
84
132
  4. Check console logs for debugging information
85
133
 
134
+ ### Google Login
135
+ 1. Create a test user in your `Users` table
136
+ 2. Link a Google account to that user using your existing connection system
137
+ 3. Try logging in with Google using the new login button
138
+ 4. Check console logs for debugging information
139
+
86
140
  ## Login Page Updates
87
141
 
88
142
  The login page now includes:
89
143
  - A "Continue with GitHub" button
90
- - A divider ("or") between regular and GitHub login
144
+ - A "Continue with Google" button
145
+ - A divider ("or") between regular and OAuth login
91
146
  - Proper styling that matches your existing design
92
147
 
93
148
  ## Security Notes
@@ -96,7 +151,7 @@ The login page now includes:
96
151
  - App authorization is checked (same as regular login)
97
152
  - 2FA is respected if enabled
98
153
  - Session management is handled the same way as regular login
99
- - GitHub access tokens are stored securely
154
+ - OAuth access tokens are stored securely
100
155
 
101
156
  ## Troubleshooting
102
157
 
package/docs/env.md CHANGED
@@ -230,16 +230,18 @@ DEVICE_TRUST_DURATION_DAYS=30 # 30 days (convenience)
230
230
 
231
231
  ---
232
232
 
233
- ## 🐙 GitHub OAuth Authentication
233
+ ## 🔐 OAuth Authentication
234
234
 
235
- ### GitHub Login Configuration
235
+ ### GitHub OAuth Authentication
236
+
237
+ #### GitHub Login Configuration
236
238
  ```env
237
239
  GITHUB_LOGIN_ENABLED=false
238
240
  GITHUB_CLIENT_ID=your-github-client-id
239
241
  GITHUB_CLIENT_SECRET=your-github-client-secret
240
242
  ```
241
243
 
242
- #### GITHUB_LOGIN_ENABLED
244
+ ##### GITHUB_LOGIN_ENABLED
243
245
  **Description:** Enables or disables GitHub OAuth login functionality.
244
246
 
245
247
  **Values:**
@@ -248,7 +250,7 @@ GITHUB_CLIENT_SECRET=your-github-client-secret
248
250
 
249
251
  **Required:** Yes (if using GitHub authentication)
250
252
 
251
- #### GITHUB_CLIENT_ID
253
+ ##### GITHUB_CLIENT_ID
252
254
  **Description:** OAuth application client ID from GitHub.
253
255
 
254
256
  - **Purpose:** Identifies your application to GitHub's OAuth service
@@ -258,7 +260,7 @@ GITHUB_CLIENT_SECRET=your-github-client-secret
258
260
 
259
261
  **Example:** `GITHUB_CLIENT_ID=Iv1.a1b2c3d4e5f6g7h8`
260
262
 
261
- #### GITHUB_CLIENT_SECRET
263
+ ##### GITHUB_CLIENT_SECRET
262
264
  **Description:** OAuth application client secret from GitHub.
263
265
 
264
266
  - **Purpose:** Authenticates your application with GitHub's OAuth service
@@ -269,7 +271,7 @@ GITHUB_CLIENT_SECRET=your-github-client-secret
269
271
 
270
272
  **Example:** `GITHUB_CLIENT_SECRET=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0`
271
273
 
272
- ### Setting Up GitHub OAuth
274
+ #### Setting Up GitHub OAuth
273
275
 
274
276
  1. **Create GitHub OAuth App:**
275
277
  - Go to [GitHub Developer Settings](https://github.com/settings/developers)
@@ -277,7 +279,7 @@ GITHUB_CLIENT_SECRET=your-github-client-secret
277
279
  - Fill in application details:
278
280
  - **Application name:** Your app name
279
281
  - **Homepage URL:** `https://yourdomain.com` (or `http://localhost:3000` for dev)
280
- - **Authorization callback URL:** `https://yourdomain.com/auth/github/callback`
282
+ - **Authorization callback URL:** `https://yourdomain.com/mbkauthe/api/github/login/callback`
281
283
  - Click "Register application"
282
284
 
283
285
  2. **Copy Credentials:**
@@ -291,10 +293,91 @@ GITHUB_CLIENT_SECRET=your-github-client-secret
291
293
  GITHUB_CLIENT_SECRET=your-copied-client-secret
292
294
  ```
293
295
 
294
- **Security Notes:**
296
+ ---
297
+
298
+ ### Google OAuth Authentication
299
+
300
+ #### Google Login Configuration
301
+ ```env
302
+ GOOGLE_LOGIN_ENABLED=false
303
+ GOOGLE_CLIENT_ID=your-google-client-id
304
+ GOOGLE_CLIENT_SECRET=your-google-client-secret
305
+ ```
306
+
307
+ ##### GOOGLE_LOGIN_ENABLED
308
+ **Description:** Enables or disables Google OAuth login functionality.
309
+
310
+ **Values:**
311
+ - `true` - Enable Google login (users can authenticate via Google)
312
+ - `false` - Disable Google login (default)
313
+
314
+ **Required:** Yes (if using Google authentication)
315
+
316
+ ##### GOOGLE_CLIENT_ID
317
+ **Description:** OAuth 2.0 client ID from Google Cloud Console.
318
+
319
+ - **Purpose:** Identifies your application to Google's OAuth service
320
+ - **Format:** String ending in `.apps.googleusercontent.com`
321
+ - **Setup:** Obtain from [Google Cloud Console](https://console.cloud.google.com/)
322
+ - **Required:** Yes (when `GOOGLE_LOGIN_ENABLED=true`)
323
+
324
+ **Example:** `GOOGLE_CLIENT_ID=123456789-abc123def456.apps.googleusercontent.com`
325
+
326
+ ##### GOOGLE_CLIENT_SECRET
327
+ **Description:** OAuth 2.0 client secret from Google Cloud Console.
328
+
329
+ - **Purpose:** Authenticates your application with Google's OAuth service
330
+ - **Security:** Keep this secret secure and never commit to version control
331
+ - **Format:** Alphanumeric string provided by Google
332
+ - **Setup:** Generated when creating OAuth credentials in Google Cloud Console
333
+ - **Required:** Yes (when `GOOGLE_LOGIN_ENABLED=true`)
334
+
335
+ **Example:** `GOOGLE_CLIENT_SECRET=GOCSPX-abc123def456ghi789jkl012mno`
336
+
337
+ #### Setting Up Google OAuth
338
+
339
+ 1. **Create Google Cloud Project:**
340
+ - Go to [Google Cloud Console](https://console.cloud.google.com/)
341
+ - Create a new project or select an existing one
342
+ - Enable the Google+ API (or People API)
343
+
344
+ 2. **Configure OAuth Consent Screen:**
345
+ - Navigate to "OAuth consent screen" in the sidebar
346
+ - Choose "External" user type (or "Internal" for Google Workspace)
347
+ - Fill in required app information
348
+ - Add your domain to authorized domains
349
+ - Save and continue
350
+
351
+ 3. **Create OAuth Credentials:**
352
+ - Navigate to "Credentials" in the sidebar
353
+ - Click "Create Credentials" > "OAuth 2.0 Client ID"
354
+ - Choose "Web application" as application type
355
+ - Add authorized JavaScript origins:
356
+ - `https://yourdomain.com`
357
+ - `http://localhost:3000` (for development)
358
+ - Add authorized redirect URIs:
359
+ - `https://yourdomain.com/mbkauthe/api/google/login/callback`
360
+ - `http://localhost:3000/mbkauthe/api/google/login/callback` (for development)
361
+ - Click "Create"
362
+
363
+ 4. **Copy Credentials:**
364
+ - Copy the **Client ID**
365
+ - Copy the **Client Secret**
366
+
367
+ 5. **Configure Environment:**
368
+ ```env
369
+ GOOGLE_LOGIN_ENABLED=true
370
+ GOOGLE_CLIENT_ID=your-copied-client-id
371
+ GOOGLE_CLIENT_SECRET=your-copied-client-secret
372
+ ```
373
+
374
+ ### OAuth Security Notes
375
+
295
376
  - Use separate OAuth apps for development and production environments
296
377
  - Rotate client secrets periodically
297
378
  - Never expose client secrets in client-side code
379
+ - Ensure callback URLs match exactly with OAuth provider configuration
380
+ - Users must link their OAuth accounts before they can use OAuth login
298
381
 
299
382
  ---
300
383
 
package/index.d.ts CHANGED
@@ -5,6 +5,44 @@
5
5
  import { Request, Response, NextFunction, Router } from 'express';
6
6
  import { Pool } from 'pg';
7
7
 
8
+ // Global augmentations must be at the top level, outside any declare module blocks
9
+ declare global {
10
+ namespace Express {
11
+ interface Request {
12
+ user?: {
13
+ username: string;
14
+ UserName: string;
15
+ role: 'SuperAdmin' | 'NormalUser' | 'Guest';
16
+ Role: 'SuperAdmin' | 'NormalUser' | 'Guest';
17
+ };
18
+ userRole?: 'SuperAdmin' | 'NormalUser' | 'Guest';
19
+ }
20
+
21
+ interface Session {
22
+ user?: {
23
+ id: number;
24
+ username: string;
25
+ UserName: string;
26
+ role: 'SuperAdmin' | 'NormalUser' | 'Guest';
27
+ Role: 'SuperAdmin' | 'NormalUser' | 'Guest';
28
+ sessionId: string;
29
+ allowedApps?: string[];
30
+ };
31
+ preAuthUser?: {
32
+ id: number;
33
+ username: string;
34
+ UserName?: string;
35
+ role: 'SuperAdmin' | 'NormalUser' | 'Guest';
36
+ Role?: 'SuperAdmin' | 'NormalUser' | 'Guest';
37
+ loginMethod?: 'password' | 'github' | 'google';
38
+ redirectUrl?: string | null;
39
+ };
40
+ oauthRedirect?: string;
41
+ oauthCsrfToken?: string;
42
+ }
43
+ }
44
+ }
45
+
8
46
  declare module 'mbkauthe' {
9
47
  // Configuration Types
10
48
  export interface MBKAuthConfig {
@@ -20,10 +58,22 @@ declare module 'mbkauthe' {
20
58
  GITHUB_LOGIN_ENABLED?: 'true' | 'false' | 'f';
21
59
  GITHUB_CLIENT_ID?: string;
22
60
  GITHUB_CLIENT_SECRET?: string;
61
+ GOOGLE_LOGIN_ENABLED?: 'true' | 'false' | 'f';
62
+ GOOGLE_CLIENT_ID?: string;
63
+ GOOGLE_CLIENT_SECRET?: string;
23
64
  loginRedirectURL?: string;
24
65
  EncPass?: 'true' | 'false' | 'f';
25
66
  }
26
67
 
68
+ export interface OAuthConfig {
69
+ GITHUB_LOGIN_ENABLED?: 'true' | 'false' | 'f';
70
+ GITHUB_CLIENT_ID?: string;
71
+ GITHUB_CLIENT_SECRET?: string;
72
+ GOOGLE_LOGIN_ENABLED?: 'true' | 'false' | 'f';
73
+ GOOGLE_CLIENT_ID?: string;
74
+ GOOGLE_CLIENT_SECRET?: string;
75
+ }
76
+
27
77
  // User Types
28
78
  export type UserRole = 'SuperAdmin' | 'NormalUser' | 'Guest';
29
79
 
@@ -43,7 +93,7 @@ declare module 'mbkauthe' {
43
93
  UserName?: string;
44
94
  role: UserRole;
45
95
  Role?: UserRole;
46
- loginMethod?: 'password' | 'github';
96
+ loginMethod?: 'password' | 'github' | 'google';
47
97
  redirectUrl?: string | null;
48
98
  }
49
99
 
@@ -90,24 +140,14 @@ declare module 'mbkauthe' {
90
140
  updated_at: Date;
91
141
  }
92
142
 
93
- // Request Extensions
94
- declare global {
95
- namespace Express {
96
- interface Request {
97
- user?: {
98
- username: string;
99
- UserName: string;
100
- role: UserRole;
101
- Role: UserRole;
102
- };
103
- }
104
-
105
- interface Session {
106
- user?: SessionUser;
107
- preAuthUser?: PreAuthUser;
108
- oauthRedirect?: string;
109
- }
110
- }
143
+ export interface GoogleUser {
144
+ id: number;
145
+ user_name: string;
146
+ google_id: string;
147
+ google_email: string;
148
+ access_token: string;
149
+ created_at: Date;
150
+ updated_at: Date;
111
151
  }
112
152
 
113
153
  // API Response Types
@@ -177,8 +217,6 @@ declare module 'mbkauthe' {
177
217
 
178
218
  export function authenticate(token: string): AuthMiddleware;
179
219
 
180
- export function authapi(requiredRole?: UserRole[]): AuthMiddleware;
181
-
182
220
  // Utility Functions
183
221
  export function renderError(
184
222
  res: Response,
@@ -28,6 +28,38 @@ function validateConfiguration() {
28
28
  throw new Error(`[mbkauthe] Configuration Error:\n - ${errors.join('\n - ')}`);
29
29
  }
30
30
 
31
+ // Parse and validate oAuthVar (optional fallback for OAuth settings)
32
+ let oAuthVar = null;
33
+ try {
34
+ if (process.env.oAuthVar) {
35
+ oAuthVar = JSON.parse(process.env.oAuthVar);
36
+ if (oAuthVar && typeof oAuthVar !== 'object') {
37
+ console.warn('[mbkauthe] oAuthVar is not a valid object, ignoring it');
38
+ oAuthVar = null;
39
+ } else {
40
+ console.log('[mbkauthe] oAuthVar detected and parsed successfully');
41
+ }
42
+ }
43
+ } catch (error) {
44
+ console.warn('[mbkauthe] Invalid JSON in process.env.oAuthVar, ignoring it');
45
+ oAuthVar = null;
46
+ }
47
+
48
+ // Merge OAuth settings: use oAuthVar as fallback if values not in mbkautheVar
49
+ const oAuthKeys = [
50
+ 'GITHUB_LOGIN_ENABLED', 'GITHUB_CLIENT_ID', 'GITHUB_CLIENT_SECRET',
51
+ 'GOOGLE_LOGIN_ENABLED', 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET'
52
+ ];
53
+
54
+ if (oAuthVar) {
55
+ oAuthKeys.forEach(key => {
56
+ if ((!mbkautheVar[key] || (typeof mbkautheVar[key] === 'string' && mbkautheVar[key].trim() === '')) && oAuthVar[key]) {
57
+ mbkautheVar[key] = oAuthVar[key];
58
+ console.log(`[mbkauthe] Using ${key} from oAuthVar`);
59
+ }
60
+ });
61
+ }
62
+
31
63
  // Validate required keys
32
64
  // COOKIE_EXPIRE_TIME is not required but if provided must be valid, COOKIE_EXPIRE_TIME by default is 2 days
33
65
  // loginRedirectURL is not required but if provided must be valid, loginRedirectURL by default is /dashboard
@@ -55,6 +87,11 @@ function validateConfiguration() {
55
87
  errors.push("mbkautheVar.GITHUB_LOGIN_ENABLED must be either 'true' or 'false' or 'f'");
56
88
  }
57
89
 
90
+ // Validate GOOGLE_LOGIN_ENABLED value
91
+ if (mbkautheVar.GOOGLE_LOGIN_ENABLED && !['true', 'false', 'f'].includes(mbkautheVar.GOOGLE_LOGIN_ENABLED.toLowerCase())) {
92
+ errors.push("mbkautheVar.GOOGLE_LOGIN_ENABLED must be either 'true' or 'false' or 'f'");
93
+ }
94
+
58
95
  // Validate EncPass value if provided
59
96
  if (mbkautheVar.EncPass && !['true', 'false', 'f'].includes(mbkautheVar.EncPass.toLowerCase())) {
60
97
  errors.push("mbkautheVar.EncPass must be either 'true' or 'false' or 'f'");
@@ -70,6 +107,16 @@ function validateConfiguration() {
70
107
  }
71
108
  }
72
109
 
110
+ // Validate Google login configuration
111
+ if (mbkautheVar.GOOGLE_LOGIN_ENABLED === "true") {
112
+ if (!mbkautheVar.GOOGLE_CLIENT_ID || mbkautheVar.GOOGLE_CLIENT_ID.trim() === '') {
113
+ errors.push("mbkautheVar.GOOGLE_CLIENT_ID is required when GOOGLE_LOGIN_ENABLED is 'true'");
114
+ }
115
+ if (!mbkautheVar.GOOGLE_CLIENT_SECRET || mbkautheVar.GOOGLE_CLIENT_SECRET.trim() === '') {
116
+ errors.push("mbkautheVar.GOOGLE_CLIENT_SECRET is required when GOOGLE_LOGIN_ENABLED is 'true'");
117
+ }
118
+ }
119
+
73
120
  // Validate COOKIE_EXPIRE_TIME if provided
74
121
  if (mbkautheVar.COOKIE_EXPIRE_TIME !== undefined) {
75
122
  const expireTime = parseFloat(mbkautheVar.COOKIE_EXPIRE_TIME);
@@ -133,4 +180,4 @@ try {
133
180
  }
134
181
  }
135
182
 
136
- export { packageJson, appVersion };
183
+ export { packageJson, appVersion };
package/lib/main.js CHANGED
@@ -2,7 +2,6 @@ import express from "express";
2
2
  import session from "express-session";
3
3
  import cookieParser from "cookie-parser";
4
4
  import passport from 'passport';
5
- import { packageJson } from "./config/index.js";
6
5
  import {
7
6
  sessionConfig,
8
7
  corsMiddleware,
@@ -12,9 +11,26 @@ import {
12
11
  import authRoutes from "./routes/auth.js";
13
12
  import oauthRoutes from "./routes/oauth.js";
14
13
  import miscRoutes from "./routes/misc.js";
14
+ import { fileURLToPath } from "url";
15
+ import path from "path";
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
+
15
19
 
16
20
  const router = express.Router();
17
21
 
22
+ // Configure Express to trust proxy headers for rate limiting in dev mode only
23
+ // This prevents conflicts with parent project proxy settings in production
24
+ if (process.env.test === "dev") {
25
+ router.use((req, res, next) => {
26
+ // Set trust proxy to true for the app instance if not already set
27
+ if (!req.app.get('trust proxy')) {
28
+ req.app.set('trust proxy', true);
29
+ }
30
+ next();
31
+ });
32
+ }
33
+
18
34
  // Basic middleware
19
35
  router.use(express.json());
20
36
  router.use(express.urlencoded({ extended: true }));
@@ -48,5 +64,15 @@ router.get(["/login", "/signin"], async (req, res) => {
48
64
  return res.redirect(redirectUrl);
49
65
  });
50
66
 
67
+ router.get('/icon.svg', (req, res) => {
68
+ res.setHeader('Cache-Control', 'public, max-age=31536000');
69
+ res.sendFile(path.join(__dirname, '..', 'public', 'icon.svg'));
70
+ });
71
+
72
+ router.get(['/favicon.ico', '/icon.ico'], (req, res) => {
73
+ res.setHeader('Cache-Control', 'public, max-age=31536000');
74
+ res.sendFile(path.join(__dirname, '..', 'public', 'icon.ico'));
75
+ });
76
+
51
77
  export { getLatestVersion } from "./routes/misc.js";
52
78
  export default router;
@@ -18,9 +18,11 @@ export const sessionConfig = {
18
18
  proxy: true,
19
19
  cookie: {
20
20
  maxAge: mbkautheVar.COOKIE_EXPIRE_TIME * 24 * 60 * 60 * 1000,
21
- domain: mbkautheVar.IS_DEPLOYED === 'true' ? `.${mbkautheVar.DOMAIN}` : undefined,
21
+ // Don't set domain in development/localhost to avoid cookie issues
22
+ domain: (mbkautheVar.IS_DEPLOYED === 'true' && process.env.test !== 'dev') ? `.${mbkautheVar.DOMAIN}` : undefined,
22
23
  httpOnly: true,
23
- secure: mbkautheVar.IS_DEPLOYED === 'true',
24
+ // Only use secure cookies in production with HTTPS
25
+ secure: mbkautheVar.IS_DEPLOYED === 'true' && process.env.test !== 'dev',
24
26
  sameSite: 'lax',
25
27
  path: '/'
26
28
  },
@@ -22,19 +22,31 @@ const LoginLimit = rateLimit({
22
22
  message: { success: false, message: "Too many attempts, please try again later" },
23
23
  skip: (req) => {
24
24
  return !!req.session.user;
25
+ },
26
+ validate: {
27
+ trustProxy: false,
28
+ xForwardedForHeader: false
25
29
  }
26
30
  });
27
31
 
28
32
  const LogoutLimit = rateLimit({
29
33
  windowMs: 1 * 60 * 1000,
30
34
  max: 10,
31
- message: { success: false, message: "Too many logout attempts, please try again later" }
35
+ message: { success: false, message: "Too many logout attempts, please try again later" },
36
+ validate: {
37
+ trustProxy: false,
38
+ xForwardedForHeader: false
39
+ }
32
40
  });
33
41
 
34
42
  const TwoFALimit = rateLimit({
35
43
  windowMs: 1 * 60 * 1000,
36
44
  max: 5,
37
- message: { success: false, message: "Too many 2FA attempts, please try again later" }
45
+ message: { success: false, message: "Too many 2FA attempts, please try again later" },
46
+ validate: {
47
+ trustProxy: false,
48
+ xForwardedForHeader: false
49
+ }
38
50
  });
39
51
 
40
52
  // CSRF protection middleware
@@ -117,8 +129,17 @@ export async function completeLoginProcess(req, res, user, redirectUrl = null, t
117
129
  const sessionId = crypto.randomBytes(32).toString("hex");
118
130
  console.log(`[mbkauthe] Generated session ID for username: ${username}`);
119
131
 
120
- // Regenerate session to prevent session fixation attacks
132
+ // Fix session fixation: Delete old session BEFORE regenerating to prevent timing window
121
133
  const oldSessionId = req.sessionID;
134
+
135
+ // Delete old session first to prevent session fixation attacks
136
+ await dblogin.query({
137
+ name: 'login-delete-old-session-before-regen',
138
+ text: 'DELETE FROM "session" WHERE sid = $1',
139
+ values: [oldSessionId]
140
+ });
141
+
142
+ // Now regenerate with new session ID (timing window closed)
122
143
  await new Promise((resolve, reject) => {
123
144
  req.session.regenerate((err) => {
124
145
  if (err) reject(err);
@@ -509,6 +530,7 @@ router.get("/login", LoginLimit, csrfProtection, (req, res) => {
509
530
  return res.render("loginmbkauthe.handlebars", {
510
531
  layout: false,
511
532
  githubLoginEnabled: mbkautheVar.GITHUB_LOGIN_ENABLED,
533
+ googleLoginEnabled: mbkautheVar.GOOGLE_LOGIN_ENABLED,
512
534
  customURL: mbkautheVar.loginRedirectURL || '/dashboard',
513
535
  userLoggedIn: !!req.session?.user,
514
536
  username: req.session?.user?.username || '',