mbkauthe 4.8.3 → 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.
- package/README.md +25 -6
- package/docs/api.md +45 -27
- package/docs/auth-flows.mmd +9 -9
- package/docs/auth-processes.mmd +71 -0
- package/docs/db.md +36 -276
- package/docs/db.sql +6 -9
- package/docs/env.md +2 -8
- package/docs/error-messages.md +3 -3
- package/docs/images/auth-flows.svg +1 -1
- package/docs/images/auth-process.svg +1 -0
- package/index.d.ts +1 -2
- package/index.js +1 -1
- package/lib/config/cookies.js +6 -6
- package/lib/config/index.js +4 -10
- package/lib/createTable.js +5 -5
- package/lib/middleware/auth.js +27 -17
- package/lib/middleware/index.js +2 -2
- package/lib/pool.js +2 -2
- package/lib/routes/auth.js +26 -38
- package/lib/routes/dbLogs.js +3 -3
- package/lib/routes/misc.js +22 -22
- package/lib/utils/timingSafeToken.js +35 -0
- package/package.json +1 -1
- package/public/main.js +3 -3
- package/views/Error/dError.handlebars +1 -1
- package/views/pages/accountSwitch.handlebars +4 -4
- package/views/pages/loginmbkauthe.handlebars +1 -1
- package/views/profilemenu.handlebars +2 -2
package/README.md
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
<img height="64px" src="./public/logo.png" alt="MBKAuthe" />
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
|
-
**MBKAuthe** is
|
|
14
|
+
**MBKAuthe** is an open source package focused on login, authentication, and validating sessions for your desired apps in Node.js with Express and PostgreSQL. It provides secure login, session validation, 2FA, role/app access checks, OAuth (GitHub & Google), multi-session support, and related authentication flows.
|
|
15
|
+
|
|
16
|
+
> **Note:** MBKAuthe is intentionally limited to authentication and session validation. The full user/permission/dashboard management system is a separate product called **MBKCore**, developed by MBKTech and not currently open source. Access to MBKCore is currently available only to the MBKTech team, and we may refine it and consider open sourcing it in the future.
|
|
15
17
|
|
|
16
18
|
## Todo
|
|
17
19
|
- Currently, for every request to a protected page, a database query is made to retrieve authentication information (allowed apps, username, session ID, role, etc.). We should implement a caching mechanism to reduce this overhead, but also find a way to allow administrators to log users out and update permissions in near real-time.
|
|
@@ -54,15 +56,15 @@ Run [docs/db.sql](docs/db.sql) to create tables and a default SuperAdmin (`suppo
|
|
|
54
56
|
|
|
55
57
|
```javascript
|
|
56
58
|
import express from 'express';
|
|
57
|
-
import mbkauthe, {
|
|
59
|
+
import mbkauthe, { sessVal, roleChk } from 'mbkauthe';
|
|
58
60
|
import dotenv from 'dotenv';
|
|
59
61
|
dotenv.config();
|
|
60
62
|
|
|
61
63
|
const app = express();
|
|
62
64
|
app.use(mbkauthe);
|
|
63
65
|
|
|
64
|
-
app.get('/dashboard',
|
|
65
|
-
app.get('/admin',
|
|
66
|
+
app.get('/dashboard', sessVal, (req, res) => res.send(`Welcome ${req.session.user.username}!`));
|
|
67
|
+
app.get('/admin', sessVal, roleChk(['SuperAdmin']), (req, res) => res.send('Admin Panel'));
|
|
66
68
|
|
|
67
69
|
app.listen(3000);
|
|
68
70
|
```
|
|
@@ -78,10 +80,27 @@ npm run dev
|
|
|
78
80
|
## 🔧 Core API
|
|
79
81
|
|
|
80
82
|
- **Session Validation:** `validateSession`
|
|
81
|
-
- **Role Check:** `checkRolePermission(['Role'])`
|
|
82
|
-
- **Combined:** `validateSessionAndRole(['SuperAdmin', 'NormalUser'])`
|
|
83
|
+
- **Role Check:** `checkRolePermission(['Role'])`/`roleChk(['Role'])`
|
|
84
|
+
- **Combined:** `validateSessionAndRole(['SuperAdmin', 'NormalUser'])`/`sessRole(['SuperAdmin', 'NormalUser'])`
|
|
83
85
|
- **API Token Auth:** `authenticate(process.env.API_TOKEN)`
|
|
84
86
|
|
|
87
|
+
## 🧾 JSON Responses (HTML vs JSON)
|
|
88
|
+
|
|
89
|
+
Most browser page routes render HTML on auth errors, while API/AJAX-style requests receive JSON error responses.
|
|
90
|
+
|
|
91
|
+
MBKAuthe treats a request as **JSON** (and returns JSON errors) when any of the following apply:
|
|
92
|
+
|
|
93
|
+
- URL/path starts with `/mbkauthe/api/` or `/api/`
|
|
94
|
+
- `X-Requested-With: XMLHttpRequest`
|
|
95
|
+
- `Accept` indicates JSON (e.g., `application/json`) and does not explicitly prefer `text/html`
|
|
96
|
+
- `User-Agent` looks like a non-browser client (e.g., `curl`, `wget`, `Postman`)
|
|
97
|
+
- `User-Agent: json` (explicitly forces JSON responses)
|
|
98
|
+
|
|
99
|
+
**Example (force JSON errors):**
|
|
100
|
+
```bash
|
|
101
|
+
curl -i -H "User-Agent: json" http://localhost:3000/mbkauthe/test
|
|
102
|
+
```
|
|
103
|
+
|
|
85
104
|
## 🧰 Diagnostics (dev only)
|
|
86
105
|
|
|
87
106
|
These are only mounted when `process.env.env === "dev"`:
|
package/docs/api.md
CHANGED
|
@@ -57,12 +57,12 @@ Authorization: Bearer <your_api_token>
|
|
|
57
57
|
|
|
58
58
|
**1. Backend Implementation (Express):**
|
|
59
59
|
|
|
60
|
-
Even when using API tokens, the `validateSession` middleware hydrates `req.session.user` for consistency, allowing you to use the same route logic for both browser and API clients.
|
|
60
|
+
Even when using API tokens, the `validateSession`/`sessVal` middleware hydrates `req.session.user` for consistency, allowing you to use the same route logic for both browser and API clients.
|
|
61
61
|
|
|
62
62
|
```javascript
|
|
63
|
-
import {
|
|
63
|
+
import { sessVal } from 'mbkauthe';
|
|
64
64
|
|
|
65
|
-
app.get('/api/protected-resource',
|
|
65
|
+
app.get('/api/protected-resource', sessVal, (req, res) => {
|
|
66
66
|
// Access user info populated from the token
|
|
67
67
|
const user = req.session.user; // { id, username, role, ... }
|
|
68
68
|
|
|
@@ -1398,15 +1398,15 @@ Both GitHub and Google OAuth implementations include:
|
|
|
1398
1398
|
|
|
1399
1399
|
## Middleware Reference
|
|
1400
1400
|
|
|
1401
|
-
### `validateSession`
|
|
1401
|
+
### `validateSession`/`sessRole`
|
|
1402
1402
|
|
|
1403
1403
|
Validates that the user has an active session.
|
|
1404
1404
|
|
|
1405
1405
|
**Usage:**
|
|
1406
1406
|
```javascript
|
|
1407
|
-
import {
|
|
1407
|
+
import { sessRole } from 'mbkauthe';
|
|
1408
1408
|
|
|
1409
|
-
app.get('/protected',
|
|
1409
|
+
app.get('/protected', sessRole, (req, res) => {
|
|
1410
1410
|
// User is authenticated
|
|
1411
1411
|
const user = req.session.user;
|
|
1412
1412
|
// user contains: { id, username, UserName, role, Role, sessionId }
|
|
@@ -1422,6 +1422,21 @@ app.get('/protected', validateSession, (req, res) => {
|
|
|
1422
1422
|
- Verifies user is authorized for the current application
|
|
1423
1423
|
- Redirects to login page if validation fails
|
|
1424
1424
|
|
|
1425
|
+
**JSON vs HTML error responses:**
|
|
1426
|
+
|
|
1427
|
+
When `validateSession` fails, MBKAuthe will either render an HTML error/login page (browser flow) or return a JSON error response (API/AJAX flow). A request is treated as **JSON** when any of these are true:
|
|
1428
|
+
|
|
1429
|
+
- URL/path starts with `/mbkauthe/api/` or `/api/`
|
|
1430
|
+
- `X-Requested-With: XMLHttpRequest`
|
|
1431
|
+
- `Accept` indicates JSON (e.g., `application/json`) and does not explicitly prefer `text/html`
|
|
1432
|
+
- `User-Agent` matches a non-browser client (e.g., `curl`, `wget`, `Postman`, `Insomnia`)
|
|
1433
|
+
- `User-Agent: json` (explicitly forces JSON responses)
|
|
1434
|
+
|
|
1435
|
+
**Example (force JSON errors on a page route):**
|
|
1436
|
+
```bash
|
|
1437
|
+
curl -i -H "User-Agent: json" http://localhost:3000/mbkauthe/test
|
|
1438
|
+
```
|
|
1439
|
+
|
|
1425
1440
|
### reloadSessionUser(req, res)
|
|
1426
1441
|
|
|
1427
1442
|
Use this helper when you need to refresh the values stored in `req.session.user` from the authoritative database record (for example, after a profile update that changes FullName, or when session expiration policies are updated).
|
|
@@ -1440,7 +1455,7 @@ Use this helper when you need to refresh the values stored in `req.session.user`
|
|
|
1440
1455
|
import { reloadSessionUser } from 'mbkauthe';
|
|
1441
1456
|
|
|
1442
1457
|
// After updating profile data
|
|
1443
|
-
app.post('/mbkauthe/api/update-profile',
|
|
1458
|
+
app.post('/mbkauthe/api/update-profile', sessRole, async (req, res) => {
|
|
1444
1459
|
// ... update profiledata.FullName in DB ...
|
|
1445
1460
|
const refreshed = await reloadSessionUser(req, res);
|
|
1446
1461
|
if (!refreshed) {
|
|
@@ -1469,7 +1484,7 @@ req.session.user = {
|
|
|
1469
1484
|
These cookies allow front-end UI to display a friendly name without making extra requests to the server.
|
|
1470
1485
|
---
|
|
1471
1486
|
|
|
1472
|
-
### `checkRolePermission(requiredRole, notAllowed)`
|
|
1487
|
+
### `checkRolePermission(requiredRole, notAllowed)`/`roleChk `
|
|
1473
1488
|
|
|
1474
1489
|
Checks if the authenticated user has the required role.
|
|
1475
1490
|
|
|
@@ -1479,15 +1494,15 @@ Checks if the authenticated user has the required role.
|
|
|
1479
1494
|
|
|
1480
1495
|
**Usage:**
|
|
1481
1496
|
```javascript
|
|
1482
|
-
import {
|
|
1497
|
+
import { sessVal, roleChk } from 'mbkauthe';
|
|
1483
1498
|
|
|
1484
1499
|
// Only SuperAdmin can access
|
|
1485
|
-
app.get('/admin',
|
|
1500
|
+
app.get('/admin', sessVal, roleChk('SuperAdmin'), (req, res) => {
|
|
1486
1501
|
res.send('Admin panel');
|
|
1487
1502
|
});
|
|
1488
1503
|
|
|
1489
1504
|
// Any authenticated user except Guest
|
|
1490
|
-
app.get('/content',
|
|
1505
|
+
app.get('/content', sessVal, roleChk('Any', 'Guest'), (req, res) => {
|
|
1491
1506
|
res.send('Protected content');
|
|
1492
1507
|
});
|
|
1493
1508
|
```
|
|
@@ -1501,7 +1516,7 @@ app.get('/content', validateSession, checkRolePermission('Any', 'Guest'), (req,
|
|
|
1501
1516
|
|
|
1502
1517
|
---
|
|
1503
1518
|
|
|
1504
|
-
### `validateSessionAndRole(requiredRole, notAllowed)`
|
|
1519
|
+
### `validateSessionAndRole(requiredRole, notAllowed)`/`sessRole`
|
|
1505
1520
|
|
|
1506
1521
|
Combined middleware for session validation and role checking.
|
|
1507
1522
|
|
|
@@ -1511,17 +1526,17 @@ Combined middleware for session validation and role checking.
|
|
|
1511
1526
|
|
|
1512
1527
|
**Usage:**
|
|
1513
1528
|
```javascript
|
|
1514
|
-
import {
|
|
1529
|
+
import { sessRole, roleChk } from 'mbkauthe';
|
|
1515
1530
|
|
|
1516
1531
|
// Validate session AND check role in one middleware
|
|
1517
|
-
app.get('/moderator',
|
|
1532
|
+
app.get('/moderator', sessRole('SuperAdmin'), (req, res) => {
|
|
1518
1533
|
res.send('Moderator panel');
|
|
1519
1534
|
});
|
|
1520
1535
|
```
|
|
1521
1536
|
|
|
1522
1537
|
**Equivalent to:**
|
|
1523
1538
|
```javascript
|
|
1524
|
-
app.get('/moderator',
|
|
1539
|
+
app.get('/moderator', sessVal, roleChk('SuperAdmin'), (req, res) => {
|
|
1525
1540
|
res.send('Moderator panel');
|
|
1526
1541
|
});
|
|
1527
1542
|
```
|
|
@@ -1603,12 +1618,15 @@ app.post('/api/data', authenticate(process.env.API_TOKEN), (req, res) => {
|
|
|
1603
1618
|
|
|
1604
1619
|
**Headers Required:**
|
|
1605
1620
|
```
|
|
1606
|
-
Authorization: your-secret-token
|
|
1621
|
+
Authorization: Bearer your-secret-token
|
|
1607
1622
|
```
|
|
1608
1623
|
|
|
1624
|
+
You can also send the raw token without the `Bearer` prefix.
|
|
1625
|
+
|
|
1609
1626
|
**Behavior:**
|
|
1610
1627
|
- Checks `Authorization` header
|
|
1611
|
-
-
|
|
1628
|
+
- Extracts the token (strips optional `Bearer` prefix)
|
|
1629
|
+
- Compares the provided token to the expected token using a timing-safe SHA-256 hash comparison
|
|
1612
1630
|
- Returns 401 if token doesn't match
|
|
1613
1631
|
|
|
1614
1632
|
---
|
|
@@ -1658,7 +1676,7 @@ const app = express();
|
|
|
1658
1676
|
app.use(mbkauthe);
|
|
1659
1677
|
|
|
1660
1678
|
// Protected route
|
|
1661
|
-
app.get('/dashboard',
|
|
1679
|
+
app.get('/dashboard', sessVal, (req, res) => {
|
|
1662
1680
|
res.send(`Welcome ${req.session.user.username}!`);
|
|
1663
1681
|
});
|
|
1664
1682
|
|
|
@@ -1672,12 +1690,12 @@ app.listen(3000, () => {
|
|
|
1672
1690
|
### Role-Based Access Control
|
|
1673
1691
|
|
|
1674
1692
|
```javascript
|
|
1675
|
-
import {
|
|
1693
|
+
import { sessVal, roleChk, sessRole } from 'mbkauthe';
|
|
1676
1694
|
|
|
1677
1695
|
// Method 1: Separate middleware
|
|
1678
1696
|
app.get('/admin',
|
|
1679
|
-
|
|
1680
|
-
|
|
1697
|
+
sessVal,
|
|
1698
|
+
roleChk('SuperAdmin'),
|
|
1681
1699
|
(req, res) => {
|
|
1682
1700
|
res.send('Admin panel');
|
|
1683
1701
|
}
|
|
@@ -1685,7 +1703,7 @@ app.get('/admin',
|
|
|
1685
1703
|
|
|
1686
1704
|
// Method 2: Combined middleware
|
|
1687
1705
|
app.get('/admin',
|
|
1688
|
-
|
|
1706
|
+
sessRole('SuperAdmin'),
|
|
1689
1707
|
(req, res) => {
|
|
1690
1708
|
res.send('Admin panel');
|
|
1691
1709
|
}
|
|
@@ -1693,8 +1711,8 @@ app.get('/admin',
|
|
|
1693
1711
|
|
|
1694
1712
|
// Allow any role except Guest
|
|
1695
1713
|
app.get('/content',
|
|
1696
|
-
|
|
1697
|
-
|
|
1714
|
+
sessVal,
|
|
1715
|
+
roleChk('Any', 'Guest'),
|
|
1698
1716
|
(req, res) => {
|
|
1699
1717
|
res.send('Content for registered users');
|
|
1700
1718
|
}
|
|
@@ -1702,7 +1720,7 @@ app.get('/content',
|
|
|
1702
1720
|
|
|
1703
1721
|
// Multiple roles (using separate middleware)
|
|
1704
1722
|
app.get('/moderator',
|
|
1705
|
-
|
|
1723
|
+
sessVal,
|
|
1706
1724
|
(req, res, next) => {
|
|
1707
1725
|
if (['SuperAdmin', 'NormalUser'].includes(req.session.user.role)) {
|
|
1708
1726
|
next();
|
|
@@ -1743,7 +1761,7 @@ app.post('/api/admin/terminate-sessions',
|
|
|
1743
1761
|
|
|
1744
1762
|
// Protected API endpoint (requires session)
|
|
1745
1763
|
app.get('/api/user/profile',
|
|
1746
|
-
|
|
1764
|
+
sessVal,
|
|
1747
1765
|
async (req, res) => {
|
|
1748
1766
|
const { username } = req.session.user;
|
|
1749
1767
|
|
|
@@ -1835,7 +1853,7 @@ async function logout() {
|
|
|
1835
1853
|
import { dblogin } from 'mbkauthe';
|
|
1836
1854
|
|
|
1837
1855
|
// Custom query using the database pool
|
|
1838
|
-
app.get('/api/users',
|
|
1856
|
+
app.get('/api/users', sessVal, roleChk('SuperAdmin'), async (req, res) => {
|
|
1839
1857
|
try {
|
|
1840
1858
|
const result = await dblogin.query(
|
|
1841
1859
|
'SELECT id, "UserName", "Role", "Active" FROM "Users" ORDER BY id'
|
package/docs/auth-flows.mmd
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
%%{init: {"themeVariables": {"fontFamily": "Arial, Helvetica, sans-serif", "primaryTextColor": "#333333", "secondaryTextColor": "#333333", "background": "#ffffff"}}}%%
|
|
2
2
|
flowchart TD
|
|
3
|
-
A[Client POST /api/login - payload: username password redirect] --> B[Validate input length & format]
|
|
3
|
+
A[Client POST /mbkauthe/api/login - payload: username password redirect] --> B[Validate input length & format]
|
|
4
4
|
B -->|invalid| Aerr[400 - missing/invalid]
|
|
5
5
|
B --> C[Query Users and TwoFA status]
|
|
6
6
|
C -->|no user| U404[401 - invalid credentials]
|
|
7
|
-
C --> D[Compare password
|
|
7
|
+
C --> D[Compare password hash ]
|
|
8
8
|
D -->|fail| P401[401 - incorrect password]
|
|
9
9
|
D -->|ok| E[Check account Active and app authorization]
|
|
10
10
|
E -->|inactive| I403[403 - account inactive]
|
|
@@ -27,7 +27,7 @@ flowchart TD
|
|
|
27
27
|
Gtrust --> RESP
|
|
28
28
|
|
|
29
29
|
%% 2FA
|
|
30
|
-
A2[Client POST /api/verify-2fa - payload: token trustDevice] --> B2[Ensure req.session.preAuthUser exists]
|
|
30
|
+
A2[Client POST /mbkauthe/api/verify-2fa - payload: token trustDevice] --> B2[Ensure req.session.preAuthUser exists]
|
|
31
31
|
B2 -->|missing| Err401[401 - session not found]
|
|
32
32
|
B2 --> C2[Validate token format - 6 digits]
|
|
33
33
|
C2 --> D2[Fetch TwoFA secret from DB for username]
|
|
@@ -39,7 +39,7 @@ flowchart TD
|
|
|
39
39
|
%% completeLoginProcess & validateSession kept separate for clarity
|
|
40
40
|
|
|
41
41
|
%% Logout
|
|
42
|
-
L1[Client POST /api/logout] --> L2{req.session.user exists?}
|
|
42
|
+
L1[Client POST /mbkauthe/api/logout] --> L2{req.session.user exists?}
|
|
43
43
|
L2 -->|no| Lerr[400 - Not logged in]
|
|
44
44
|
L2 -->|yes| L3[Delete app Sessions row and session store row]
|
|
45
45
|
L3 --> L4[removeAccountFromCookie]
|
|
@@ -47,7 +47,7 @@ flowchart TD
|
|
|
47
47
|
L5 --> LResp[200 - logout successful]
|
|
48
48
|
|
|
49
49
|
%% Account-sessions
|
|
50
|
-
AS1[Client GET /api/account-sessions] --> AS2[readAccountListFromCookie]
|
|
50
|
+
AS1[Client GET /mbkauthe/api/account-sessions] --> AS2[readAccountListFromCookie]
|
|
51
51
|
AS2 -->|empty| ASresp[Return empty accounts and currentSessionId]
|
|
52
52
|
AS2 --> AS3[For each stored account: validate each stored session via fetchActiveSession]
|
|
53
53
|
AS3 -->|invalid| AS4[invalidate DB session and remove account from cookie]
|
|
@@ -55,7 +55,7 @@ flowchart TD
|
|
|
55
55
|
AS5 --> ASresp2[Return accounts and currentSessionId]
|
|
56
56
|
|
|
57
57
|
%% Switch session
|
|
58
|
-
SS1[Client POST /api/switch-session] --> SS2[Validate sessionId format]
|
|
58
|
+
SS1[Client POST /mbkauthe/api/switch-session] --> SS2[Validate sessionId format]
|
|
59
59
|
SS2 -->|invalid| SSerr400[400 - Invalid session id]
|
|
60
60
|
SS2 --> SS3[Check sessionId in readAccountListFromCookie]
|
|
61
61
|
SS3 -->|missing| SSerr403[403 - Account not available on this device]
|
|
@@ -66,7 +66,7 @@ flowchart TD
|
|
|
66
66
|
SS6 --> SSresp[200 - success with username fullName redirect]
|
|
67
67
|
|
|
68
68
|
%% Logout-all
|
|
69
|
-
LA1[Client POST /api/logout-all] --> LA2[readAccountListFromCookie]
|
|
69
|
+
LA1[Client POST /mbkauthe/api/logout-all] --> LA2[readAccountListFromCookie]
|
|
70
70
|
LA2 --> LA3[Collect sessionIds; add currentSession if present]
|
|
71
71
|
LA3 --> LA4[Delete Sessions rows by ids]
|
|
72
72
|
LA4 --> LA5[Delete session store row for current session]
|
|
@@ -74,9 +74,9 @@ flowchart TD
|
|
|
74
74
|
LA6 --> LAresp[200 - All accounts logged out]
|
|
75
75
|
|
|
76
76
|
%% OAuth
|
|
77
|
-
O1[Client GET /api/
|
|
77
|
+
O1[Client GET /mbkauthe/api/github/login or /mbkauthe/api/google/login?redirect=...] --> O2[Server create CSRF token and save to session.oauthCsrfToken and oauthRedirect]
|
|
78
78
|
O2 --> O3[passport.authenticate -> redirect to provider auth page]
|
|
79
|
-
O3 --> O4[Provider redirects back to /api/
|
|
79
|
+
O3 --> O4[Provider redirects back to /mbkauthe/api/github/login/callback or /mbkauthe/api/google/login/callback with state and auth code]
|
|
80
80
|
O4 --> O5[validateOAuthCallback: compare state with session.oauthCsrfToken]
|
|
81
81
|
O5 -->|invalid| Oerr[403 - CSRF mismatch]
|
|
82
82
|
O5 -->|valid| O6[passport.authenticate -> locate linked user record]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
sequenceDiagram
|
|
2
|
+
participant C as Client
|
|
3
|
+
participant S as Server
|
|
4
|
+
participant DB as Database
|
|
5
|
+
|
|
6
|
+
rect rgb(235, 245, 255)
|
|
7
|
+
Note over C, DB: Authentication Flow
|
|
8
|
+
|
|
9
|
+
C->>S: POST /login (username, password)
|
|
10
|
+
S->>S: Validate payload format
|
|
11
|
+
S->>DB: Query User & 2FA status
|
|
12
|
+
DB-->>S: User Data (Password Hash, 2FA Enabled)
|
|
13
|
+
S->>S: Compare Hash (PasswordEnc)
|
|
14
|
+
|
|
15
|
+
alt 2FA Enabled & Device Not Trusted
|
|
16
|
+
S-->>C: 200 (twoFactorRequired: true)
|
|
17
|
+
|
|
18
|
+
C->>S: POST /verify-2fa (TOTP Token)
|
|
19
|
+
S->>DB: Fetch TOTP Secret
|
|
20
|
+
DB-->>S: Secret Key
|
|
21
|
+
S->>S: Verify TOTP
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Note over S, DB: completeLoginProcess
|
|
25
|
+
|
|
26
|
+
S->>DB: Delete old sessions & Prune max sessions
|
|
27
|
+
S->>S: Regenerate Session ID
|
|
28
|
+
S->>DB: Insert new Session row
|
|
29
|
+
S->>DB: Update Users.last_login
|
|
30
|
+
|
|
31
|
+
S-->>C: 200 Success (Set Encrypted Cookies)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
rect rgb(245, 245, 245)
|
|
35
|
+
Note over C, DB: Request Authentication Middleware Flow
|
|
36
|
+
|
|
37
|
+
C->>S: Request + Auth (Cookie or Bearer Token)
|
|
38
|
+
|
|
39
|
+
rect rgb(240, 240, 240)
|
|
40
|
+
Note over S, DB: Token Path (API)
|
|
41
|
+
|
|
42
|
+
alt Header: Bearer mbk_token
|
|
43
|
+
S->>S: Hash Token
|
|
44
|
+
S->>DB: Query ApiTokens JOIN Users
|
|
45
|
+
|
|
46
|
+
alt Valid & Not Expired
|
|
47
|
+
S->>DB: Update last_used
|
|
48
|
+
S->>S: Authorize Scope
|
|
49
|
+
else Invalid/Expired
|
|
50
|
+
S-->>C: 401 Unauthorized
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
rect rgb(220, 230, 250)
|
|
56
|
+
Note over S, DB: Session Path (Web)
|
|
57
|
+
|
|
58
|
+
alt Cookie: sessionId exists
|
|
59
|
+
S->>DB: Query Sessions JOIN Users
|
|
60
|
+
DB-->>S: Session Data + User Status
|
|
61
|
+
|
|
62
|
+
alt Session Valid & User Active
|
|
63
|
+
S->>S: Sync Cookies & Update session.user
|
|
64
|
+
S->>S: Proceed to Route
|
|
65
|
+
else Session Expired/User Inactive
|
|
66
|
+
S->>S: Destroy Session & Clear Cookies
|
|
67
|
+
S-->>C: 403 Forbidden
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|