strapi-plugin-magic-sessionmanager 3.3.2 → 3.4.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 +294 -1141
- 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/README.md
CHANGED
|
@@ -1,1310 +1,463 @@
|
|
|
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
|
|
12
|
+
## 📸 What It Looks Like
|
|
64
13
|
|
|
65
|
-
|
|
66
|
-
npm install strapi-plugin-magic-sessionmanager
|
|
67
|
-
# or
|
|
68
|
-
yarn add strapi-plugin-magic-sessionmanager
|
|
69
|
-
```
|
|
14
|
+
### Main Dashboard - See All Active Sessions
|
|
70
15
|
|
|
71
|
-
|
|
16
|
+

|
|
72
17
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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!) 🔐
|
|
105
|
-
|
|
106
|
-
Generate a secure encryption key for JWT token storage:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
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
|
|
124
|
-
|
|
125
|
-
### 5. Access Admin Dashboard
|
|
126
|
-
|
|
127
|
-
- Navigate to Strapi Admin: `http://localhost:1337/admin`
|
|
128
|
-
- Find **Sessions** in the left sidebar under plugins
|
|
129
|
-
- Start with the **License** tab to activate your license
|
|
130
|
-
- Go to **Settings → Security** to generate your encryption key
|
|
18
|
+
**What you see:**
|
|
19
|
+
- Who is logged in right now (green = online)
|
|
20
|
+
- When they logged in
|
|
21
|
+
- What device they're using
|
|
22
|
+
- Their IP address and location
|
|
23
|
+
- One-click session termination
|
|
131
24
|
|
|
132
25
|
---
|
|
133
26
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
### Architecture Overview
|
|
137
|
-
|
|
138
|
-
Magic Session Manager works by **intercepting Strapi's native authentication routes** WITHOUT replacing them. It uses middleware to hook into the authentication flow:
|
|
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
|
-
```
|
|
230
|
-
|
|
231
|
-
### Logout Flow
|
|
232
|
-
|
|
233
|
-
Magic Session Manager **replaces** the default `/api/auth/logout` route:
|
|
27
|
+
### Session Details Modal
|
|
234
28
|
|
|
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
|
-
```
|
|
29
|
+

|
|
258
30
|
|
|
259
|
-
|
|
31
|
+
**Click any session to see:**
|
|
32
|
+
- Full device information
|
|
33
|
+
- Browser and operating system
|
|
34
|
+
- Complete session history
|
|
35
|
+
- IP geolocation (Premium)
|
|
36
|
+
- Security risk score (Premium)
|
|
260
37
|
|
|
261
|
-
|
|
38
|
+
---
|
|
262
39
|
|
|
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
|
-
```
|
|
40
|
+
### Content Manager Integration
|
|
293
41
|
|
|
294
|
-
|
|
42
|
+

|
|
295
43
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
Find sessions where:
|
|
302
|
-
lastActive < (now - inactivityTimeout)
|
|
303
|
-
AND isActive = true
|
|
304
|
-
↓
|
|
305
|
-
For each inactive session:
|
|
306
|
-
Update: isActive = false
|
|
307
|
-
↓
|
|
308
|
-
Log: "Cleaned up X inactive sessions"
|
|
309
|
-
```
|
|
44
|
+
**When viewing a user:**
|
|
45
|
+
- Sidebar shows their active sessions
|
|
46
|
+
- Quick actions (terminate, block)
|
|
47
|
+
- Offline/Online status indicator
|
|
48
|
+
- No need to leave the page!
|
|
310
49
|
|
|
311
50
|
---
|
|
312
51
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
### Routes Integration
|
|
316
|
-
|
|
317
|
-
#### Native Strapi Routes (Intercepted)
|
|
52
|
+
### Settings Page
|
|
318
53
|
|
|
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) |
|
|
54
|
+

|
|
323
55
|
|
|
324
|
-
|
|
56
|
+
**Easy configuration:**
|
|
57
|
+
- Session timeouts
|
|
58
|
+
- Rate limiting
|
|
59
|
+
- Email alerts
|
|
60
|
+
- Webhook notifications
|
|
61
|
+
- Geo-blocking rules
|
|
325
62
|
|
|
326
|
-
|
|
327
|
-
|-------|--------|------------------------------|
|
|
328
|
-
| `/api/auth/logout` | `POST` | **Replaced** - Custom handler terminates session by JWT token |
|
|
63
|
+

