strapi-plugin-magic-sessionmanager 3.3.2 → 3.5.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/README.md +303 -1137
- package/package.json +3 -2
- package/pics/dashboard.png +0 -0
- package/pics/dashboardsessionmodal.png +0 -0
- package/pics/sessioninfopanel.png +0 -0
- package/pics/settings1.png +0 -0
- package/pics/settings2.png +0 -0
- package/pics/widget.png +0 -0
package/README.md
CHANGED
|
@@ -1,1310 +1,476 @@
|
|
|
1
1
|
# Magic Session Manager 🔐
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**See who's logged into your Strapi app - and control their sessions!**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager)
|
|
7
|
-
[](https://github.com/Schero94/Magic-Sessionmanager/releases)
|
|
5
|
+
Track logins, monitor active users, and secure your app with one simple plugin. No complicated setup required.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## 📋 Table of Contents
|
|
12
|
-
|
|
13
|
-
- [Features](#features)
|
|
14
|
-
- [Quick Start](#quick-start)
|
|
15
|
-
- [How It Works](#how-it-works)
|
|
16
|
-
- [Strapi Integration](#strapi-integration)
|
|
17
|
-
- [Admin Dashboard](#admin-dashboard)
|
|
18
|
-
- [API Routes](#api-routes)
|
|
19
|
-
- [Configuration](#configuration)
|
|
20
|
-
- [Premium Features](#premium-features)
|
|
21
|
-
- [Use Cases](#use-cases)
|
|
22
|
-
- [Testing](#testing)
|
|
23
|
-
- [Troubleshooting](#troubleshooting)
|
|
24
|
-
- [Development](#development)
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## ✨ Features
|
|
29
|
-
|
|
30
|
-
### Core Session Management
|
|
31
|
-
✅ **Automatic Session Tracking** - Sessions created on login, terminated on logout
|
|
32
|
-
✅ **Session History** - Complete record of all login/logout events with IP & browser
|
|
33
|
-
✅ **Activity Monitoring** - Track last seen time with rate limiting
|
|
34
|
-
✅ **Multi-Session Support** - Users can have multiple active sessions
|
|
35
|
-
✅ **Auto-Cleanup** - Inactive sessions automatically marked inactive
|
|
36
|
-
✅ **Real-time Dashboard** - View all active & historical sessions
|
|
37
|
-
|
|
38
|
-
### Security Features (Premium)
|
|
39
|
-
🔒 **IP Geolocation** - Get country, city, ISP from IP addresses
|
|
40
|
-
🔒 **Threat Detection** - Identify VPN, proxy, and threat IPs
|
|
41
|
-
🔒 **Geo-Fencing** - Block/allow logins by country
|
|
42
|
-
🔒 **Security Scoring** - Risk analysis for each login
|
|
43
|
-
🔒 **Auto-Blocking** - Prevent logins from high-risk locations
|
|
44
|
-
🔒 **Email Alerts** - Notify users of suspicious login attempts
|
|
45
|
-
🔒 **Webhook Notifications** - Send Discord/Slack alerts on key events
|
|
46
|
-
|
|
47
|
-
### Admin Dashboard
|
|
48
|
-
📊 **Active Sessions** - Real-time view of logged-in users
|
|
49
|
-
📊 **Analytics** - Session trends, concurrent users, geo-heatmap
|
|
50
|
-
📊 **Settings** - Configure timeouts, notifications, geo-restrictions
|
|
51
|
-
📊 **License Management** - Built-in license activation interface
|
|
52
|
-
|
|
53
|
-
### Non-Invasive Architecture
|
|
54
|
-
✅ **No Core Modifications** - Pure plugin, zero changes to Strapi core
|
|
55
|
-
✅ **Runtime Injection** - Middleware-based architecture
|
|
56
|
-
✅ **DB-Backed** - Uses `plugin::magic-sessionmanager.session` content type
|
|
57
|
-
✅ **License-Based** - Premium features via license key
|
|
7
|
+
[](https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager)
|
|
8
|
+
[](LICENSE)
|
|
58
9
|
|
|
59
10
|
---
|
|
60
11
|
|
|
61
|
-
##
|
|
62
|
-
|
|
63
|
-
### 1. Install Plugin
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npm install strapi-plugin-magic-sessionmanager
|
|
67
|
-
# or
|
|
68
|
-
yarn add strapi-plugin-magic-sessionmanager
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### 2. Register in Config
|
|
72
|
-
|
|
73
|
-
Add to `src/config/plugins.ts` (or `plugins.js`):
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
export default () => ({
|
|
77
|
-
'magic-sessionmanager': {
|
|
78
|
-
enabled: true,
|
|
79
|
-
resolve: './src/plugins/magic-sessionmanager',
|
|
80
|
-
config: {
|
|
81
|
-
// Optional: rate limit for lastSeen updates (ms)
|
|
82
|
-
lastSeenRateLimit: 30000, // 30 seconds (default)
|
|
83
|
-
|
|
84
|
-
// Optional: session inactivity timeout (ms)
|
|
85
|
-
inactivityTimeout: 15 * 60 * 1000, // 15 minutes (default)
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### 3. Build & Run
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
# Install dependencies
|
|
95
|
-
npm install
|
|
96
|
-
|
|
97
|
-
# Build the plugin (includes admin UI)
|
|
98
|
-
npm run build
|
|
99
|
-
|
|
100
|
-
# Start Strapi
|
|
101
|
-
npm run develop
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 4. Configure Encryption (Important!) 🔐
|
|
12
|
+
## 📸 What It Looks Like
|
|
105
13
|
|
|
106
|
-
|
|
14
|
+
### Homepage Widget - Quick Stats at a Glance
|
|
107
15
|
|
|
108
|
-
|
|
109
|
-
# Option 1: Use Admin Panel
|
|
110
|
-
# Go to Admin → Sessions → Settings → Security Settings
|
|
111
|
-
# Click "Generate Key" and copy to .env
|
|
112
|
-
|
|
113
|
-
# Option 2: Generate manually
|
|
114
|
-
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
115
|
-
|
|
116
|
-
# Add to .env file:
|
|
117
|
-
SESSION_ENCRYPTION_KEY=your-generated-32-char-key-here
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
**Why this is important:**
|
|
121
|
-
- JWT tokens are encrypted before storing in database
|
|
122
|
-
- Prevents token exposure if database is compromised
|
|
123
|
-
- Uses AES-256-GCM encryption standard
|
|
16
|
+

|
|
124
17
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
18
|
+
**On your Strapi homepage:**
|
|
19
|
+
- See online users instantly
|
|
20
|
+
- Active in last 15/30 minutes
|
|
21
|
+
- Total users count
|
|
22
|
+
- Blocked users count
|
|
23
|
+
- No need to navigate anywhere!
|
|
131
24
|
|
|
132
25
|
---
|
|
133
26
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
### Architecture Overview
|
|
27
|
+
### Main Dashboard - See All Active Sessions
|
|
137
28
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
┌─────────────────────────────────────────────────────────┐
|
|
142
|
-
│ Client sends: │
|
|
143
|
-
│ POST /api/auth/local │
|
|
144
|
-
│ { identifier: "user@example.com", password: "pass123" }│
|
|
145
|
-
└────────────────┬────────────────────────────────────────┘
|
|
146
|
-
│
|
|
147
|
-
▼
|
|
148
|
-
┌─────────────────────────────────────────────────────────┐
|
|
149
|
-
│ Strapi's Native Auth (users-permissions plugin) │
|
|
150
|
-
│ - Validates credentials │
|
|
151
|
-
│ - Creates JWT token │
|
|
152
|
-
│ - Returns: { jwt: "...", user: {...} } │
|
|
153
|
-
└────────────────┬────────────────────────────────────────┘
|
|
154
|
-
│
|
|
155
|
-
▼
|
|
156
|
-
┌─────────────────────────────────────────────────────────┐
|
|
157
|
-
│ Magic Session Manager Middleware (AFTER auth) │
|
|
158
|
-
│ - Detects successful login (status 200 + user object) │
|
|
159
|
-
│ - Extracts: IP, User Agent, JWT Token │
|
|
160
|
-
│ - [PREMIUM] Checks IP geolocation & threat level │
|
|
161
|
-
│ - [PREMIUM] Applies geo-fencing rules │
|
|
162
|
-
│ - Creates session record in database │
|
|
163
|
-
│ - [PREMIUM] Sends notifications (email/webhook) │
|
|
164
|
-
└────────────────┬────────────────────────────────────────┘
|
|
165
|
-
│
|
|
166
|
-
▼
|
|
167
|
-
┌─────────────────────────────────────────────────────────┐
|
|
168
|
-
│ Response returned to client (unchanged) │
|
|
169
|
-
│ { jwt: "...", user: {...} } │
|
|
170
|
-
└─────────────────────────────────────────────────────────┘
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Login Flow (Detailed)
|
|
174
|
-
|
|
175
|
-
```
|
|
176
|
-
User Login Request
|
|
177
|
-
↓
|
|
178
|
-
[POST /api/auth/local]
|
|
179
|
-
Body: { identifier, password }
|
|
180
|
-
↓
|
|
181
|
-
Strapi Auth validates credentials
|
|
182
|
-
↓
|
|
183
|
-
✅ Success → Strapi creates JWT token
|
|
184
|
-
↓
|
|
185
|
-
Strapi prepares response: { jwt, user }
|
|
186
|
-
↓
|
|
187
|
-
[Magic Session Manager Middleware INTERCEPTS]
|
|
188
|
-
↓
|
|
189
|
-
Extract from response:
|
|
190
|
-
- user.id
|
|
191
|
-
- ctx.body.jwt (Access Token)
|
|
192
|
-
- IP address (from headers/proxies)
|
|
193
|
-
- User Agent (browser info)
|
|
194
|
-
↓
|
|
195
|
-
[PREMIUM] Check IP Geolocation:
|
|
196
|
-
- Get country, city, ISP
|
|
197
|
-
- Detect VPN/Proxy/Threat
|
|
198
|
-
- Calculate security score (0-100)
|
|
199
|
-
- Apply geo-fencing rules
|
|
200
|
-
↓
|
|
201
|
-
[PREMIUM] Auto-blocking if:
|
|
202
|
-
- Known threat IP (isThreat = true)
|
|
203
|
-
- VPN detected (isVpn = true)
|
|
204
|
-
- Country blocked (not in allowlist)
|
|
205
|
-
- Security score < 50
|
|
206
|
-
↓
|
|
207
|
-
Block? NO → Continue ✅
|
|
208
|
-
Block? YES → Return 403 Forbidden ❌
|
|
209
|
-
↓
|
|
210
|
-
Create plugin::magic-sessionmanager.session record:
|
|
211
|
-
{
|
|
212
|
-
user: userId,
|
|
213
|
-
token: jwt, // Access Token
|
|
214
|
-
ipAddress: "192.168.1.100",
|
|
215
|
-
userAgent: "Mozilla/5.0...",
|
|
216
|
-
loginTime: now,
|
|
217
|
-
lastActive: now,
|
|
218
|
-
isActive: true,
|
|
219
|
-
geoLocation: {...}, // Premium
|
|
220
|
-
securityScore: 95 // Premium
|
|
221
|
-
}
|
|
222
|
-
↓
|
|
223
|
-
[PREMIUM] Send notifications:
|
|
224
|
-
- Email alert (if suspicious)
|
|
225
|
-
- Webhook (Discord/Slack)
|
|
226
|
-
↓
|
|
227
|
-
Return response to client (unchanged):
|
|
228
|
-
{ jwt: "...", user: {...} }
|
|
229
|
-
```
|
|
29
|
+

|
|
230
30
|
|
|
231
|
-
|
|
31
|
+
**What you see:**
|
|
32
|
+
- Who is logged in right now (green = online)
|
|
33
|
+
- When they logged in
|
|
34
|
+
- What device they're using
|
|
35
|
+
- Their IP address and location
|
|
36
|
+
- One-click session termination
|
|
232
37
|
|
|
233
|
-
|
|
38
|
+
---
|
|
234
39
|
|
|
235
|
-
|
|
236
|
-
User Logout Request
|
|
237
|
-
↓
|
|
238
|
-
[POST /api/auth/logout]
|
|
239
|
-
Headers: { Authorization: "Bearer <JWT>" }
|
|
240
|
-
↓
|
|
241
|
-
Magic Session Manager Handler (NOT Strapi's default)
|
|
242
|
-
↓
|
|
243
|
-
Extract JWT from Authorization header
|
|
244
|
-
↓
|
|
245
|
-
Find matching session:
|
|
246
|
-
WHERE token = jwt AND isActive = true
|
|
247
|
-
↓
|
|
248
|
-
Found? YES → Update session:
|
|
249
|
-
{
|
|
250
|
-
isActive: false,
|
|
251
|
-
logoutTime: now
|
|
252
|
-
}
|
|
253
|
-
↓
|
|
254
|
-
Found? NO → Continue anyway (idempotent)
|
|
255
|
-
↓
|
|
256
|
-
Return: { message: "Logged out successfully" }
|
|
257
|
-
```
|
|
40
|
+
### Session Details Modal
|
|
258
41
|
|
|
259
|
-
|
|
42
|
+

|
|
260
43
|
|
|
261
|
-
|
|
44
|
+
**Click any session to see:**
|
|
45
|
+
- Full device information
|
|
46
|
+
- Browser and operating system
|
|
47
|
+
- Complete session history
|
|
48
|
+
- IP geolocation (Premium)
|
|
49
|
+
- Security risk score (Premium)
|
|
262
50
|
|
|
263
|
-
|
|
264
|
-
Authenticated API Request
|
|
265
|
-
(Any route with valid JWT)
|
|
266
|
-
↓
|
|
267
|
-
[LastSeen Middleware - BEFORE request]
|
|
268
|
-
↓
|
|
269
|
-
Check: Does user have active session?
|
|
270
|
-
WHERE user.id = X AND isActive = true
|
|
271
|
-
↓
|
|
272
|
-
NO active sessions?
|
|
273
|
-
→ Reject: 401 Unauthorized
|
|
274
|
-
→ Message: "All sessions terminated. Please login again."
|
|
275
|
-
↓
|
|
276
|
-
Has active session? Continue ✅
|
|
277
|
-
↓
|
|
278
|
-
[Process actual request]
|
|
279
|
-
↓
|
|
280
|
-
[LastSeen Middleware - AFTER request]
|
|
281
|
-
↓
|
|
282
|
-
Check: Was lastActive updated < 30s ago?
|
|
283
|
-
(Rate limiting to prevent DB noise)
|
|
284
|
-
↓
|
|
285
|
-
YES (recently updated) → Skip ⏭️
|
|
286
|
-
NO (old timestamp) → Update session:
|
|
287
|
-
{
|
|
288
|
-
lastActive: now
|
|
289
|
-
}
|
|
290
|
-
↓
|
|
291
|
-
Request complete
|
|
292
|
-
```
|
|
51
|
+
---
|
|
293
52
|
|
|
294
|
-
###
|
|
53
|
+
### Content Manager Integration
|
|
295
54
|
|
|
296
|
-
|
|
55
|
+

|
|
297
56
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
AND isActive = true
|
|
304
|
-
↓
|
|
305
|
-
For each inactive session:
|
|
306
|
-
Update: isActive = false
|
|
307
|
-
↓
|
|
308
|
-
Log: "Cleaned up X inactive sessions"
|
|
309
|
-
```
|
|
57
|
+
**When viewing a user:**
|
|
58
|
+
- Sidebar shows their active sessions
|
|
59
|
+
- Quick actions (terminate, block)
|
|
60
|
+
- Offline/Online status indicator
|
|
61
|
+
- No need to leave the page!
|
|
310
62
|
|
|
311
63
|
---
|
|
312
64
|
|
|
313
|
-
|
|
65
|
+
### Settings Page
|
|
314
66
|
|
|
315
|
-
|
|
67
|
+

|
|
316
68
|
|
|
317
|
-
|
|
69
|
+
**Easy configuration:**
|
|
70
|
+
- Session timeouts
|
|
71
|
+
- Rate limiting
|
|
72
|
+
- Email alerts
|
|
73
|
+
- Webhook notifications
|
|
74
|
+
- Geo-blocking rules
|
|
318
75
|
|
|
319
|
-
|
|
320
|
-
|-------|--------|------------------------------|
|
|
321
|
-
| `/api/auth/local` | `POST` | **Intercepted** - Middleware runs AFTER Strapi auth creates JWT, then creates session |
|
|
322
|
-
| `/api/auth/local/register` | `POST` | **Intercepted** - Same as login (auto-login after registration) |
|
|
76
|
+

|
|
323
77
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
#### Plugin Routes
|
|
78
|
+
**Advanced security:**
|
|
79
|
+
- Encryption key generator (one click!)
|
|
80
|
+
- Country allow/block lists
|
|
81
|
+
- VPN detection
|
|
82
|
+
- Threat blocking
|
|
331
83
|
|
|
332
|
-
|
|
333
|
-
|-------|--------|---------|
|
|
334
|
-
| `/api/magic-sessionmanager/logout` | `POST` | Alternative logout endpoint |
|
|
335
|
-
| `/api/magic-sessionmanager/logout-all` | `POST` | Logout from all devices |
|
|
336
|
-
| `/api/magic-sessionmanager/sessions` | `GET` | Get user's sessions |
|
|
337
|
-
| `/api/magic-sessionmanager/user/:id/sessions` | `GET` | Get sessions for specific user |
|
|
84
|
+
---
|
|
338
85
|
|
|
339
|
-
|
|
86
|
+
## ✨ What This Plugin Does
|
|
340
87
|
|
|
341
|
-
|
|
342
|
-
- **Stored:** YES - in `session.token` field
|
|
343
|
-
- **Used for:** Matching sessions during logout
|
|
344
|
-
- **Expiration:** Controlled by Strapi's JWT config
|
|
345
|
-
- **Validation:** Done by Strapi's auth system (not the plugin)
|
|
88
|
+
### Simple Version
|
|
346
89
|
|
|
347
|
-
**
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
90
|
+
**When users login:**
|
|
91
|
+
- Plugin saves who logged in, when, and from where
|
|
92
|
+
- You can see them in the dashboard (see screenshot above)
|
|
93
|
+
- You can force-logout anyone anytime
|
|
351
94
|
|
|
352
|
-
|
|
95
|
+
**When users logout:**
|
|
96
|
+
- Plugin marks their session as "logged out"
|
|
97
|
+
- They disappear from the active sessions list
|
|
353
98
|
|
|
354
|
-
**
|
|
355
|
-
|
|
99
|
+
**While users are active:**
|
|
100
|
+
- Plugin updates their "last seen" time
|
|
101
|
+
- You always know who's currently using your app
|
|
356
102
|
|
|
357
|
-
|
|
358
|
-
Access Token expires after 30 min
|
|
359
|
-
↓
|
|
360
|
-
User still has Refresh Token
|
|
361
|
-
↓
|
|
362
|
-
User requests new Access Token:
|
|
363
|
-
POST /api/auth/refresh
|
|
364
|
-
↓
|
|
365
|
-
Strapi issues new JWT
|
|
366
|
-
↓
|
|
367
|
-
User continues without re-login
|
|
368
|
-
```
|
|
103
|
+
---
|
|
369
104
|
|
|
370
|
-
|
|
371
|
-
- **Stored:** YES - Refresh tokens are encrypted and stored with sessions ✅
|
|
372
|
-
- **Tracked:** YES - Middleware intercepts `/api/auth/refresh` requests ✅
|
|
373
|
-
- **Validated:** YES - Checks if session is still active before issuing new tokens ✅
|
|
105
|
+
## 🚀 Quick Install
|
|
374
106
|
|
|
375
|
-
|
|
107
|
+
### Step 1: Install
|
|
376
108
|
|
|
109
|
+
```bash
|
|
110
|
+
npm install strapi-plugin-magic-sessionmanager
|
|
377
111
|
```
|
|
378
|
-
Login: User gets JWT + Refresh Token
|
|
379
|
-
↓
|
|
380
|
-
Both tokens encrypted and stored in session
|
|
381
|
-
↓
|
|
382
|
-
Admin terminates session
|
|
383
|
-
↓
|
|
384
|
-
Session: isActive = false ❌
|
|
385
|
-
↓
|
|
386
|
-
User tries to refresh token:
|
|
387
|
-
POST /api/auth/refresh
|
|
388
|
-
{ refreshToken: "..." }
|
|
389
|
-
↓
|
|
390
|
-
[Refresh Token Middleware]
|
|
391
|
-
↓
|
|
392
|
-
Decrypt all active session refresh tokens
|
|
393
|
-
↓
|
|
394
|
-
Find matching session
|
|
395
|
-
↓
|
|
396
|
-
Session found but isActive = false?
|
|
397
|
-
→ BLOCK! Return 401 Unauthorized ❌
|
|
398
|
-
→ Message: "Session terminated. Please login again."
|
|
399
|
-
↓
|
|
400
|
-
Session found and isActive = true?
|
|
401
|
-
→ ALLOW! ✅
|
|
402
|
-
→ Strapi issues new tokens
|
|
403
|
-
→ Session updated with new encrypted tokens
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
**Security Benefits:**
|
|
407
112
|
|
|
408
|
-
|
|
409
|
-
✅ **Refresh tokens tracked** - Encrypted & stored securely
|
|
410
|
-
✅ **Token rotation** - New tokens automatically updated in session
|
|
411
|
-
✅ **Admin control** - Force logout works even with refresh tokens
|
|
113
|
+
### Step 2: Enable Plugin
|
|
412
114
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
Enable refresh tokens in Strapi:
|
|
115
|
+
Add this to `config/plugins.ts`:
|
|
416
116
|
|
|
417
117
|
```typescript
|
|
418
|
-
// src/config/plugins.ts
|
|
419
118
|
export default () => ({
|
|
420
|
-
'users-permissions': {
|
|
421
|
-
config: {
|
|
422
|
-
jwtManagement: 'refresh', // Enable refresh tokens
|
|
423
|
-
sessions: {
|
|
424
|
-
accessTokenLifespan: 3600, // 1 hour (in seconds)
|
|
425
|
-
maxRefreshTokenLifespan: 2592000, // 30 days
|
|
426
|
-
idleRefreshTokenLifespan: 604800, // 7 days idle
|
|
427
|
-
},
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
119
|
'magic-sessionmanager': {
|
|
431
120
|
enabled: true,
|
|
432
|
-
config: {
|
|
433
|
-
inactivityTimeout: 15 * 60 * 1000, // 15 minutes
|
|
434
|
-
},
|
|
435
121
|
},
|
|
436
122
|
});
|
|
437
123
|
```
|
|
438
124
|
|
|
439
|
-
|
|
125
|
+
### Step 3: Rebuild & Start
|
|
440
126
|
|
|
441
127
|
```bash
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
-H "Content-Type: application/json" \
|
|
445
|
-
-d '{"identifier":"user@example.com","password":"pass"}'
|
|
446
|
-
|
|
447
|
-
# Save both tokens:
|
|
448
|
-
ACCESS_TOKEN="eyJhbGci..."
|
|
449
|
-
REFRESH_TOKEN="abc123..."
|
|
450
|
-
|
|
451
|
-
# 2. Admin terminates session
|
|
452
|
-
# Go to Admin → Sessions → Find session → Terminate
|
|
453
|
-
|
|
454
|
-
# 3. Try to refresh token
|
|
455
|
-
curl -X POST http://localhost:1337/api/auth/refresh \
|
|
456
|
-
-H "Content-Type: application/json" \
|
|
457
|
-
-d "{\"refreshToken\":\"$REFRESH_TOKEN\"}"
|
|
458
|
-
|
|
459
|
-
# Expected: 401 Unauthorized
|
|
460
|
-
# "Session terminated. Please login again."
|
|
128
|
+
npm run build
|
|
129
|
+
npm run develop
|
|
461
130
|
```
|
|
462
131
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
### Without Refresh Tokens (Default Behavior)
|
|
132
|
+
### Step 4: Open Dashboard
|
|
466
133
|
|
|
467
|
-
|
|
134
|
+
1. Go to Strapi Admin: `http://localhost:1337/admin`
|
|
135
|
+
2. Look in the left sidebar for **"Sessions"**
|
|
136
|
+
3. Click it!
|
|
137
|
+
4. You'll see the dashboard (like the screenshot above)
|
|
468
138
|
|
|
469
|
-
|
|
470
|
-
Login: User gets JWT (no refresh token)
|
|
471
|
-
↓
|
|
472
|
-
JWT stored in session (encrypted)
|
|
473
|
-
↓
|
|
474
|
-
JWT expires after 30 min (or configured time)
|
|
475
|
-
↓
|
|
476
|
-
User must re-login ❌
|
|
477
|
-
↓
|
|
478
|
-
No automatic token refresh
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
**Behavior:**
|
|
482
|
-
- ✅ Session Manager works normally
|
|
483
|
-
- ✅ Sessions tracked, logout works
|
|
484
|
-
- ✅ Force logout works (no refresh token bypass possible)
|
|
485
|
-
- ⚠️ Users must re-login when JWT expires
|
|
486
|
-
- ℹ️ No refresh token middleware runs (skipped)
|
|
487
|
-
|
|
488
|
-
**Logs when refresh tokens disabled:**
|
|
489
|
-
```
|
|
490
|
-
[magic-sessionmanager] ✅ Session created for user 1 (IP: 192.168.1.1)
|
|
491
|
-
[magic-sessionmanager] ℹ️ No refresh token in response (JWT management not enabled)
|
|
492
|
-
[magic-sessionmanager] ✅ Refresh Token interceptor middleware mounted
|
|
493
|
-
```
|
|
139
|
+
**That's it! You're done!** 🎉
|
|
494
140
|
|
|
495
|
-
|
|
496
|
-
- Endpoint returns **404 Not Found** (Strapi doesn't create the route)
|
|
497
|
-
- Or returns **401 Unauthorized** if route exists but tokens not configured
|
|
498
|
-
- This is expected and correct behavior
|
|
141
|
+
---
|
|
499
142
|
|
|
500
|
-
|
|
143
|
+
## 🔐 Security Features (Optional)
|
|
501
144
|
|
|
502
|
-
|
|
503
|
-
|---------|---------------------|------------------------|
|
|
504
|
-
| User Experience | ✅ Seamless (auto-refresh) | ⚠️ Must re-login |
|
|
505
|
-
| Security | ✅ Tracked & blockable | ✅ No bypass risk |
|
|
506
|
-
| Session Duration | Long (days/weeks) | Short (hours) |
|
|
507
|
-
| Force Logout | ✅ Complete | ✅ Complete |
|
|
145
|
+
### Encryption Key (Recommended)
|
|
508
146
|
|
|
509
|
-
|
|
147
|
+
Your JWT tokens are encrypted before saving to database. Generate a key:
|
|
510
148
|
|
|
511
|
-
**
|
|
149
|
+
**In Admin Panel:**
|
|
150
|
+
1. Go to **Sessions → Settings**
|
|
151
|
+
2. Scroll to **"JWT Encryption Key Generator"**
|
|
152
|
+
3. Click **"Generate Key"**
|
|
153
|
+
4. Click **"Copy for .env"**
|
|
154
|
+
5. Paste into your `.env` file
|
|
155
|
+
6. Restart Strapi
|
|
512
156
|
|
|
513
|
-
**
|
|
157
|
+
**Or generate manually:**
|
|
158
|
+
```bash
|
|
159
|
+
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
160
|
+
```
|
|
514
161
|
|
|
162
|
+
Then add to `.env`:
|
|
515
163
|
```
|
|
516
|
-
|
|
517
|
-
POST /api/auth/local
|
|
518
|
-
→ Save: jwt, refreshToken, session_id
|
|
519
|
-
|
|
520
|
-
2. Refresh Token (should work)
|
|
521
|
-
POST /api/auth/refresh
|
|
522
|
-
Body: { "refreshToken": "..." }
|
|
523
|
-
→ Returns: New jwt + refreshToken ✅
|
|
524
|
-
|
|
525
|
-
3. Admin terminates session
|
|
526
|
-
POST /magic-sessionmanager/sessions/:id/terminate
|
|
527
|
-
|
|
528
|
-
4. Try refresh token again
|
|
529
|
-
POST /api/auth/refresh
|
|
530
|
-
Body: { "refreshToken": "..." }
|
|
531
|
-
→ Returns: 401 Unauthorized ✅
|
|
532
|
-
→ Message: "Session terminated. Please login again."
|
|
164
|
+
SESSION_ENCRYPTION_KEY=your-key-here
|
|
533
165
|
```
|
|
534
166
|
|
|
535
|
-
**
|
|
536
|
-
|
|
537
|
-
```bash
|
|
538
|
-
cd /path/to/magic-sessionmanager
|
|
539
|
-
|
|
540
|
-
# Set environment variables
|
|
541
|
-
export TEST_USER_EMAIL=user@example.com
|
|
542
|
-
export TEST_USER_PASSWORD=password123
|
|
543
|
-
export ADMIN_EMAIL=admin@example.com
|
|
544
|
-
export ADMIN_PASSWORD=adminpass
|
|
545
|
-
|
|
546
|
-
# Run test suite
|
|
547
|
-
node test-session-manager.js
|
|
167
|
+
**Why?** If someone hacks your database, they can't steal user sessions! 🔒
|
|
548
168
|
|
|
549
|
-
|
|
550
|
-
# Should show: ✅ Refresh token BLOCKED as expected!
|
|
551
|
-
|
|
552
|
-
# Note: Tests include delays to avoid rate limiting
|
|
553
|
-
# Total runtime: ~45-60 seconds (includes 8s pause before refresh token test)
|
|
554
|
-
```
|
|
169
|
+
---
|
|
555
170
|
|
|
556
|
-
|
|
171
|
+
## 🎯 Main Features Explained Simply
|
|
557
172
|
|
|
558
|
-
|
|
559
|
-
- Tests include 1-5 second delays between requests (8s before final test)
|
|
560
|
-
- Strapi may have aggressive rate limiting enabled
|
|
561
|
-
- **Wait 3-5 minutes** and run tests again
|
|
562
|
-
- Or disable rate limiting in Strapi config temporarily for testing
|
|
563
|
-
- Or run individual tests instead of full suite
|
|
173
|
+
### 1. See Who's Logged In
|
|
564
174
|
|
|
565
|
-
|
|
175
|
+
**Dashboard Tab:**
|
|
176
|
+
- Shows all active users
|
|
177
|
+
- Green badge = currently online
|
|
178
|
+
- Gray badge = logged out
|
|
179
|
+
- Click to see details
|
|
566
180
|
|
|
567
|
-
|
|
568
|
-
**Magic Session Manager:** Tracks each login as separate session
|
|
181
|
+
### 2. Force Logout Anyone
|
|
569
182
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
- Laptop (Firefox) → Session 3
|
|
183
|
+
**Need to kick someone out?**
|
|
184
|
+
1. Find their session
|
|
185
|
+
2. Click **"Terminate"**
|
|
186
|
+
3. Done! They're logged out immediately
|
|
575
187
|
|
|
576
|
-
|
|
577
|
-
User can logout from one device without affecting others.
|
|
578
|
-
```
|
|
188
|
+
**Even works if they have refresh tokens!** (See below)
|
|
579
189
|
|
|
580
|
-
###
|
|
190
|
+
### 3. Session Details
|
|
581
191
|
|
|
582
|
-
|
|
192
|
+
**Click any session to see:**
|
|
193
|
+
- When they logged in
|
|
194
|
+
- Last time they did something
|
|
195
|
+
- What browser/device they use
|
|
196
|
+
- Their IP address
|
|
197
|
+
- Location (if Premium)
|
|
583
198
|
|
|
584
|
-
|
|
585
|
-
// bootstrap.js line 140
|
|
586
|
-
const isMagicLink = ctx.path.includes('/magic-link/login') && ctx.method === 'POST';
|
|
587
|
-
```
|
|
199
|
+
### 4. Multiple Devices
|
|
588
200
|
|
|
589
|
-
|
|
201
|
+
**Users can login from:**
|
|
202
|
+
- Desktop computer
|
|
203
|
+
- Phone
|
|
204
|
+
- Tablet
|
|
205
|
+
- All at the same time!
|
|
590
206
|
|
|
591
|
-
|
|
207
|
+
Each login = separate session. You can see them all and logout each individually.
|
|
592
208
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
Access at **Admin → Sessions** (sidebar plugin)
|
|
596
|
-
|
|
597
|
-
### Tabs Overview
|
|
598
|
-
|
|
599
|
-
#### 1. 📊 **Active Sessions**
|
|
600
|
-
- Real-time list of currently logged-in users
|
|
601
|
-
- Shows: User, IP, Device, Login Time, Last Seen
|
|
602
|
-
- Actions: Terminate session, View details
|
|
603
|
-
- Live status indicators
|
|
604
|
-
|
|
605
|
-
**Features:**
|
|
606
|
-
- Filter by user, device, location
|
|
607
|
-
- Sort by login time, last activity
|
|
608
|
-
- Bulk actions (terminate multiple)
|
|
609
|
-
- Export to CSV
|
|
610
|
-
|
|
611
|
-
#### 2. 📈 **Analytics**
|
|
612
|
-
- Total sessions today/this week/this month
|
|
613
|
-
- Concurrent users graph (real-time)
|
|
614
|
-
- Geo-heatmap (Premium - shows login locations)
|
|
615
|
-
- Device/browser breakdown
|
|
616
|
-
- Peak usage times
|
|
617
|
-
- Average session duration
|
|
618
|
-
|
|
619
|
-
#### 3. ⚙️ **Settings**
|
|
620
|
-
|
|
621
|
-
**Basic Settings:**
|
|
622
|
-
- Rate limits (lastSeen update frequency)
|
|
623
|
-
- Inactivity timeout
|
|
624
|
-
- Cleanup schedule
|
|
625
|
-
|
|
626
|
-
**Premium Settings:**
|
|
627
|
-
- License key activation
|
|
628
|
-
- Geolocation enabled
|
|
629
|
-
- Security scoring enabled
|
|
630
|
-
- Auto-blocking suspicious logins
|
|
631
|
-
- VPN/Proxy alerts
|
|
632
|
-
|
|
633
|
-
**Notification Settings:**
|
|
634
|
-
- Email alerts configuration
|
|
635
|
-
- Suspicious login alerts
|
|
636
|
-
- Discord webhook URL
|
|
637
|
-
- Slack webhook URL
|
|
638
|
-
|
|
639
|
-
**Geo-Fencing:**
|
|
640
|
-
- Country allow/block lists
|
|
641
|
-
- IP whitelist/blacklist
|
|
209
|
+
### 5. Auto-Cleanup
|
|
642
210
|
|
|
643
|
-
|
|
644
|
-
-
|
|
645
|
-
-
|
|
646
|
-
-
|
|
647
|
-
- License holder details
|
|
648
|
-
- Auto-ping status (15-minute intervals)
|
|
211
|
+
**Inactive sessions are automatically cleaned up:**
|
|
212
|
+
- If user doesn't do anything for 15 minutes (configurable)
|
|
213
|
+
- Session is marked as "inactive"
|
|
214
|
+
- Keeps your database clean
|
|
649
215
|
|
|
650
216
|
---
|
|
651
217
|
|
|
652
|
-
##
|
|
218
|
+
## 🔒 Refresh Token Protection (Advanced)
|
|
653
219
|
|
|
654
|
-
###
|
|
220
|
+
### The Problem (Without This Plugin)
|
|
655
221
|
|
|
656
|
-
All require valid JWT authentication (Bearer token).
|
|
657
|
-
|
|
658
|
-
#### Get User Sessions
|
|
659
|
-
|
|
660
|
-
```bash
|
|
661
|
-
GET /api/magic-sessionmanager/sessions
|
|
662
|
-
Authorization: Bearer YOUR_JWT
|
|
663
|
-
|
|
664
|
-
Response:
|
|
665
|
-
{
|
|
666
|
-
"data": [
|
|
667
|
-
{
|
|
668
|
-
"id": 1,
|
|
669
|
-
"attributes": {
|
|
670
|
-
"loginTime": "2024-01-15T10:30:00Z",
|
|
671
|
-
"lastActive": "2024-01-15T10:35:45Z",
|
|
672
|
-
"logoutTime": null,
|
|
673
|
-
"isActive": true,
|
|
674
|
-
"ipAddress": "192.168.1.100",
|
|
675
|
-
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
|
|
676
|
-
"token": "eyJhbGciOiJIUzI1NiIs...", // JWT Access Token
|
|
677
|
-
"geoLocation": { // Premium
|
|
678
|
-
"country": "Germany",
|
|
679
|
-
"city": "Berlin",
|
|
680
|
-
"country_code": "DE",
|
|
681
|
-
"latitude": 52.52,
|
|
682
|
-
"longitude": 13.41
|
|
683
|
-
},
|
|
684
|
-
"securityScore": 95 // Premium
|
|
685
|
-
},
|
|
686
|
-
"relationships": {
|
|
687
|
-
"user": { "id": 1, "username": "john" }
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
],
|
|
691
|
-
"meta": { "count": 3 }
|
|
692
|
-
}
|
|
693
222
|
```
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
Response:
|
|
702
|
-
{
|
|
703
|
-
"message": "Logged out successfully"
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
# This is the REPLACED Strapi route
|
|
707
|
-
# Terminates session matching the JWT token
|
|
223
|
+
Admin kicks out a user
|
|
224
|
+
↓
|
|
225
|
+
User has "refresh token"
|
|
226
|
+
↓
|
|
227
|
+
User gets new login token automatically
|
|
228
|
+
↓
|
|
229
|
+
User is back in! 😱
|
|
708
230
|
```
|
|
709
231
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
```bash
|
|
713
|
-
POST /api/magic-sessionmanager/logout
|
|
714
|
-
Authorization: Bearer YOUR_JWT
|
|
715
|
-
|
|
716
|
-
Response:
|
|
717
|
-
{
|
|
718
|
-
"message": "Session terminated successfully"
|
|
719
|
-
}
|
|
232
|
+
### The Solution (With This Plugin)
|
|
720
233
|
|
|
721
|
-
# Alternative endpoint with same behavior
|
|
722
234
|
```
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
Response:
|
|
731
|
-
{
|
|
732
|
-
"message": "All sessions terminated",
|
|
733
|
-
"count": 3
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
# Terminates ALL active sessions for the user
|
|
737
|
-
# Useful for "logout everywhere" feature
|
|
235
|
+
Admin kicks out a user
|
|
236
|
+
↓
|
|
237
|
+
User tries to use refresh token
|
|
238
|
+
↓
|
|
239
|
+
Plugin blocks it! 🚫
|
|
240
|
+
↓
|
|
241
|
+
User MUST login again
|
|
738
242
|
```
|
|
739
243
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
### Admin API Routes
|
|
743
|
-
|
|
744
|
-
All require **admin authentication**.
|
|
745
|
-
|
|
746
|
-
| Method | Route | Purpose |
|
|
747
|
-
|--------|-------|---------|
|
|
748
|
-
| `GET` | `/magic-sessionmanager/admin/sessions` | Get all sessions (all users) |
|
|
749
|
-
| `GET` | `/magic-sessionmanager/admin/sessions/active` | Get only active sessions |
|
|
750
|
-
| `GET` | `/magic-sessionmanager/admin/user/:userId/sessions` | Get sessions for a user |
|
|
751
|
-
| `POST` | `/magic-sessionmanager/admin/sessions/:sessionId/terminate` | Mark session inactive |
|
|
752
|
-
| `DELETE` | `/magic-sessionmanager/admin/sessions/:sessionId` | Permanently delete session |
|
|
753
|
-
| `POST` | `/magic-sessionmanager/admin/sessions/clean-inactive` | Delete all inactive sessions |
|
|
754
|
-
| `POST` | `/magic-sessionmanager/admin/user/:userId/terminate-all` | Logout user everywhere |
|
|
755
|
-
| `GET` | `/magic-sessionmanager/admin/geolocation/:ipAddress` | Get IP info (Premium) |
|
|
756
|
-
| `GET` | `/magic-sessionmanager/admin/settings` | Get plugin settings |
|
|
757
|
-
| `PUT` | `/magic-sessionmanager/admin/settings` | Update plugin settings |
|
|
758
|
-
| `GET` | `/magic-sessionmanager/admin/license/status` | Get license status |
|
|
759
|
-
| `POST` | `/magic-sessionmanager/admin/license/activate` | Activate license |
|
|
760
|
-
|
|
761
|
-
---
|
|
762
|
-
|
|
763
|
-
## ⚙️ Configuration
|
|
244
|
+
**How to enable:**
|
|
764
245
|
|
|
765
|
-
|
|
246
|
+
Add to `config/plugins.ts`:
|
|
766
247
|
|
|
767
248
|
```typescript
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
//
|
|
774
|
-
// Prevents excessive DB writes
|
|
775
|
-
lastSeenRateLimit: 30000, // 30 seconds (default)
|
|
776
|
-
|
|
777
|
-
// Session inactivity timeout (milliseconds)
|
|
778
|
-
// Sessions inactive longer than this are marked inactive
|
|
779
|
-
inactivityTimeout: 15 * 60 * 1000, // 15 minutes (default)
|
|
780
|
-
|
|
781
|
-
// IMPORTANT: Set this LOWER than your JWT expiration
|
|
782
|
-
// to prevent orphaned sessions
|
|
783
|
-
},
|
|
784
|
-
},
|
|
785
|
-
});
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
### Relationship with JWT Config
|
|
789
|
-
|
|
790
|
-
```typescript
|
|
791
|
-
// src/config/plugins.ts
|
|
792
|
-
export default () => ({
|
|
793
|
-
// Strapi JWT Configuration
|
|
794
|
-
'users-permissions': {
|
|
795
|
-
config: {
|
|
796
|
-
jwt: {
|
|
797
|
-
expiresIn: '30m', // Access Token expires after 30 minutes
|
|
798
|
-
},
|
|
249
|
+
'users-permissions': {
|
|
250
|
+
config: {
|
|
251
|
+
jwtManagement: 'refresh', // Enable refresh tokens
|
|
252
|
+
sessions: {
|
|
253
|
+
accessTokenLifespan: 3600, // 1 hour
|
|
254
|
+
maxRefreshTokenLifespan: 2592000, // 30 days
|
|
799
255
|
},
|
|
800
256
|
},
|
|
801
|
-
|
|
802
|
-
// Session Manager Configuration
|
|
803
|
-
'magic-sessionmanager': {
|
|
804
|
-
enabled: true,
|
|
805
|
-
config: {
|
|
806
|
-
// Set inactivity timeout LOWER than JWT expiration
|
|
807
|
-
// This prevents orphaned sessions when JWT expires
|
|
808
|
-
inactivityTimeout: 15 * 60 * 1000, // 15 minutes < 30 minutes JWT
|
|
809
|
-
|
|
810
|
-
// Or match JWT expiration exactly:
|
|
811
|
-
// inactivityTimeout: 30 * 60 * 1000, // 30 minutes = JWT expiration
|
|
812
|
-
},
|
|
813
|
-
},
|
|
814
|
-
});
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
### Premium Config
|
|
818
|
-
|
|
819
|
-
Available through Admin UI **Settings → Sessions → Settings**:
|
|
820
|
-
|
|
821
|
-
```typescript
|
|
822
|
-
// Settings stored in database via Admin UI
|
|
823
|
-
{
|
|
824
|
-
// Geolocation & Security
|
|
825
|
-
enableGeolocation: true,
|
|
826
|
-
enableSecurityScoring: true,
|
|
827
|
-
blockSuspiciousSessions: true,
|
|
828
|
-
alertOnVpnProxy: true,
|
|
829
|
-
|
|
830
|
-
// Geo-Fencing
|
|
831
|
-
enableGeofencing: true,
|
|
832
|
-
allowedCountries: ["DE", "AT", "CH"], // Germany, Austria, Switzerland
|
|
833
|
-
blockedCountries: ["RU", "CN"], // Russia, China
|
|
834
|
-
|
|
835
|
-
// Notifications
|
|
836
|
-
enableEmailAlerts: true,
|
|
837
|
-
alertOnSuspiciousLogin: true,
|
|
838
|
-
enableWebhooks: true,
|
|
839
|
-
discordWebhookUrl: "https://discord.com/api/webhooks/...",
|
|
840
|
-
slackWebhookUrl: "https://hooks.slack.com/services/...",
|
|
841
257
|
}
|
|
842
258
|
```
|
|
843
259
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
### Encryption
|
|
849
|
-
|
|
850
|
-
All JWT tokens are **encrypted before storing** in the database using **AES-256-GCM** encryption.
|
|
851
|
-
|
|
852
|
-
#### Why Encrypt Tokens?
|
|
853
|
-
|
|
854
|
-
```
|
|
855
|
-
❌ Without Encryption:
|
|
856
|
-
Database compromised → Attacker sees JWTs → Can impersonate users!
|
|
857
|
-
|
|
858
|
-
✅ With Encryption:
|
|
859
|
-
Database compromised → Attacker sees encrypted data → Useless without key!
|
|
860
|
-
```
|
|
861
|
-
|
|
862
|
-
#### How It Works
|
|
863
|
-
|
|
864
|
-
```
|
|
865
|
-
Login: User gets JWT
|
|
866
|
-
↓
|
|
867
|
-
JWT: "eyJhbGciOiJIUzI1NiIs..."
|
|
868
|
-
↓
|
|
869
|
-
[Encrypt with AES-256-GCM]
|
|
870
|
-
↓
|
|
871
|
-
Encrypted: "a3f7b2c1:8c4d9e2a:f2a5b8c3d4e5f6a7..."
|
|
872
|
-
↓
|
|
873
|
-
Stored in Database (secure!)
|
|
874
|
-
|
|
875
|
-
Logout: User sends JWT
|
|
876
|
-
↓
|
|
877
|
-
[Fetch all active sessions from DB]
|
|
878
|
-
↓
|
|
879
|
-
[Decrypt each token]
|
|
880
|
-
↓
|
|
881
|
-
[Compare with user's JWT]
|
|
882
|
-
↓
|
|
883
|
-
Match found → Terminate session ✅
|
|
884
|
-
```
|
|
885
|
-
|
|
886
|
-
#### Configuration
|
|
887
|
-
|
|
888
|
-
**Generate Encryption Key (Admin Panel):**
|
|
889
|
-
|
|
890
|
-
1. Go to **Admin → Sessions → Settings**
|
|
891
|
-
2. Open **Security Settings** accordion
|
|
892
|
-
3. Find **JWT Encryption Key Generator**
|
|
893
|
-
4. Click **"Generate Key"**
|
|
894
|
-
5. Copy key with **"Copy for .env"** button
|
|
895
|
-
6. Add to your `.env` file
|
|
896
|
-
|
|
897
|
-
**Or generate manually:**
|
|
898
|
-
|
|
899
|
-
```bash
|
|
900
|
-
# Generate secure 32-byte key
|
|
901
|
-
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
260
|
+
**What this does:**
|
|
261
|
+
- Users stay logged in longer (better experience)
|
|
262
|
+
- But admins can still force-logout completely (better security)
|
|
263
|
+
- Best of both worlds! ✅
|
|
902
264
|
|
|
903
|
-
|
|
904
|
-
SESSION_ENCRYPTION_KEY=aBc123XyZ...your-32-char-key
|
|
905
|
-
```
|
|
265
|
+
---
|
|
906
266
|
|
|
907
|
-
|
|
267
|
+
## 🌍 Premium Features (Optional License)
|
|
908
268
|
|
|
909
|
-
|
|
910
|
-
- Plugin uses `APP_KEYS` or `API_TOKEN_SALT` as fallback
|
|
911
|
-
- ⚠️ Warning logged on startup
|
|
912
|
-
- Still encrypted, but key is derived from Strapi's keys
|
|
269
|
+
### IP Geolocation
|
|
913
270
|
|
|
914
|
-
**
|
|
915
|
-
|
|
271
|
+
**See where users login from:**
|
|
272
|
+
- Country (with flag! 🇩🇪🇺🇸🇬🇧)
|
|
273
|
+
- City
|
|
274
|
+
- ISP Provider
|
|
275
|
+
- Coordinates (for map)
|
|
916
276
|
|
|
917
|
-
|
|
277
|
+
### Threat Detection
|
|
918
278
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
| Auth Tag | 128 bits (16 bytes) |
|
|
925
|
-
| Format | `iv:authTag:encryptedData` (hex) |
|
|
279
|
+
**Automatically check if IP is:**
|
|
280
|
+
- VPN
|
|
281
|
+
- Proxy
|
|
282
|
+
- Known threat
|
|
283
|
+
- Security score (0-100)
|
|
926
284
|
|
|
927
|
-
###
|
|
285
|
+
### Auto-Blocking
|
|
928
286
|
|
|
929
|
-
|
|
287
|
+
**Block logins from:**
|
|
288
|
+
- Specific countries
|
|
289
|
+
- VPNs or proxies
|
|
290
|
+
- Low security score IPs
|
|
291
|
+
- Known threat IPs
|
|
930
292
|
|
|
931
|
-
|
|
932
|
-
sessionId: "sess_lx3k7_4f2a8b3c_a1b2c3d4e5f6"
|
|
933
|
-
// prefix^ ^timestamp ^user-hash ^random-bytes
|
|
934
|
-
```
|
|
293
|
+
### Notifications
|
|
935
294
|
|
|
936
|
-
**
|
|
937
|
-
-
|
|
938
|
-
-
|
|
939
|
-
-
|
|
940
|
-
-
|
|
295
|
+
**Get alerts when:**
|
|
296
|
+
- Suspicious login detected
|
|
297
|
+
- VPN used
|
|
298
|
+
- New location login
|
|
299
|
+
- Send to Discord or Slack!
|
|
941
300
|
|
|
942
301
|
---
|
|
943
302
|
|
|
944
|
-
##
|
|
945
|
-
|
|
946
|
-
### IP Geolocation & Threat Detection
|
|
947
|
-
|
|
948
|
-
Uses **ipapi.co** API for accurate IP information:
|
|
949
|
-
|
|
950
|
-
```json
|
|
951
|
-
{
|
|
952
|
-
"country": "Germany",
|
|
953
|
-
"country_code": "DE",
|
|
954
|
-
"city": "Berlin",
|
|
955
|
-
"latitude": 52.52,
|
|
956
|
-
"longitude": 13.41,
|
|
957
|
-
"isp": "Deutsche Telekom",
|
|
958
|
-
"isVpn": false,
|
|
959
|
-
"isProxy": false,
|
|
960
|
-
"isThreat": false,
|
|
961
|
-
"securityScore": 95,
|
|
962
|
-
"threatType": null
|
|
963
|
-
}
|
|
964
|
-
```
|
|
965
|
-
|
|
966
|
-
### Auto-Blocking Rules
|
|
967
|
-
|
|
968
|
-
```
|
|
969
|
-
Login attempt from IP: 1.2.3.4
|
|
970
|
-
↓
|
|
971
|
-
[Geolocation Check]
|
|
972
|
-
↓
|
|
973
|
-
isThreat = true → BLOCK ❌
|
|
974
|
-
isVpn = true (if alertOnVpnProxy) → BLOCK ❌
|
|
975
|
-
country = "RU" (if in blockedCountries) → BLOCK ❌
|
|
976
|
-
country ≠ ["DE","AT","CH"] (if allowedCountries set) → BLOCK ❌
|
|
977
|
-
securityScore < 50 → BLOCK ❌
|
|
978
|
-
↓
|
|
979
|
-
None of above? → ALLOW ✅
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### Email Alerts
|
|
983
|
-
|
|
984
|
-
```
|
|
985
|
-
Subject: ⚠️ Unusual Login Activity
|
|
986
|
-
|
|
987
|
-
Hi John,
|
|
988
|
-
|
|
989
|
-
A login from a new location was detected:
|
|
303
|
+
## 📋 Simple API Guide
|
|
990
304
|
|
|
991
|
-
|
|
992
|
-
🌐 IP Address: 192.168.1.100
|
|
993
|
-
🔒 Risk Level: Medium (VPN detected)
|
|
994
|
-
⏰ Time: 2024-01-15 10:30:00 UTC
|
|
995
|
-
💻 Device: Chrome on Windows
|
|
305
|
+
### Get Sessions
|
|
996
306
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
307
|
+
```bash
|
|
308
|
+
# Get all active sessions
|
|
309
|
+
GET /magic-sessionmanager/sessions
|
|
1000
310
|
```
|
|
1001
311
|
|
|
1002
|
-
###
|
|
312
|
+
### Logout
|
|
1003
313
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
━━━━━━━━━━━━━━━━━━
|
|
1008
|
-
User: john@example.com
|
|
1009
|
-
IP: 192.168.1.100
|
|
1010
|
-
Location: Berlin, Germany
|
|
1011
|
-
Risk: ⚠️ Medium (VPN)
|
|
1012
|
-
Browser: Chrome / Windows
|
|
1013
|
-
Time: 2024-01-15 10:30:00
|
|
314
|
+
```bash
|
|
315
|
+
# Logout current user
|
|
316
|
+
POST /api/auth/logout
|
|
1014
317
|
```
|
|
1015
318
|
|
|
1016
|
-
---
|
|
1017
|
-
|
|
1018
|
-
## 💡 Use Cases
|
|
1019
|
-
|
|
1020
319
|
### Force Logout
|
|
1021
320
|
|
|
1022
321
|
```bash
|
|
1023
|
-
# Admin
|
|
1024
|
-
POST /
|
|
1025
|
-
|
|
1026
|
-
# Admin logs out user from all devices
|
|
1027
|
-
POST /api/magic-sessionmanager/admin/user/5/terminate-all
|
|
1028
|
-
|
|
1029
|
-
# Next API request from that user:
|
|
1030
|
-
GET /api/some-endpoint
|
|
1031
|
-
Authorization: Bearer <their JWT>
|
|
1032
|
-
|
|
1033
|
-
# Response: 401 Unauthorized
|
|
1034
|
-
# "All sessions have been terminated. Please login again."
|
|
1035
|
-
```
|
|
1036
|
-
|
|
1037
|
-
### Security Monitoring
|
|
1038
|
-
|
|
1039
|
-
```
|
|
1040
|
-
Premium feature: VPN Detection
|
|
1041
|
-
↓
|
|
1042
|
-
User logs in from VPN
|
|
1043
|
-
↓
|
|
1044
|
-
isVpn = true detected
|
|
1045
|
-
↓
|
|
1046
|
-
Email sent: "Suspicious login from VPN"
|
|
1047
|
-
↓
|
|
1048
|
-
Webhook notification to Slack
|
|
1049
|
-
↓
|
|
1050
|
-
Admin reviews in dashboard
|
|
1051
|
-
↓
|
|
1052
|
-
Admin can terminate session if needed
|
|
322
|
+
# Admin force-logout a session
|
|
323
|
+
POST /magic-sessionmanager/sessions/:sessionId/terminate
|
|
1053
324
|
```
|
|
1054
325
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
```
|
|
1058
|
-
Export all sessions to CSV:
|
|
1059
|
-
- Who logged in
|
|
1060
|
-
- When & where (IP, location)
|
|
1061
|
-
- Device & browser used
|
|
1062
|
-
- Session duration
|
|
1063
|
-
- Logout time (if any)
|
|
1064
|
-
|
|
1065
|
-
Perfect for compliance requirements!
|
|
1066
|
-
```
|
|
326
|
+
**That's all you need to know!**
|
|
1067
327
|
|
|
1068
328
|
---
|
|
1069
329
|
|
|
1070
|
-
##
|
|
330
|
+
## ⚙️ Settings You Can Change
|
|
1071
331
|
|
|
1072
|
-
|
|
332
|
+
**In `config/plugins.ts`:**
|
|
1073
333
|
|
|
1074
|
-
```
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
# Response:
|
|
1084
|
-
{
|
|
1085
|
-
"jwt": "eyJhbGciOiJIUzI1NiIs...",
|
|
1086
|
-
"user": { "id": 1, "email": "test@example.com", ... }
|
|
334
|
+
```typescript
|
|
335
|
+
'magic-sessionmanager': {
|
|
336
|
+
config: {
|
|
337
|
+
// How often to update "last seen" (in milliseconds)
|
|
338
|
+
lastSeenRateLimit: 30000, // Default: 30 seconds
|
|
339
|
+
|
|
340
|
+
// When to mark sessions inactive (in milliseconds)
|
|
341
|
+
inactivityTimeout: 900000, // Default: 15 minutes
|
|
342
|
+
},
|
|
1087
343
|
}
|
|
1088
|
-
|
|
1089
|
-
# Save JWT
|
|
1090
|
-
export JWT="eyJhbGciOiJIUzI1NiIs..."
|
|
1091
|
-
|
|
1092
|
-
# Check session was created
|
|
1093
|
-
curl http://localhost:1337/api/magic-sessionmanager/sessions \
|
|
1094
|
-
-H "Authorization: Bearer $JWT"
|
|
1095
|
-
|
|
1096
|
-
# Should show new session with:
|
|
1097
|
-
# - loginTime
|
|
1098
|
-
# - isActive: true
|
|
1099
|
-
# - ipAddress
|
|
1100
|
-
# - userAgent
|
|
1101
|
-
# - token (matches JWT)
|
|
1102
344
|
```
|
|
1103
345
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
# Check lastActive timestamp
|
|
1112
|
-
curl http://localhost:1337/api/magic-sessionmanager/sessions \
|
|
1113
|
-
-H "Authorization: Bearer $JWT"
|
|
346
|
+
**In Admin Panel (Settings Tab):**
|
|
347
|
+
- Email alerts on/off
|
|
348
|
+
- Webhook URLs (Discord/Slack)
|
|
349
|
+
- Countries to block/allow
|
|
350
|
+
- VPN detection on/off
|
|
351
|
+
- Generate encryption key
|
|
1114
352
|
|
|
1115
|
-
|
|
1116
|
-
sleep 35
|
|
1117
|
-
|
|
1118
|
-
# Second request (should update lastActive)
|
|
1119
|
-
curl http://localhost:1337/api/users \
|
|
1120
|
-
-H "Authorization: Bearer $JWT"
|
|
1121
|
-
|
|
1122
|
-
# Check lastActive changed
|
|
1123
|
-
curl http://localhost:1337/api/magic-sessionmanager/sessions \
|
|
1124
|
-
-H "Authorization: Bearer $JWT"
|
|
1125
|
-
```
|
|
353
|
+
---
|
|
1126
354
|
|
|
1127
|
-
|
|
355
|
+
## 🐛 Common Problems & Fixes
|
|
1128
356
|
|
|
1129
|
-
|
|
1130
|
-
# Logout via Strapi's route (replaced by plugin)
|
|
1131
|
-
curl -X POST http://localhost:1337/api/auth/logout \
|
|
1132
|
-
-H "Authorization: Bearer $JWT"
|
|
357
|
+
### I don't see the Sessions menu
|
|
1133
358
|
|
|
1134
|
-
|
|
359
|
+
**Fix:**
|
|
360
|
+
1. Make sure plugin is in `config/plugins.ts`
|
|
361
|
+
2. Run `npm run build`
|
|
362
|
+
3. Restart Strapi
|
|
363
|
+
4. Refresh browser (Cmd+Shift+R)
|
|
1135
364
|
|
|
1136
|
-
|
|
1137
|
-
curl http://localhost:1337/api/magic-sessionmanager/sessions \
|
|
1138
|
-
-H "Authorization: Bearer $JWT"
|
|
365
|
+
### Sessions not being created
|
|
1139
366
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
367
|
+
**Fix:**
|
|
368
|
+
1. Check Strapi logs for errors
|
|
369
|
+
2. Make sure users are logging in (not already logged in)
|
|
370
|
+
3. Check database is working
|
|
1144
371
|
|
|
1145
|
-
###
|
|
372
|
+
### 401 or 403 errors
|
|
1146
373
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
-H "Authorization: Bearer $JWT_A"
|
|
374
|
+
**Fix:**
|
|
375
|
+
- 401 = Not logged in (need to login as admin)
|
|
376
|
+
- 403 = Not allowed (check you're admin, not regular user)
|
|
1151
377
|
|
|
1152
|
-
|
|
1153
|
-
curl http://localhost:1337/api/users \
|
|
1154
|
-
-H "Authorization: Bearer $JWT_A"
|
|
378
|
+
### Database table "sessions" already exists
|
|
1155
379
|
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
380
|
+
**Fix:**
|
|
381
|
+
- This plugin uses `magic_sessions` table (not `sessions`)
|
|
382
|
+
- If you see this error, another plugin is using that name
|
|
383
|
+
- Our plugin automatically uses the correct name
|
|
1159
384
|
|
|
1160
385
|
---
|
|
1161
386
|
|
|
1162
|
-
##
|
|
1163
|
-
|
|
1164
|
-
### Sessions Not Creating
|
|
1165
|
-
|
|
1166
|
-
**Problem:** Login succeeds but no session record appears.
|
|
1167
|
-
|
|
1168
|
-
**Solutions:**
|
|
1169
|
-
1. Check Strapi logs:
|
|
1170
|
-
```bash
|
|
1171
|
-
npm run develop
|
|
1172
|
-
# Look for: [magic-sessionmanager] 🔍 Login detected!
|
|
1173
|
-
# Look for: [magic-sessionmanager] ✅ Session X created
|
|
1174
|
-
```
|
|
387
|
+
## 💡 When To Use This Plugin
|
|
1175
388
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
389
|
+
**Perfect for:**
|
|
390
|
+
- Multi-tenant apps (see which tenant users are online)
|
|
391
|
+
- E-commerce (track customer sessions)
|
|
392
|
+
- Collaboration tools (show who's currently working)
|
|
393
|
+
- Security-critical apps (force-logout compromised accounts)
|
|
394
|
+
- Compliance requirements (session audit logs)
|
|
1180
395
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
396
|
+
**Not needed if:**
|
|
397
|
+
- Single-user app
|
|
398
|
+
- No need to see who's logged in
|
|
399
|
+
- No security requirements
|
|
1184
400
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
**Problem:** After logout, JWT still authenticates API requests.
|
|
1188
|
-
|
|
1189
|
-
**Explanation:** This is EXPECTED behavior!
|
|
1190
|
-
- JWT tokens are **stateless** - validated by signature alone
|
|
1191
|
-
- Plugin marks session `isActive = false`
|
|
1192
|
-
- But JWT itself remains valid until expiration
|
|
1193
|
-
- Next authenticated request is **blocked** by LastSeen middleware
|
|
401
|
+
---
|
|
1194
402
|
|
|
1195
|
-
|
|
403
|
+
## 🔧 How To Test It
|
|
1196
404
|
|
|
1197
|
-
###
|
|
405
|
+
### Quick Manual Test
|
|
1198
406
|
|
|
1199
|
-
**
|
|
407
|
+
1. **Login to your Strapi app** (frontend or admin)
|
|
408
|
+
2. **Go to Admin → Sessions**
|
|
409
|
+
3. **You should see your session!**
|
|
410
|
+
4. **Click "Terminate" on your session**
|
|
411
|
+
5. **Try to use the app → You're logged out!**
|
|
1200
412
|
|
|
1201
|
-
|
|
413
|
+
### With Postman
|
|
1202
414
|
|
|
1203
|
-
**
|
|
1204
|
-
```
|
|
1205
|
-
|
|
1206
|
-
{
|
|
1207
|
-
'magic-sessionmanager': {
|
|
1208
|
-
config: {
|
|
1209
|
-
inactivityTimeout: 15 * 60 * 1000 // 15 min (if JWT = 30 min)
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
415
|
+
**1. Login:**
|
|
416
|
+
```
|
|
417
|
+
POST http://localhost:1337/api/auth/local
|
|
418
|
+
Body: { "identifier": "user@test.com", "password": "pass123" }
|
|
1213
419
|
```
|
|
1214
420
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
**Solutions:**
|
|
1220
|
-
1. Check rate limit:
|
|
1221
|
-
```typescript
|
|
1222
|
-
config: {
|
|
1223
|
-
lastSeenRateLimit: 5000 // Lower for testing
|
|
1224
|
-
}
|
|
1225
|
-
```
|
|
421
|
+
**2. Check session created:**
|
|
422
|
+
```
|
|
423
|
+
GET http://localhost:1337/magic-sessionmanager/sessions
|
|
424
|
+
```
|
|
1226
425
|
|
|
1227
|
-
|
|
426
|
+
**3. Logout:**
|
|
427
|
+
```
|
|
428
|
+
POST http://localhost:1337/api/auth/logout
|
|
429
|
+
Authorization: Bearer YOUR_JWT_TOKEN
|
|
430
|
+
```
|
|
1228
431
|
|
|
1229
|
-
|
|
1230
|
-
```bash
|
|
1231
|
-
# Look for: [magic-sessionmanager] ✅ LastSeen middleware mounted
|
|
1232
|
-
```
|
|
432
|
+
**Done!**
|
|
1233
433
|
|
|
1234
434
|
---
|
|
1235
435
|
|
|
1236
|
-
##
|
|
436
|
+
## 📦 What Gets Installed
|
|
1237
437
|
|
|
1238
|
-
|
|
438
|
+
When you install this plugin, you get:
|
|
1239
439
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
│ ├── services/
|
|
1247
|
-
│ │ ├── session.js # 💾 Session CRUD operations
|
|
1248
|
-
│ │ ├── geolocation.js # 🌍 IP geolocation (Premium)
|
|
1249
|
-
│ │ ├── notifications.js # 📧 Email/webhook alerts
|
|
1250
|
-
│ │ └── license-guard.js # 🔑 License validation
|
|
1251
|
-
│ ├── controllers/
|
|
1252
|
-
│ │ ├── session.js # 🎮 Session API handlers
|
|
1253
|
-
│ │ ├── settings.js # ⚙️ Settings API
|
|
1254
|
-
│ │ └── license.js # 🔑 License API
|
|
1255
|
-
│ ├── routes/
|
|
1256
|
-
│ │ ├── content-api.js # 🌐 User-facing routes
|
|
1257
|
-
│ │ └── admin.js # 👑 Admin-only routes
|
|
1258
|
-
│ └── utils/
|
|
1259
|
-
│ └── getClientIp.js # 📍 IP extraction (proxy-aware)
|
|
1260
|
-
│
|
|
1261
|
-
├── admin/src/
|
|
1262
|
-
│ ├── pages/
|
|
1263
|
-
│ │ ├── HomePage.jsx # 📊 Main dashboard
|
|
1264
|
-
│ │ ├── ActiveSessions.jsx # 👥 Active sessions tab
|
|
1265
|
-
│ │ ├── Analytics.jsx # 📈 Analytics tab
|
|
1266
|
-
│ │ ├── Settings.jsx # ⚙️ Settings tab
|
|
1267
|
-
│ │ └── License.jsx # 🔑 License tab
|
|
1268
|
-
│ └── components/
|
|
1269
|
-
│ ├── SessionDetailModal.jsx
|
|
1270
|
-
│ └── LicenseGuard.jsx
|
|
1271
|
-
│
|
|
1272
|
-
├── .github/workflows/
|
|
1273
|
-
│ ├── semantic-release.yml # 🚀 NPM publishing
|
|
1274
|
-
│ └── test.yml # ✅ CI/CD tests
|
|
1275
|
-
│
|
|
1276
|
-
├── package.json
|
|
1277
|
-
├── .releaserc.json # 📦 semantic-release config
|
|
1278
|
-
└── README.md
|
|
1279
|
-
```
|
|
440
|
+
- ✅ Dashboard to see all sessions
|
|
441
|
+
- ✅ Session tracking (automatic)
|
|
442
|
+
- ✅ Force logout buttons
|
|
443
|
+
- ✅ Activity monitoring
|
|
444
|
+
- ✅ Encryption (secure)
|
|
445
|
+
- ✅ Multi-device support
|
|
1280
446
|
|
|
1281
|
-
|
|
447
|
+
**Premium features require a license (free to generate):**
|
|
448
|
+
- 🔒 IP Geolocation
|
|
449
|
+
- 🔒 Threat detection
|
|
450
|
+
- 🔒 Auto-blocking
|
|
451
|
+
- 🔒 Email/webhook alerts
|
|
1282
452
|
|
|
1283
|
-
|
|
1284
|
-
# Build
|
|
1285
|
-
npm run build
|
|
453
|
+
---
|
|
1286
454
|
|
|
1287
|
-
|
|
1288
|
-
git commit -m "feat: add new feature" # → MINOR
|
|
1289
|
-
git commit -m "fix: fix bug" # → PATCH
|
|
1290
|
-
git commit -m "feat!: breaking change" # → MAJOR
|
|
1291
|
-
```
|
|
455
|
+
## 🙋 FAQ
|
|
1292
456
|
|
|
1293
|
-
|
|
457
|
+
**Q: Do I need to change my Strapi code?**
|
|
458
|
+
A: No! Just install and enable the plugin.
|
|
1294
459
|
|
|
1295
|
-
|
|
460
|
+
**Q: Will this break my existing logins?**
|
|
461
|
+
A: No! It just tracks them, doesn't change them.
|
|
1296
462
|
|
|
1297
|
-
|
|
463
|
+
**Q: Can users see each other's sessions?**
|
|
464
|
+
A: No! Only admins can see all sessions. Users only see their own.
|
|
1298
465
|
|
|
1299
|
-
|
|
466
|
+
**Q: What if I uninstall the plugin?**
|
|
467
|
+
A: Sessions will stop being tracked. Everything else works normally.
|
|
1300
468
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
fix: correct session cleanup # → v1.0.1
|
|
1304
|
-
feat!: change API response format # → v2.0.0
|
|
1305
|
-
```
|
|
469
|
+
**Q: Does it slow down my app?**
|
|
470
|
+
A: No! It has smart rate-limiting to prevent database spam.
|
|
1306
471
|
|
|
1307
|
-
|
|
472
|
+
**Q: Can I customize the dashboard?**
|
|
473
|
+
A: Not yet, but it's planned for future versions!
|
|
1308
474
|
|
|
1309
475
|
---
|
|
1310
476
|
|
|
@@ -1312,16 +478,16 @@ GitHub Actions automatically publishes to NPM on push to `main`.
|
|
|
1312
478
|
|
|
1313
479
|
- **NPM:** https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager
|
|
1314
480
|
- **GitHub:** https://github.com/Schero94/Magic-Sessionmanager
|
|
1315
|
-
- **
|
|
481
|
+
- **Report Bugs:** https://github.com/Schero94/Magic-Sessionmanager/issues
|
|
1316
482
|
|
|
1317
483
|
---
|
|
1318
484
|
|
|
1319
485
|
## 📄 License
|
|
1320
486
|
|
|
1321
|
-
**MIT License** - Free
|
|
487
|
+
**MIT License** - Free to use!
|
|
1322
488
|
|
|
1323
|
-
**Copyright
|
|
489
|
+
**Copyright © 2025 Schero D.**
|
|
1324
490
|
|
|
1325
491
|
---
|
|
1326
492
|
|
|
1327
|
-
**
|
|
493
|
+
**Made with ❤️ for Strapi v5**
|