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 CHANGED
@@ -1,1310 +1,463 @@
1
1
  # Magic Session Manager 🔐
2
2
 
3
- **Advanced Session Management for Strapi v5** - Track user login/logout, monitor active sessions, and secure your application with IP geolocation, threat detection, and real-time analytics.
3
+ **See who's logged into your Strapi app - and control their sessions!**
4
4
 
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
- [![npm version](https://img.shields.io/npm/v/strapi-plugin-magic-sessionmanager.svg)](https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager)
7
- [![GitHub release](https://img.shields.io/github/v/release/Schero94/Magic-Sessionmanager.svg)](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
+ [![NPM](https://img.shields.io/npm/v/strapi-plugin-magic-sessionmanager.svg)](https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager)
8
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
58
9
 
59
10
  ---
60
11
 
61
- ## 🚀 Quick Start
62
-
63
- ### 1. Install Plugin
12
+ ## 📸 What It Looks Like
64
13
 
65
- ```bash
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
- ### 2. Register in Config
16
+ ![Dashboard](pics/dashboard.png)
72
17
 
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!) 🔐
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
- ## 🔄 How It Works
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
+ ![Session Modal](pics/dashboardsessionmodal.png)
258
30
 
259
- ### Activity Tracking
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
- Every authenticated request updates `lastActive`:
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
- ### Periodic Cleanup
42
+ ![Session Info Panel](pics/sessioninfopanel.png)
295
43
 
296
- Runs automatically every 30 minutes:
297
-
298
- ```
299
- Cleanup Job (every 30 min)
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
- ## 🔌 Strapi Integration
314
-
315
- ### Routes Integration
316
-
317
- #### Native Strapi Routes (Intercepted)
52
+ ### Settings Page
318
53
 
319
- | Route | Method | Magic Session Manager Action |
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
+ ![Settings 1](pics/settings1.png)
323
55
 
324
- #### Overridden Routes
56
+ **Easy configuration:**
57
+ - Session timeouts
58
+ - Rate limiting
59
+ - Email alerts
60
+ - Webhook notifications
61
+ - Geo-blocking rules
325
62
 
326
- | Route | Method | Magic Session Manager Action |
327
- |-------|--------|------------------------------|
328
- | `/api/auth/logout` | `POST` | **Replaced** - Custom handler terminates session by JWT token |
63
+ ![Settings 2](pics/settings2.png)
329
64
 
330
- #### Plugin Routes
65
+ **Advanced security:**
66
+ - Encryption key generator (one click!)
67
+ - Country allow/block lists
68
+ - VPN detection
69
+ - Threat blocking
331
70
 
332
- | Route | Method | Purpose |
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
- ### JWT Token Handling
73
+ ## What This Plugin Does
340
74
 
341
- #### Access Tokens (JWT)
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
- **Important:** When a JWT expires, the session becomes orphaned but remains `isActive = true` until:
348
- 1. User explicitly logs out
349
- 2. Inactivity timeout triggers cleanup
350
- 3. Admin terminates the session
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
- #### Refresh Tokens ✅ **SOLVED!**
82
+ **When users logout:**
83
+ - Plugin marks their session as "logged out"
84
+ - They disappear from the active sessions list
353
85
 
354
- **What are Refresh Tokens?**
355
- Refresh tokens allow users to get new Access Tokens (JWTs) without re-entering credentials. This enables longer sessions:
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
- **The Solution (v3.2+):**
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
- **How It Works:**
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
- **Session termination is FINAL** - User cannot get new tokens
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
- **Configuration:**
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
- **Testing Refresh Token Blocking:**
112
+ ### Step 3: Rebuild & Start
440
113
 
441
114
  ```bash
442
- # 1. Login and get tokens
443
- curl -X POST http://localhost:1337/api/auth/local \
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
- **This completely solves the refresh token security gap!** 🔒
119
+ ### Step 4: Open Dashboard
464
120
 
465
- ### Without Refresh Tokens (Default Behavior)
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
- If you **don't enable** refresh tokens (`jwtManagement: 'refresh'`):
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
- **Trade-offs:**
130
+ ## 🔐 Security Features (Optional)
501
131
 
502
- | Feature | With Refresh Tokens | Without Refresh Tokens |
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
- **Recommendation:**
134
+ Your JWT tokens are encrypted before saving to database. Generate a key:
510
135
 
511
- **Enable refresh tokens** for better UX + use this plugin to secure them! 🔒
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
- **Testing in Postman:**
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
- 1. Login (get JWT + refreshToken)
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
- **Run Automated Test:**
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
- # Run test suite
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
- # Note: Tests include delays to avoid rate limiting
553
- # Total runtime: ~45-60 seconds (includes 8s pause before refresh token test)
554
- ```
158
+ ## 🎯 Main Features Explained Simply
555
159
 
556
- **Troubleshooting Tests:**
160
+ ### 1. See Who's Logged In
557
161
 
558
- If you get "Too many requests":
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
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
- ### Multi-Login Behavior
168
+ ### 2. Force Logout Anyone
566
169
 
567
- **Strapi Default:** Allows multiple simultaneous logins
568
- **Magic Session Manager:** Tracks each login as separate session
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
- All sessions are active simultaneously.
577
- User can logout from one device without affecting others.
578
- ```
177
+ ### 3. Session Details
579
178
 
580
- ### Magic Link Integration
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
- If you use `strapi-plugin-magic-link`, the session manager automatically detects Magic Link logins:
186
+ ### 4. Multiple Devices
583
187
 
584
- ```javascript
585
- // bootstrap.js line 140
586
- const isMagicLink = ctx.path.includes('/magic-link/login') && ctx.method === 'POST';
587
- ```
188
+ **Users can login from:**
189
+ - Desktop computer
190
+ - Phone
191
+ - Tablet
192
+ - All at the same time!
588
193
 
589
- Sessions are created the same way for Magic Link logins.
194
+ Each login = separate session. You can see them all and logout each individually.
590
195
 
591
- ---
196
+ ### 5. Auto-Cleanup
592
197
 
593
- ## 🎛️ Admin Dashboard
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
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
- ## 📡 API Routes
653
-
654
- ### Content API Routes
205
+ ## 🔒 Refresh Token Protection (Advanced)
655
206
 
656
- All require valid JWT authentication (Bearer token).
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
- #### Logout (Method 1 - Strapi Native)
696
-
697
- ```bash
698
- POST /api/auth/logout
699
- Authorization: Bearer YOUR_JWT
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
- #### Logout (Method 2 - Plugin Endpoint)
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
- #### Logout All Devices
725
-
726
- ```bash
727
- POST /api/magic-sessionmanager/logout-all
728
- Authorization: Bearer YOUR_JWT
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
- ### Relationship with JWT Config
233
+ Add to `config/plugins.ts`:
789
234
 
790
235
  ```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
- },
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
- ## 🔐 JWT Token Security
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
- **Fallback Behavior:**
254
+ ## 🌍 Premium Features (Optional License)
908
255
 
909
- If `SESSION_ENCRYPTION_KEY` is not set:
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
- **Production Recommendation:**
915
- Always use a dedicated `SESSION_ENCRYPTION_KEY` for better security isolation.
258
+ **See where users login from:**
259
+ - Country (with flag! 🇩🇪🇺🇸🇬🇧)
260
+ - City
261
+ - ISP Provider
262
+ - Coordinates (for map)
916
263
 
917
- #### Security Details
264
+ ### Threat Detection
918
265
 
919
- | Feature | Value |
920
- |---------|-------|
921
- | Algorithm | AES-256-GCM |
922
- | Key Size | 256 bits (32 bytes) |
923
- | IV Length | 128 bits (16 bytes) |
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
- ### Unique Session IDs
272
+ ### Auto-Blocking
928
273
 
929
- Each session gets a cryptographically unique identifier:
274
+ **Block logins from:**
275
+ - Specific countries
276
+ - VPNs or proxies
277
+ - Low security score IPs
278
+ - Known threat IPs
930
279
 
931
- ```javascript
932
- sessionId: "sess_lx3k7_4f2a8b3c_a1b2c3d4e5f6"
933
- // prefix^ ^timestamp ^user-hash ^random-bytes
934
- ```
280
+ ### Notifications
935
281
 
936
- **Benefits:**
937
- - No collisions across sessions
938
- - Traceable session identifiers
939
- - Independent from database IDs
940
- - URL-safe for future features
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
- ## 🔒 Premium Features
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
- 📍 Location: Berlin, Germany
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
- If this wasn't you, secure your account immediately.
998
-
999
- Magic Session Manager
294
+ ```bash
295
+ # Get all active sessions
296
+ GET /magic-sessionmanager/sessions
1000
297
  ```
1001
298
 
1002
- ### Webhook Notifications
299
+ ### Logout
1003
300
 
1004
- **Discord:**
1005
- ```
1006
- 🔓 NEW LOGIN
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 terminates specific session
1024
- POST /api/magic-sessionmanager/admin/sessions/123/terminate
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
- ### Compliance Audit
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
- ## 🧪 Testing
317
+ ## ⚙️ Settings You Can Change
1071
318
 
1072
- ### 1. Test Login & Session Creation
319
+ **In `config/plugins.ts`:**
1073
320
 
1074
- ```bash
1075
- # Login via Strapi's native route
1076
- curl -X POST http://localhost:1337/api/auth/local \
1077
- -H "Content-Type: application/json" \
1078
- -d '{
1079
- "identifier": "test@example.com",
1080
- "password": "Test@123"
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
- ### 2. Test Activity Tracking
1105
-
1106
- ```bash
1107
- # First request (updates lastActive)
1108
- curl http://localhost:1337/api/users \
1109
- -H "Authorization: Bearer $JWT"
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
- # Wait 35 seconds (> 30s rate limit)
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
- ### 3. Test Logout
342
+ ## 🐛 Common Problems & Fixes
1128
343
 
1129
- ```bash
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
- # Response: { "message": "Logged out successfully" }
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
- # Check session is inactive
1137
- curl http://localhost:1337/api/magic-sessionmanager/sessions \
1138
- -H "Authorization: Bearer $JWT"
352
+ ### Sessions not being created
1139
353
 
1140
- # Should show:
1141
- # - isActive: false
1142
- # - logoutTime: (timestamp)
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
- ### 4. Test Force Logout
359
+ ### 401 or 403 errors
1146
360
 
1147
- ```bash
1148
- # User A terminates all their sessions
1149
- curl -X POST http://localhost:1337/api/magic-sessionmanager/logout-all \
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
- # Try to use API with old JWT
1153
- curl http://localhost:1337/api/users \
1154
- -H "Authorization: Bearer $JWT_A"
365
+ ### Database table "sessions" already exists
1155
366
 
1156
- # Response: 401 Unauthorized
1157
- # "All sessions have been terminated. Please login again."
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
- ## 🐛 Troubleshooting
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
- 2. Verify middleware is mounted:
1177
- ```bash
1178
- # Look for: [magic-sessionmanager] Login/Logout interceptor middleware mounted
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
- 3. Check `plugin::magic-sessionmanager.session` collection exists:
1182
- - Go to Admin → Content Manager
1183
- - Look for "Session" collection
383
+ **Not needed if:**
384
+ - Single-user app
385
+ - No need to see who's logged in
386
+ - No security requirements
1184
387
 
1185
- ### JWT Still Works After Logout
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
- **Solution:** This is by design. The middleware blocks requests from users with no active sessions.
390
+ ## 🔧 How To Test It
1196
391
 
1197
- ### Orphaned Sessions
392
+ ### Quick Manual Test
1198
393
 
1199
- **Problem:** Sessions remain `isActive = true` after JWT expires.
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
- **Cause:** JWT expiration > inactivity timeout
400
+ ### With Postman
1202
401
 
1203
- **Solution:**
1204
- ```typescript
1205
- // Set inactivity timeout LOWER than JWT expiration
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
- ### LastSeen Not Updating
1216
-
1217
- **Problem:** `lastActive` timestamp doesn't change.
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
- 2. Wait longer than rate limit (default 30s)
413
+ **3. Logout:**
414
+ ```
415
+ POST http://localhost:1337/api/auth/logout
416
+ Authorization: Bearer YOUR_JWT_TOKEN
417
+ ```
1228
418
 
1229
- 3. Verify middleware mounted:
1230
- ```bash
1231
- # Look for: [magic-sessionmanager] ✅ LastSeen middleware mounted
1232
- ```
419
+ **Done!**
1233
420
 
1234
421
  ---
1235
422
 
1236
- ## 🛠️ Development
423
+ ## 📦 What Gets Installed
1237
424
 
1238
- ### Plugin Structure
425
+ When you install this plugin, you get:
1239
426
 
1240
- ```
1241
- magic-sessionmanager/
1242
- ├── server/src/
1243
- │ ├── bootstrap.js # ⚙️ CORE: Mounts middlewares & intercepts routes
1244
- │ ├── middlewares/
1245
- │ │ └── last-seen.js # 🔄 Updates lastActive on each request
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
- ### Build & Release
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
- ```bash
1284
- # Build
1285
- npm run build
440
+ ---
1286
441
 
1287
- # Release (automatic via semantic commits)
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
- ## 📦 NPM Release Process
447
+ **Q: Will this break my existing logins?**
448
+ A: No! It just tracks them, doesn't change them.
1296
449
 
1297
- Uses **semantic-release** for automated versioning.
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
- ### Commit Format
453
+ **Q: What if I uninstall the plugin?**
454
+ A: Sessions will stop being tracked. Everything else works normally.
1300
455
 
1301
- ```bash
1302
- feat: add geo-fencing support # v1.1.0
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
- GitHub Actions automatically publishes to NPM on push to `main`.
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
- - **Issues:** https://github.com/Schero94/Magic-Sessionmanager/issues
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 for personal & commercial use
474
+ **MIT License** - Free to use!
1322
475
 
1323
- **Copyright (c) 2025 Schero D.**
476
+ **Copyright © 2025 Schero D.**
1324
477
 
1325
478
  ---
1326
479
 
1327
- **Built with ❤️ for Strapi v5**
480
+ **Made with ❤️ for Strapi v5**