|
|
329
64
|
|
|
330
|
-
|
|
65
|
+
**Advanced security:**
|
|
66
|
+
- Encryption key generator (one click!)
|
|
67
|
+
- Country allow/block lists
|
|
68
|
+
- VPN detection
|
|
69
|
+
- Threat blocking
|
|
331
70
|
|
|
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 |
|
|
71
|
+
---
|
|
338
72
|
|
|
339
|
-
|
|
73
|
+
## ✨ What This Plugin Does
|
|
340
74
|
|
|
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)
|
|
75
|
+
### Simple Version
|
|
346
76
|
|
|
347
|
-
**
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
77
|
+
**When users login:**
|
|
78
|
+
- Plugin saves who logged in, when, and from where
|
|
79
|
+
- You can see them in the dashboard (see screenshot above)
|
|
80
|
+
- You can force-logout anyone anytime
|
|
351
81
|
|
|
352
|
-
|
|
82
|
+
**When users logout:**
|
|
83
|
+
- Plugin marks their session as "logged out"
|
|
84
|
+
- They disappear from the active sessions list
|
|
353
85
|
|
|
354
|
-
**
|
|
355
|
-
|
|
86
|
+
**While users are active:**
|
|
87
|
+
- Plugin updates their "last seen" time
|
|
88
|
+
- You always know who's currently using your app
|
|
356
89
|
|
|
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
|
-
```
|
|
90
|
+
---
|
|
369
91
|
|
|
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 ✅
|
|
92
|
+
## 🚀 Quick Install
|
|
374
93
|
|
|
375
|
-
|
|
94
|
+
### Step 1: Install
|
|
376
95
|
|
|
96
|
+
```bash
|
|
97
|
+
npm install strapi-plugin-magic-sessionmanager
|
|
377
98
|
```
|
|
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
99
|
|
|
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
|
|
100
|
+
### Step 2: Enable Plugin
|
|
412
101
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
Enable refresh tokens in Strapi:
|
|
102
|
+
Add this to `config/plugins.ts`:
|
|
416
103
|
|
|
417
104
|
```typescript
|
|
418
|
-
// src/config/plugins.ts
|
|
419
105
|
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
106
|
'magic-sessionmanager': {
|
|
431
107
|
enabled: true,
|
|
432
|
-
config: {
|
|
433
|
-
inactivityTimeout: 15 * 60 * 1000, // 15 minutes
|
|
434
|
-
},
|
|
435
108
|
},
|
|
436
109
|
});
|
|
437
110
|
```
|
|
438
111
|
|
|
439
|
-
|
|
112
|
+
### Step 3: Rebuild & Start
|
|
440
113
|
|
|
441
114
|
```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."
|
|
115
|
+
npm run build
|
|
116
|
+
npm run develop
|
|
461
117
|
```
|
|
462
118
|
|
|
463
|
-
|
|
119
|
+
### Step 4: Open Dashboard
|
|
464
120
|
|
|
465
|
-
|
|
121
|
+
1. Go to Strapi Admin: `http://localhost:1337/admin`
|
|
122
|
+
2. Look in the left sidebar for **"Sessions"**
|
|
123
|
+
3. Click it!
|
|
124
|
+
4. You'll see the dashboard (like the screenshot above)
|
|
466
125
|
|
|
467
|
-
|
|
126
|
+
**That's it! You're done!** 🎉
|
|
468
127
|
|
|
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
|
-
```
|
|
494
|
-
|
|
495
|
-
**If you try to call `/api/auth/refresh` without enabling it:**
|
|
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
|
|
128
|
+
---
|
|
499
129
|
|
|
500
|
-
|
|
130
|
+
## 🔐 Security Features (Optional)
|
|
501
131
|
|
|
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 |
|
|
132
|
+
### Encryption Key (Recommended)
|
|
508
133
|
|
|
509
|
-
|
|
134
|
+
Your JWT tokens are encrypted before saving to database. Generate a key:
|
|
510
135
|
|
|
511
|
-
**
|
|
136
|
+
**In Admin Panel:**
|
|
137
|
+
1. Go to **Sessions → Settings**
|
|
138
|
+
2. Scroll to **"JWT Encryption Key Generator"**
|
|
139
|
+
3. Click **"Generate Key"**
|
|
140
|
+
4. Click **"Copy for .env"**
|
|
141
|
+
5. Paste into your `.env` file
|
|
142
|
+
6. Restart Strapi
|
|
512
143
|
|
|
513
|
-
**
|
|
144
|
+
**Or generate manually:**
|
|
145
|
+
```bash
|
|
146
|
+
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
147
|
+
```
|
|
514
148
|
|
|
149
|
+
Then add to `.env`:
|
|
515
150
|
```
|
|
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."
|
|
151
|
+
SESSION_ENCRYPTION_KEY=your-key-here
|
|
533
152
|
```
|
|
534
153
|
|
|
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
|
|
154
|
+
**Why?** If someone hacks your database, they can't steal user sessions! 🔒
|
|
545
155
|
|
|
546
|
-
|
|
547
|
-
node test-session-manager.js
|
|
548
|
-
|
|
549
|
-
# Look for "USER TEST 5: Blocked Refresh Token Test"
|
|
550
|
-
# Should show: ✅ Refresh token BLOCKED as expected!
|
|
156
|
+
---
|
|
551
157
|
|
|
552
|
-
|
|
553
|
-
# Total runtime: ~45-60 seconds (includes 8s pause before refresh token test)
|
|
554
|
-
```
|
|
158
|
+
## 🎯 Main Features Explained Simply
|
|
555
159
|
|
|
556
|
-
|
|
160
|
+
### 1. See Who's Logged In
|
|
557
161
|
|
|
558
|
-
|
|
559
|
-
-
|
|
560
|
-
-
|
|
561
|
-
-
|
|
562
|
-
-
|
|
563
|
-
- Or run individual tests instead of full suite
|
|
162
|
+
**Dashboard Tab:**
|
|
163
|
+
- Shows all active users
|
|
164
|
+
- Green badge = currently online
|
|
165
|
+
- Gray badge = logged out
|
|
166
|
+
- Click to see details
|
|
564
167
|
|
|
565
|
-
###
|
|
168
|
+
### 2. Force Logout Anyone
|
|
566
169
|
|
|
567
|
-
**
|
|
568
|
-
|
|
170
|
+
**Need to kick someone out?**
|
|
171
|
+
1. Find their session
|
|
172
|
+
2. Click **"Terminate"**
|
|
173
|
+
3. Done! They're logged out immediately
|
|
569
174
|
|
|
570
|
-
|
|
571
|
-
User logs in from:
|
|
572
|
-
- Desktop (Chrome) → Session 1
|
|
573
|
-
- Mobile (Safari) → Session 2
|
|
574
|
-
- Laptop (Firefox) → Session 3
|
|
175
|
+
**Even works if they have refresh tokens!** (See below)
|
|
575
176
|
|
|
576
|
-
|
|
577
|
-
User can logout from one device without affecting others.
|
|
578
|
-
```
|
|
177
|
+
### 3. Session Details
|
|
579
178
|
|
|
580
|
-
|
|
179
|
+
**Click any session to see:**
|
|
180
|
+
- When they logged in
|
|
181
|
+
- Last time they did something
|
|
182
|
+
- What browser/device they use
|
|
183
|
+
- Their IP address
|
|
184
|
+
- Location (if Premium)
|
|
581
185
|
|
|
582
|
-
|
|
186
|
+
### 4. Multiple Devices
|
|
583
187
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
188
|
+
**Users can login from:**
|
|
189
|
+
- Desktop computer
|
|
190
|
+
- Phone
|
|
191
|
+
- Tablet
|
|
192
|
+
- All at the same time!
|
|
588
193
|
|
|
589
|
-
|
|
194
|
+
Each login = separate session. You can see them all and logout each individually.
|
|
590
195
|
|
|
591
|
-
|
|
196
|
+
### 5. Auto-Cleanup
|
|
592
197
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
|
642
|
-
|
|
643
|
-
#### 4. 🔑 **License**
|
|
644
|
-
- Activate license key
|
|
645
|
-
- View license status & expiry
|
|
646
|
-
- Offline mode information
|
|
647
|
-
- License holder details
|
|
648
|
-
- Auto-ping status (15-minute intervals)
|
|
198
|
+
**Inactive sessions are automatically cleaned up:**
|
|
199
|
+
- If user doesn't do anything for 15 minutes (configurable)
|
|
200
|
+
- Session is marked as "inactive"
|
|
201
|
+
- Keeps your database clean
|
|
649
202
|
|
|
650
203
|
---
|
|
651
204
|
|
|
652
|
-
##
|
|
653
|
-
|
|
654
|
-
### Content API Routes
|
|
205
|
+
## 🔒 Refresh Token Protection (Advanced)
|
|
655
206
|
|
|
656
|
-
|
|
207
|
+
### The Problem (Without This Plugin)
|
|
657
208
|
|
|
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
209
|
```
|
|
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
|
|
210
|
+
Admin kicks out a user
|
|
211
|
+
↓
|
|
212
|
+
User has "refresh token"
|
|
213
|
+
↓
|
|
214
|
+
User gets new login token automatically
|
|
215
|
+
↓
|
|
216
|
+
User is back in! 😱
|
|
708
217
|
```
|
|
709
218
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
```bash
|
|
713
|
-
POST /api/magic-sessionmanager/logout
|
|
714
|
-
Authorization: Bearer YOUR_JWT
|
|
219
|
+
### The Solution (With This Plugin)
|
|
715
220
|
|
|
716
|
-
Response:
|
|
717
|
-
{
|
|
718
|
-
"message": "Session terminated successfully"
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
# Alternative endpoint with same behavior
|
|
722
221
|
```
|
|
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
|
|
222
|
+
Admin kicks out a user
|
|
223
|
+
↓
|
|
224
|
+
User tries to use refresh token
|
|
225
|
+
↓
|
|
226
|
+
Plugin blocks it! 🚫
|
|
227
|
+
↓
|
|
228
|
+
User MUST login again
|
|
738
229
|
```
|
|
739
230
|
|
|
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
|
|
764
|
-
|
|
765
|
-
### Basic Config
|
|
766
|
-
|
|
767
|
-
```typescript
|
|
768
|
-
// src/config/plugins.ts
|
|
769
|
-
export default () => ({
|
|
770
|
-
'magic-sessionmanager': {
|
|
771
|
-
enabled: true,
|
|
772
|
-
config: {
|
|
773
|
-
// Rate limit for lastSeen updates (milliseconds)
|
|
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
|
-
```
|
|
231
|
+
**How to enable:**
|
|
787
232
|
|
|
788
|
-
|
|
233
|
+
Add to `config/plugins.ts`:
|
|
789
234
|
|
|
790
235
|
```typescript
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
//
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
expiresIn: '30m', // Access Token expires after 30 minutes
|
|
798
|
-
},
|
|
236
|
+
'users-permissions': {
|
|
237
|
+
config: {
|
|
238
|
+
jwtManagement: 'refresh', // Enable refresh tokens
|
|
239
|
+
sessions: {
|
|
240
|
+
accessTokenLifespan: 3600, // 1 hour
|
|
241
|
+
maxRefreshTokenLifespan: 2592000, // 30 days
|
|
799
242
|
},
|
|
800
243
|
},
|
|
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
244
|
}
|
|
842
245
|
```
|
|
843
246
|
|
|
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?
|
|
247
|
+
**What this does:**
|
|
248
|
+
- Users stay logged in longer (better experience)
|
|
249
|
+
- But admins can still force-logout completely (better security)
|
|
250
|
+
- Best of both worlds! ✅
|
|
853
251
|
|
|
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'))"
|
|
902
|
-
|
|
903
|
-
# Add to .env
|
|
904
|
-
SESSION_ENCRYPTION_KEY=aBc123XyZ...your-32-char-key
|
|
905
|
-
```
|
|
252
|
+
---
|
|
906
253
|
|
|
907
|
-
|
|
254
|
+
## 🌍 Premium Features (Optional License)
|
|
908
255
|
|
|
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
|
|
256
|
+
### IP Geolocation
|
|
913
257
|
|
|
914
|
-
**
|
|
915
|
-
|
|
258
|
+
**See where users login from:**
|
|
259
|
+
- Country (with flag! 🇩🇪🇺🇸🇬🇧)
|
|
260
|
+
- City
|
|
261
|
+
- ISP Provider
|
|
262
|
+
- Coordinates (for map)
|
|
916
263
|
|
|
917
|
-
|
|
264
|
+
### Threat Detection
|
|
918
265
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
| Auth Tag | 128 bits (16 bytes) |
|
|
925
|
-
| Format | `iv:authTag:encryptedData` (hex) |
|
|
266
|
+
**Automatically check if IP is:**
|
|
267
|
+
- VPN
|
|
268
|
+
- Proxy
|
|
269
|
+
- Known threat
|
|
270
|
+
- Security score (0-100)
|
|
926
271
|
|
|
927
|
-
###
|
|
272
|
+
### Auto-Blocking
|
|
928
273
|
|
|
929
|
-
|
|
274
|
+
**Block logins from:**
|
|
275
|
+
- Specific countries
|
|
276
|
+
- VPNs or proxies
|
|
277
|
+
- Low security score IPs
|
|
278
|
+
- Known threat IPs
|
|
930
279
|
|
|
931
|
-
|
|
932
|
-
sessionId: "sess_lx3k7_4f2a8b3c_a1b2c3d4e5f6"
|
|
933
|
-
// prefix^ ^timestamp ^user-hash ^random-bytes
|
|
934
|
-
```
|
|
280
|
+
### Notifications
|
|
935
281
|
|
|
936
|
-
**
|
|
937
|
-
-
|
|
938
|
-
-
|
|
939
|
-
-
|
|
940
|
-
-
|
|
282
|
+
**Get alerts when:**
|
|
283
|
+
- Suspicious login detected
|
|
284
|
+
- VPN used
|
|
285
|
+
- New location login
|
|
286
|
+
- Send to Discord or Slack!
|
|
941
287
|
|
|
942
288
|
---
|
|
943
289
|
|
|
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:
|
|
290
|
+
## 📋 Simple API Guide
|
|
990
291
|
|
|
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
|
|
292
|
+
### Get Sessions
|
|
996
293
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
294
|
+
```bash
|
|
295
|
+
# Get all active sessions
|
|
296
|
+
GET /magic-sessionmanager/sessions
|
|
1000
297
|
```
|
|
1001
298
|
|
|
1002
|
-
###
|
|
299
|
+
### Logout
|
|
1003
300
|
|
|
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
|
|
301
|
+
```bash
|
|
302
|
+
# Logout current user
|
|
303
|
+
POST /api/auth/logout
|
|
1014
304
|
```
|
|
1015
305
|
|
|
1016
|
-
---
|
|
1017
|
-
|
|
1018
|
-
## 💡 Use Cases
|
|
1019
|
-
|
|
1020
306
|
### Force Logout
|
|
1021
307
|
|
|
1022
308
|
```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
|
|
309
|
+
# Admin force-logout a session
|
|
310
|
+
POST /magic-sessionmanager/sessions/:sessionId/terminate
|
|
1053
311
|
```
|
|
1054
312
|
|
|
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
|
-
```
|
|
313
|
+
**That's all you need to know!**
|
|
1067
314
|
|
|
1068
315
|
---
|
|
1069
316
|
|
|
1070
|
-
##
|
|
317
|
+
## ⚙️ Settings You Can Change
|
|
1071
318
|
|
|
1072
|
-
|
|
319
|
+
**In `config/plugins.ts`:**
|
|
1073
320
|
|
|
1074
|
-
```
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
# Response:
|
|
1084
|
-
{
|
|
1085
|
-
"jwt": "eyJhbGciOiJIUzI1NiIs...",
|
|
1086
|
-
"user": { "id": 1, "email": "test@example.com", ... }
|
|
321
|
+
```typescript
|
|
322
|
+
'magic-sessionmanager': {
|
|
323
|
+
config: {
|
|
324
|
+
// How often to update "last seen" (in milliseconds)
|
|
325
|
+
lastSeenRateLimit: 30000, // Default: 30 seconds
|
|
326
|
+
|
|
327
|
+
// When to mark sessions inactive (in milliseconds)
|
|
328
|
+
inactivityTimeout: 900000, // Default: 15 minutes
|
|
329
|
+
},
|
|
1087
330
|
}
|
|
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
331
|
```
|
|
1103
332
|
|
|
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"
|
|
333
|
+
**In Admin Panel (Settings Tab):**
|
|
334
|
+
- Email alerts on/off
|
|
335
|
+
- Webhook URLs (Discord/Slack)
|
|
336
|
+
- Countries to block/allow
|
|
337
|
+
- VPN detection on/off
|
|
338
|
+
- Generate encryption key
|
|
1114
339
|
|
|
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
|
-
```
|
|
340
|
+
---
|
|
1126
341
|
|
|
1127
|
-
|
|
342
|
+
## 🐛 Common Problems & Fixes
|
|
1128
343
|
|
|
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"
|
|
344
|
+
### I don't see the Sessions menu
|
|
1133
345
|
|
|
1134
|
-
|
|
346
|
+
**Fix:**
|
|
347
|
+
1. Make sure plugin is in `config/plugins.ts`
|
|
348
|
+
2. Run `npm run build`
|
|
349
|
+
3. Restart Strapi
|
|
350
|
+
4. Refresh browser (Cmd+Shift+R)
|
|
1135
351
|
|
|
1136
|
-
|
|
1137
|
-
curl http://localhost:1337/api/magic-sessionmanager/sessions \
|
|
1138
|
-
-H "Authorization: Bearer $JWT"
|
|
352
|
+
### Sessions not being created
|
|
1139
353
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
354
|
+
**Fix:**
|
|
355
|
+
1. Check Strapi logs for errors
|
|
356
|
+
2. Make sure users are logging in (not already logged in)
|
|
357
|
+
3. Check database is working
|
|
1144
358
|
|
|
1145
|
-
###
|
|
359
|
+
### 401 or 403 errors
|
|
1146
360
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
-H "Authorization: Bearer $JWT_A"
|
|
361
|
+
**Fix:**
|
|
362
|
+
- 401 = Not logged in (need to login as admin)
|
|
363
|
+
- 403 = Not allowed (check you're admin, not regular user)
|
|
1151
364
|
|
|
1152
|
-
|
|
1153
|
-
curl http://localhost:1337/api/users \
|
|
1154
|
-
-H "Authorization: Bearer $JWT_A"
|
|
365
|
+
### Database table "sessions" already exists
|
|
1155
366
|
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
367
|
+
**Fix:**
|
|
368
|
+
- This plugin uses `magic_sessions` table (not `sessions`)
|
|
369
|
+
- If you see this error, another plugin is using that name
|
|
370
|
+
- Our plugin automatically uses the correct name
|
|
1159
371
|
|
|
1160
372
|
---
|
|
1161
373
|
|
|
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
|
-
```
|
|
374
|
+
## 💡 When To Use This Plugin
|
|
1175
375
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
376
|
+
**Perfect for:**
|
|
377
|
+
- Multi-tenant apps (see which tenant users are online)
|
|
378
|
+
- E-commerce (track customer sessions)
|
|
379
|
+
- Collaboration tools (show who's currently working)
|
|
380
|
+
- Security-critical apps (force-logout compromised accounts)
|
|
381
|
+
- Compliance requirements (session audit logs)
|
|
1180
382
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
383
|
+
**Not needed if:**
|
|
384
|
+
- Single-user app
|
|
385
|
+
- No need to see who's logged in
|
|
386
|
+
- No security requirements
|
|
1184
387
|
|
|
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
|
|
388
|
+
---
|
|
1194
389
|
|
|
1195
|
-
|
|
390
|
+
## 🔧 How To Test It
|
|
1196
391
|
|
|
1197
|
-
###
|
|
392
|
+
### Quick Manual Test
|
|
1198
393
|
|
|
1199
|
-
**
|
|
394
|
+
1. **Login to your Strapi app** (frontend or admin)
|
|
395
|
+
2. **Go to Admin → Sessions**
|
|
396
|
+
3. **You should see your session!**
|
|
397
|
+
4. **Click "Terminate" on your session**
|
|
398
|
+
5. **Try to use the app → You're logged out!**
|
|
1200
399
|
|
|
1201
|
-
|
|
400
|
+
### With Postman
|
|
1202
401
|
|
|
1203
|
-
**
|
|
1204
|
-
```
|
|
1205
|
-
|
|
1206
|
-
{
|
|
1207
|
-
'magic-sessionmanager': {
|
|
1208
|
-
config: {
|
|
1209
|
-
inactivityTimeout: 15 * 60 * 1000 // 15 min (if JWT = 30 min)
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
402
|
+
**1. Login:**
|
|
403
|
+
```
|
|
404
|
+
POST http://localhost:1337/api/auth/local
|
|
405
|
+
Body: { "identifier": "user@test.com", "password": "pass123" }
|
|
1213
406
|
```
|
|
1214
407
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
**Solutions:**
|
|
1220
|
-
1. Check rate limit:
|
|
1221
|
-
```typescript
|
|
1222
|
-
config: {
|
|
1223
|
-
lastSeenRateLimit: 5000 // Lower for testing
|
|
1224
|
-
}
|
|
1225
|
-
```
|
|
408
|
+
**2. Check session created:**
|
|
409
|
+
```
|
|
410
|
+
GET http://localhost:1337/magic-sessionmanager/sessions
|
|
411
|
+
```
|
|
1226
412
|
|
|
1227
|
-
|
|
413
|
+
**3. Logout:**
|
|
414
|
+
```
|
|
415
|
+
POST http://localhost:1337/api/auth/logout
|
|
416
|
+
Authorization: Bearer YOUR_JWT_TOKEN
|
|
417
|
+
```
|
|
1228
418
|
|
|
1229
|
-
|
|
1230
|
-
```bash
|
|
1231
|
-
# Look for: [magic-sessionmanager] ✅ LastSeen middleware mounted
|
|
1232
|
-
```
|
|
419
|
+
**Done!**
|
|
1233
420
|
|
|
1234
421
|
---
|
|
1235
422
|
|
|
1236
|
-
##
|
|
423
|
+
## 📦 What Gets Installed
|
|
1237
424
|
|
|
1238
|
-
|
|
425
|
+
When you install this plugin, you get:
|
|
1239
426
|
|
|
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
|
-
```
|
|
427
|
+
- ✅ Dashboard to see all sessions
|
|
428
|
+
- ✅ Session tracking (automatic)
|
|
429
|
+
- ✅ Force logout buttons
|
|
430
|
+
- ✅ Activity monitoring
|
|
431
|
+
- ✅ Encryption (secure)
|
|
432
|
+
- ✅ Multi-device support
|
|
1280
433
|
|
|
1281
|
-
|
|
434
|
+
**Premium features require a license (free to generate):**
|
|
435
|
+
- 🔒 IP Geolocation
|
|
436
|
+
- 🔒 Threat detection
|
|
437
|
+
- 🔒 Auto-blocking
|
|
438
|
+
- 🔒 Email/webhook alerts
|
|
1282
439
|
|
|
1283
|
-
|
|
1284
|
-
# Build
|
|
1285
|
-
npm run build
|
|
440
|
+
---
|
|
1286
441
|
|
|
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
|
-
```
|
|
442
|
+
## 🙋 FAQ
|
|
1292
443
|
|
|
1293
|
-
|
|
444
|
+
**Q: Do I need to change my Strapi code?**
|
|
445
|
+
A: No! Just install and enable the plugin.
|
|
1294
446
|
|
|
1295
|
-
|
|
447
|
+
**Q: Will this break my existing logins?**
|
|
448
|
+
A: No! It just tracks them, doesn't change them.
|
|
1296
449
|
|
|
1297
|
-
|
|
450
|
+
**Q: Can users see each other's sessions?**
|
|
451
|
+
A: No! Only admins can see all sessions. Users only see their own.
|
|
1298
452
|
|
|
1299
|
-
|
|
453
|
+
**Q: What if I uninstall the plugin?**
|
|
454
|
+
A: Sessions will stop being tracked. Everything else works normally.
|
|
1300
455
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
fix: correct session cleanup # → v1.0.1
|
|
1304
|
-
feat!: change API response format # → v2.0.0
|
|
1305
|
-
```
|
|
456
|
+
**Q: Does it slow down my app?**
|
|
457
|
+
A: No! It has smart rate-limiting to prevent database spam.
|
|
1306
458
|
|
|
1307
|
-
|
|
459
|
+
**Q: Can I customize the dashboard?**
|
|
460
|
+
A: Not yet, but it's planned for future versions!
|
|
1308
461
|
|
|
1309
462
|
---
|
|
1310
463
|
|
|
@@ -1312,16 +465,16 @@ GitHub Actions automatically publishes to NPM on push to `main`.
|
|
|
1312
465
|
|
|
1313
466
|
- **NPM:** https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager
|
|
1314
467
|
- **GitHub:** https://github.com/Schero94/Magic-Sessionmanager
|
|
1315
|
-
- **
|
|
468
|
+
- **Report Bugs:** https://github.com/Schero94/Magic-Sessionmanager/issues
|
|
1316
469
|
|
|
1317
470
|
---
|
|
1318
471
|
|
|
1319
472
|
## 📄 License
|
|
1320
473
|
|
|
1321
|
-
**MIT License** - Free
|
|
474
|
+
**MIT License** - Free to use!
|
|
1322
475
|
|
|
1323
|
-
**Copyright
|
|
476
|
+
**Copyright © 2025 Schero D.**
|
|
1324
477
|
|
|
1325
478
|
---
|
|
1326
479
|
|
|
1327
|
-
**
|
|
480
|
+
**Made with ❤️ for Strapi v5**
|