strapi-plugin-magic-sessionmanager 3.3.2 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,1310 +1,476 @@
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
64
-
65
- ```bash
66
- npm install strapi-plugin-magic-sessionmanager
67
- # or
68
- yarn add strapi-plugin-magic-sessionmanager
69
- ```
70
-
71
- ### 2. Register in Config
72
-
73
- Add to `src/config/plugins.ts` (or `plugins.js`):
74
-
75
- ```typescript
76
- export default () => ({
77
- 'magic-sessionmanager': {
78
- enabled: true,
79
- resolve: './src/plugins/magic-sessionmanager',
80
- config: {
81
- // Optional: rate limit for lastSeen updates (ms)
82
- lastSeenRateLimit: 30000, // 30 seconds (default)
83
-
84
- // Optional: session inactivity timeout (ms)
85
- inactivityTimeout: 15 * 60 * 1000, // 15 minutes (default)
86
- },
87
- },
88
- });
89
- ```
90
-
91
- ### 3. Build & Run
92
-
93
- ```bash
94
- # Install dependencies
95
- npm install
96
-
97
- # Build the plugin (includes admin UI)
98
- npm run build
99
-
100
- # Start Strapi
101
- npm run develop
102
- ```
103
-
104
- ### 4. Configure Encryption (Important!) 🔐
12
+ ## 📸 What It Looks Like
105
13
 
106
- Generate a secure encryption key for JWT token storage:
14
+ ### Homepage Widget - Quick Stats at a Glance
107
15
 
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
16
+ ![Online Users Widget](pics/widget.png)
124
17
 
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
+ **On your Strapi homepage:**
19
+ - See online users instantly
20
+ - Active in last 15/30 minutes
21
+ - Total users count
22
+ - Blocked users count
23
+ - No need to navigate anywhere!
131
24
 
132
25
  ---
133
26
 
134
- ## 🔄 How It Works
135
-
136
- ### Architecture Overview
27
+ ### Main Dashboard - See All Active Sessions
137
28
 
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
- ```
29
+ ![Dashboard](pics/dashboard.png)
230
30
 
231
- ### Logout Flow
31
+ **What you see:**
32
+ - Who is logged in right now (green = online)
33
+ - When they logged in
34
+ - What device they're using
35
+ - Their IP address and location
36
+ - One-click session termination
232
37
 
233
- Magic Session Manager **replaces** the default `/api/auth/logout` route:
38
+ ---
234
39
 
235
- ```
236
- User Logout Request
237
-
238
- [POST /api/auth/logout]
239
- Headers: { Authorization: "Bearer <JWT>" }
240
-
241
- Magic Session Manager Handler (NOT Strapi's default)
242
-
243
- Extract JWT from Authorization header
244
-
245
- Find matching session:
246
- WHERE token = jwt AND isActive = true
247
-
248
- Found? YES → Update session:
249
- {
250
- isActive: false,
251
- logoutTime: now
252
- }
253
-
254
- Found? NO → Continue anyway (idempotent)
255
-
256
- Return: { message: "Logged out successfully" }
257
- ```
40
+ ### Session Details Modal
258
41
 
259
- ### Activity Tracking
42
+ ![Session Modal](pics/dashboardsessionmodal.png)
260
43
 
261
- Every authenticated request updates `lastActive`:
44
+ **Click any session to see:**
45
+ - Full device information
46
+ - Browser and operating system
47
+ - Complete session history
48
+ - IP geolocation (Premium)
49
+ - Security risk score (Premium)
262
50
 
263
- ```
264
- Authenticated API Request
265
- (Any route with valid JWT)
266
-
267
- [LastSeen Middleware - BEFORE request]
268
-
269
- Check: Does user have active session?
270
- WHERE user.id = X AND isActive = true
271
-
272
- NO active sessions?
273
- → Reject: 401 Unauthorized
274
- → Message: "All sessions terminated. Please login again."
275
-
276
- Has active session? Continue ✅
277
-
278
- [Process actual request]
279
-
280
- [LastSeen Middleware - AFTER request]
281
-
282
- Check: Was lastActive updated < 30s ago?
283
- (Rate limiting to prevent DB noise)
284
-
285
- YES (recently updated) → Skip ⏭️
286
- NO (old timestamp) → Update session:
287
- {
288
- lastActive: now
289
- }
290
-
291
- Request complete
292
- ```
51
+ ---
293
52
 
294
- ### Periodic Cleanup
53
+ ### Content Manager Integration
295
54
 
296
- Runs automatically every 30 minutes:
55
+ ![Session Info Panel](pics/sessioninfopanel.png)
297
56
 
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
- ```
57
+ **When viewing a user:**
58
+ - Sidebar shows their active sessions
59
+ - Quick actions (terminate, block)
60
+ - Offline/Online status indicator
61
+ - No need to leave the page!
310
62
 
311
63
  ---
312
64
 
313
- ## 🔌 Strapi Integration
65
+ ### Settings Page
314
66
 
315
- ### Routes Integration
67
+ ![Settings 1](pics/settings1.png)
316
68
 
317
- #### Native Strapi Routes (Intercepted)
69
+ **Easy configuration:**
70
+ - Session timeouts
71
+ - Rate limiting
72
+ - Email alerts
73
+ - Webhook notifications
74
+ - Geo-blocking rules
318
75
 
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) |
76
+ ![Settings 2](pics/settings2.png)
323
77
 
324
- #### Overridden Routes
325
-
326
- | Route | Method | Magic Session Manager Action |
327
- |-------|--------|------------------------------|
328
- | `/api/auth/logout` | `POST` | **Replaced** - Custom handler terminates session by JWT token |
329
-
330
- #### Plugin Routes
78
+ **Advanced security:**
79
+ - Encryption key generator (one click!)
80
+ - Country allow/block lists
81
+ - VPN detection
82
+ - Threat blocking
331
83
 
332
- | 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 |
84
+ ---
338
85
 
339
- ### JWT Token Handling
86
+ ## What This Plugin Does
340
87
 
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)
88
+ ### Simple Version
346
89
 
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
90
+ **When users login:**
91
+ - Plugin saves who logged in, when, and from where
92
+ - You can see them in the dashboard (see screenshot above)
93
+ - You can force-logout anyone anytime
351
94
 
352
- #### Refresh Tokens ✅ **SOLVED!**
95
+ **When users logout:**
96
+ - Plugin marks their session as "logged out"
97
+ - They disappear from the active sessions list
353
98
 
354
- **What are Refresh Tokens?**
355
- Refresh tokens allow users to get new Access Tokens (JWTs) without re-entering credentials. This enables longer sessions:
99
+ **While users are active:**
100
+ - Plugin updates their "last seen" time
101
+ - You always know who's currently using your app
356
102
 
357
- ```
358
- Access Token expires after 30 min
359
-
360
- User still has Refresh Token
361
-
362
- User requests new Access Token:
363
- POST /api/auth/refresh
364
-
365
- Strapi issues new JWT
366
-
367
- User continues without re-login
368
- ```
103
+ ---
369
104
 
370
- **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 ✅
105
+ ## 🚀 Quick Install
374
106
 
375
- **How It Works:**
107
+ ### Step 1: Install
376
108
 
109
+ ```bash
110
+ npm install strapi-plugin-magic-sessionmanager
377
111
  ```
378
- Login: User gets JWT + Refresh Token
379
-
380
- Both tokens encrypted and stored in session
381
-
382
- Admin terminates session
383
-
384
- Session: isActive = false ❌
385
-
386
- User tries to refresh token:
387
- POST /api/auth/refresh
388
- { refreshToken: "..." }
389
-
390
- [Refresh Token Middleware]
391
-
392
- Decrypt all active session refresh tokens
393
-
394
- Find matching session
395
-
396
- Session found but isActive = false?
397
- → BLOCK! Return 401 Unauthorized ❌
398
- → Message: "Session terminated. Please login again."
399
-
400
- Session found and isActive = true?
401
- → ALLOW! ✅
402
- → Strapi issues new tokens
403
- → Session updated with new encrypted tokens
404
- ```
405
-
406
- **Security Benefits:**
407
112
 
408
- **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
113
+ ### Step 2: Enable Plugin
412
114
 
413
- **Configuration:**
414
-
415
- Enable refresh tokens in Strapi:
115
+ Add this to `config/plugins.ts`:
416
116
 
417
117
  ```typescript
418
- // src/config/plugins.ts
419
118
  export default () => ({
420
- 'users-permissions': {
421
- config: {
422
- jwtManagement: 'refresh', // Enable refresh tokens
423
- sessions: {
424
- accessTokenLifespan: 3600, // 1 hour (in seconds)
425
- maxRefreshTokenLifespan: 2592000, // 30 days
426
- idleRefreshTokenLifespan: 604800, // 7 days idle
427
- },
428
- },
429
- },
430
119
  'magic-sessionmanager': {
431
120
  enabled: true,
432
- config: {
433
- inactivityTimeout: 15 * 60 * 1000, // 15 minutes
434
- },
435
121
  },
436
122
  });
437
123
  ```
438
124
 
439
- **Testing Refresh Token Blocking:**
125
+ ### Step 3: Rebuild & Start
440
126
 
441
127
  ```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."
128
+ npm run build
129
+ npm run develop
461
130
  ```
462
131
 
463
- **This completely solves the refresh token security gap!** 🔒
464
-
465
- ### Without Refresh Tokens (Default Behavior)
132
+ ### Step 4: Open Dashboard
466
133
 
467
- If you **don't enable** refresh tokens (`jwtManagement: 'refresh'`):
134
+ 1. Go to Strapi Admin: `http://localhost:1337/admin`
135
+ 2. Look in the left sidebar for **"Sessions"**
136
+ 3. Click it!
137
+ 4. You'll see the dashboard (like the screenshot above)
468
138
 
469
- ```
470
- Login: User gets JWT (no refresh token)
471
-
472
- JWT stored in session (encrypted)
473
-
474
- JWT expires after 30 min (or configured time)
475
-
476
- User must re-login ❌
477
-
478
- No automatic token refresh
479
- ```
480
-
481
- **Behavior:**
482
- - ✅ Session Manager works normally
483
- - ✅ Sessions tracked, logout works
484
- - ✅ Force logout works (no refresh token bypass possible)
485
- - ⚠️ Users must re-login when JWT expires
486
- - ℹ️ No refresh token middleware runs (skipped)
487
-
488
- **Logs when refresh tokens disabled:**
489
- ```
490
- [magic-sessionmanager] ✅ Session created for user 1 (IP: 192.168.1.1)
491
- [magic-sessionmanager] ℹ️ No refresh token in response (JWT management not enabled)
492
- [magic-sessionmanager] ✅ Refresh Token interceptor middleware mounted
493
- ```
139
+ **That's it! You're done!** 🎉
494
140
 
495
- **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
141
+ ---
499
142
 
500
- **Trade-offs:**
143
+ ## 🔐 Security Features (Optional)
501
144
 
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 |
145
+ ### Encryption Key (Recommended)
508
146
 
509
- **Recommendation:**
147
+ Your JWT tokens are encrypted before saving to database. Generate a key:
510
148
 
511
- **Enable refresh tokens** for better UX + use this plugin to secure them! 🔒
149
+ **In Admin Panel:**
150
+ 1. Go to **Sessions → Settings**
151
+ 2. Scroll to **"JWT Encryption Key Generator"**
152
+ 3. Click **"Generate Key"**
153
+ 4. Click **"Copy for .env"**
154
+ 5. Paste into your `.env` file
155
+ 6. Restart Strapi
512
156
 
513
- **Testing in Postman:**
157
+ **Or generate manually:**
158
+ ```bash
159
+ node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
160
+ ```
514
161
 
162
+ Then add to `.env`:
515
163
  ```
516
- 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."
164
+ SESSION_ENCRYPTION_KEY=your-key-here
533
165
  ```
534
166
 
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
545
-
546
- # Run test suite
547
- node test-session-manager.js
167
+ **Why?** If someone hacks your database, they can't steal user sessions! 🔒
548
168
 
549
- # Look for "USER TEST 5: Blocked Refresh Token Test"
550
- # Should show: ✅ Refresh token BLOCKED as expected!
551
-
552
- # Note: Tests include delays to avoid rate limiting
553
- # Total runtime: ~45-60 seconds (includes 8s pause before refresh token test)
554
- ```
169
+ ---
555
170
 
556
- **Troubleshooting Tests:**
171
+ ## 🎯 Main Features Explained Simply
557
172
 
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
173
+ ### 1. See Who's Logged In
564
174
 
565
- ### Multi-Login Behavior
175
+ **Dashboard Tab:**
176
+ - Shows all active users
177
+ - Green badge = currently online
178
+ - Gray badge = logged out
179
+ - Click to see details
566
180
 
567
- **Strapi Default:** Allows multiple simultaneous logins
568
- **Magic Session Manager:** Tracks each login as separate session
181
+ ### 2. Force Logout Anyone
569
182
 
570
- ```
571
- User logs in from:
572
- - Desktop (Chrome) → Session 1
573
- - Mobile (Safari) Session 2
574
- - Laptop (Firefox) → Session 3
183
+ **Need to kick someone out?**
184
+ 1. Find their session
185
+ 2. Click **"Terminate"**
186
+ 3. Done! They're logged out immediately
575
187
 
576
- All sessions are active simultaneously.
577
- User can logout from one device without affecting others.
578
- ```
188
+ **Even works if they have refresh tokens!** (See below)
579
189
 
580
- ### Magic Link Integration
190
+ ### 3. Session Details
581
191
 
582
- If you use `strapi-plugin-magic-link`, the session manager automatically detects Magic Link logins:
192
+ **Click any session to see:**
193
+ - When they logged in
194
+ - Last time they did something
195
+ - What browser/device they use
196
+ - Their IP address
197
+ - Location (if Premium)
583
198
 
584
- ```javascript
585
- // bootstrap.js line 140
586
- const isMagicLink = ctx.path.includes('/magic-link/login') && ctx.method === 'POST';
587
- ```
199
+ ### 4. Multiple Devices
588
200
 
589
- Sessions are created the same way for Magic Link logins.
201
+ **Users can login from:**
202
+ - Desktop computer
203
+ - Phone
204
+ - Tablet
205
+ - All at the same time!
590
206
 
591
- ---
207
+ Each login = separate session. You can see them all and logout each individually.
592
208
 
593
- ## 🎛️ 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
209
+ ### 5. Auto-Cleanup
642
210
 
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)
211
+ **Inactive sessions are automatically cleaned up:**
212
+ - If user doesn't do anything for 15 minutes (configurable)
213
+ - Session is marked as "inactive"
214
+ - Keeps your database clean
649
215
 
650
216
  ---
651
217
 
652
- ## 📡 API Routes
218
+ ## 🔒 Refresh Token Protection (Advanced)
653
219
 
654
- ### Content API Routes
220
+ ### The Problem (Without This Plugin)
655
221
 
656
- All require valid JWT authentication (Bearer token).
657
-
658
- #### Get User Sessions
659
-
660
- ```bash
661
- GET /api/magic-sessionmanager/sessions
662
- Authorization: Bearer YOUR_JWT
663
-
664
- Response:
665
- {
666
- "data": [
667
- {
668
- "id": 1,
669
- "attributes": {
670
- "loginTime": "2024-01-15T10:30:00Z",
671
- "lastActive": "2024-01-15T10:35:45Z",
672
- "logoutTime": null,
673
- "isActive": true,
674
- "ipAddress": "192.168.1.100",
675
- "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
676
- "token": "eyJhbGciOiJIUzI1NiIs...", // JWT Access Token
677
- "geoLocation": { // Premium
678
- "country": "Germany",
679
- "city": "Berlin",
680
- "country_code": "DE",
681
- "latitude": 52.52,
682
- "longitude": 13.41
683
- },
684
- "securityScore": 95 // Premium
685
- },
686
- "relationships": {
687
- "user": { "id": 1, "username": "john" }
688
- }
689
- }
690
- ],
691
- "meta": { "count": 3 }
692
- }
693
222
  ```
694
-
695
- #### 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
223
+ Admin kicks out a user
224
+
225
+ User has "refresh token"
226
+
227
+ User gets new login token automatically
228
+
229
+ User is back in! 😱
708
230
  ```
709
231
 
710
- #### Logout (Method 2 - Plugin Endpoint)
711
-
712
- ```bash
713
- POST /api/magic-sessionmanager/logout
714
- Authorization: Bearer YOUR_JWT
715
-
716
- Response:
717
- {
718
- "message": "Session terminated successfully"
719
- }
232
+ ### The Solution (With This Plugin)
720
233
 
721
- # Alternative endpoint with same behavior
722
234
  ```
723
-
724
- #### 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
235
+ Admin kicks out a user
236
+
237
+ User tries to use refresh token
238
+
239
+ Plugin blocks it! 🚫
240
+
241
+ User MUST login again
738
242
  ```
739
243
 
740
- ---
741
-
742
- ### Admin API Routes
743
-
744
- All require **admin authentication**.
745
-
746
- | Method | Route | Purpose |
747
- |--------|-------|---------|
748
- | `GET` | `/magic-sessionmanager/admin/sessions` | Get all sessions (all users) |
749
- | `GET` | `/magic-sessionmanager/admin/sessions/active` | Get only active sessions |
750
- | `GET` | `/magic-sessionmanager/admin/user/:userId/sessions` | Get sessions for a user |
751
- | `POST` | `/magic-sessionmanager/admin/sessions/:sessionId/terminate` | Mark session inactive |
752
- | `DELETE` | `/magic-sessionmanager/admin/sessions/:sessionId` | Permanently delete session |
753
- | `POST` | `/magic-sessionmanager/admin/sessions/clean-inactive` | Delete all inactive sessions |
754
- | `POST` | `/magic-sessionmanager/admin/user/:userId/terminate-all` | Logout user everywhere |
755
- | `GET` | `/magic-sessionmanager/admin/geolocation/:ipAddress` | Get IP info (Premium) |
756
- | `GET` | `/magic-sessionmanager/admin/settings` | Get plugin settings |
757
- | `PUT` | `/magic-sessionmanager/admin/settings` | Update plugin settings |
758
- | `GET` | `/magic-sessionmanager/admin/license/status` | Get license status |
759
- | `POST` | `/magic-sessionmanager/admin/license/activate` | Activate license |
760
-
761
- ---
762
-
763
- ## ⚙️ Configuration
244
+ **How to enable:**
764
245
 
765
- ### Basic Config
246
+ Add to `config/plugins.ts`:
766
247
 
767
248
  ```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
- ```
787
-
788
- ### Relationship with JWT Config
789
-
790
- ```typescript
791
- // src/config/plugins.ts
792
- export default () => ({
793
- // Strapi JWT Configuration
794
- 'users-permissions': {
795
- config: {
796
- jwt: {
797
- expiresIn: '30m', // Access Token expires after 30 minutes
798
- },
249
+ 'users-permissions': {
250
+ config: {
251
+ jwtManagement: 'refresh', // Enable refresh tokens
252
+ sessions: {
253
+ accessTokenLifespan: 3600, // 1 hour
254
+ maxRefreshTokenLifespan: 2592000, // 30 days
799
255
  },
800
256
  },
801
-
802
- // Session Manager Configuration
803
- 'magic-sessionmanager': {
804
- enabled: true,
805
- config: {
806
- // Set inactivity timeout LOWER than JWT expiration
807
- // This prevents orphaned sessions when JWT expires
808
- inactivityTimeout: 15 * 60 * 1000, // 15 minutes < 30 minutes JWT
809
-
810
- // Or match JWT expiration exactly:
811
- // inactivityTimeout: 30 * 60 * 1000, // 30 minutes = JWT expiration
812
- },
813
- },
814
- });
815
- ```
816
-
817
- ### Premium Config
818
-
819
- Available through Admin UI **Settings → Sessions → Settings**:
820
-
821
- ```typescript
822
- // Settings stored in database via Admin UI
823
- {
824
- // Geolocation & Security
825
- enableGeolocation: true,
826
- enableSecurityScoring: true,
827
- blockSuspiciousSessions: true,
828
- alertOnVpnProxy: true,
829
-
830
- // Geo-Fencing
831
- enableGeofencing: true,
832
- allowedCountries: ["DE", "AT", "CH"], // Germany, Austria, Switzerland
833
- blockedCountries: ["RU", "CN"], // Russia, China
834
-
835
- // Notifications
836
- enableEmailAlerts: true,
837
- alertOnSuspiciousLogin: true,
838
- enableWebhooks: true,
839
- discordWebhookUrl: "https://discord.com/api/webhooks/...",
840
- slackWebhookUrl: "https://hooks.slack.com/services/...",
841
257
  }
842
258
  ```
843
259
 
844
- ---
845
-
846
- ## 🔐 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?
853
-
854
- ```
855
- ❌ Without Encryption:
856
- Database compromised → Attacker sees JWTs → Can impersonate users!
857
-
858
- ✅ With Encryption:
859
- Database compromised → Attacker sees encrypted data → Useless without key!
860
- ```
861
-
862
- #### How It Works
863
-
864
- ```
865
- Login: User gets JWT
866
-
867
- JWT: "eyJhbGciOiJIUzI1NiIs..."
868
-
869
- [Encrypt with AES-256-GCM]
870
-
871
- Encrypted: "a3f7b2c1:8c4d9e2a:f2a5b8c3d4e5f6a7..."
872
-
873
- Stored in Database (secure!)
874
-
875
- Logout: User sends JWT
876
-
877
- [Fetch all active sessions from DB]
878
-
879
- [Decrypt each token]
880
-
881
- [Compare with user's JWT]
882
-
883
- Match found → Terminate session ✅
884
- ```
885
-
886
- #### Configuration
887
-
888
- **Generate Encryption Key (Admin Panel):**
889
-
890
- 1. Go to **Admin → Sessions → Settings**
891
- 2. Open **Security Settings** accordion
892
- 3. Find **JWT Encryption Key Generator**
893
- 4. Click **"Generate Key"**
894
- 5. Copy key with **"Copy for .env"** button
895
- 6. Add to your `.env` file
896
-
897
- **Or generate manually:**
898
-
899
- ```bash
900
- # Generate secure 32-byte key
901
- node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
260
+ **What this does:**
261
+ - Users stay logged in longer (better experience)
262
+ - But admins can still force-logout completely (better security)
263
+ - Best of both worlds! ✅
902
264
 
903
- # Add to .env
904
- SESSION_ENCRYPTION_KEY=aBc123XyZ...your-32-char-key
905
- ```
265
+ ---
906
266
 
907
- **Fallback Behavior:**
267
+ ## 🌍 Premium Features (Optional License)
908
268
 
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
269
+ ### IP Geolocation
913
270
 
914
- **Production Recommendation:**
915
- Always use a dedicated `SESSION_ENCRYPTION_KEY` for better security isolation.
271
+ **See where users login from:**
272
+ - Country (with flag! 🇩🇪🇺🇸🇬🇧)
273
+ - City
274
+ - ISP Provider
275
+ - Coordinates (for map)
916
276
 
917
- #### Security Details
277
+ ### Threat Detection
918
278
 
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) |
279
+ **Automatically check if IP is:**
280
+ - VPN
281
+ - Proxy
282
+ - Known threat
283
+ - Security score (0-100)
926
284
 
927
- ### Unique Session IDs
285
+ ### Auto-Blocking
928
286
 
929
- Each session gets a cryptographically unique identifier:
287
+ **Block logins from:**
288
+ - Specific countries
289
+ - VPNs or proxies
290
+ - Low security score IPs
291
+ - Known threat IPs
930
292
 
931
- ```javascript
932
- sessionId: "sess_lx3k7_4f2a8b3c_a1b2c3d4e5f6"
933
- // prefix^ ^timestamp ^user-hash ^random-bytes
934
- ```
293
+ ### Notifications
935
294
 
936
- **Benefits:**
937
- - No collisions across sessions
938
- - Traceable session identifiers
939
- - Independent from database IDs
940
- - URL-safe for future features
295
+ **Get alerts when:**
296
+ - Suspicious login detected
297
+ - VPN used
298
+ - New location login
299
+ - Send to Discord or Slack!
941
300
 
942
301
  ---
943
302
 
944
- ## 🔒 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:
303
+ ## 📋 Simple API Guide
990
304
 
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
305
+ ### Get Sessions
996
306
 
997
- If this wasn't you, secure your account immediately.
998
-
999
- Magic Session Manager
307
+ ```bash
308
+ # Get all active sessions
309
+ GET /magic-sessionmanager/sessions
1000
310
  ```
1001
311
 
1002
- ### Webhook Notifications
312
+ ### Logout
1003
313
 
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
314
+ ```bash
315
+ # Logout current user
316
+ POST /api/auth/logout
1014
317
  ```
1015
318
 
1016
- ---
1017
-
1018
- ## 💡 Use Cases
1019
-
1020
319
  ### Force Logout
1021
320
 
1022
321
  ```bash
1023
- # Admin 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
322
+ # Admin force-logout a session
323
+ POST /magic-sessionmanager/sessions/:sessionId/terminate
1053
324
  ```
1054
325
 
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
- ```
326
+ **That's all you need to know!**
1067
327
 
1068
328
  ---
1069
329
 
1070
- ## 🧪 Testing
330
+ ## ⚙️ Settings You Can Change
1071
331
 
1072
- ### 1. Test Login & Session Creation
332
+ **In `config/plugins.ts`:**
1073
333
 
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", ... }
334
+ ```typescript
335
+ 'magic-sessionmanager': {
336
+ config: {
337
+ // How often to update "last seen" (in milliseconds)
338
+ lastSeenRateLimit: 30000, // Default: 30 seconds
339
+
340
+ // When to mark sessions inactive (in milliseconds)
341
+ inactivityTimeout: 900000, // Default: 15 minutes
342
+ },
1087
343
  }
1088
-
1089
- # Save JWT
1090
- export JWT="eyJhbGciOiJIUzI1NiIs..."
1091
-
1092
- # Check session was created
1093
- curl http://localhost:1337/api/magic-sessionmanager/sessions \
1094
- -H "Authorization: Bearer $JWT"
1095
-
1096
- # Should show new session with:
1097
- # - loginTime
1098
- # - isActive: true
1099
- # - ipAddress
1100
- # - userAgent
1101
- # - token (matches JWT)
1102
344
  ```
1103
345
 
1104
- ### 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"
346
+ **In Admin Panel (Settings Tab):**
347
+ - Email alerts on/off
348
+ - Webhook URLs (Discord/Slack)
349
+ - Countries to block/allow
350
+ - VPN detection on/off
351
+ - Generate encryption key
1114
352
 
1115
- # 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
- ```
353
+ ---
1126
354
 
1127
- ### 3. Test Logout
355
+ ## 🐛 Common Problems & Fixes
1128
356
 
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"
357
+ ### I don't see the Sessions menu
1133
358
 
1134
- # Response: { "message": "Logged out successfully" }
359
+ **Fix:**
360
+ 1. Make sure plugin is in `config/plugins.ts`
361
+ 2. Run `npm run build`
362
+ 3. Restart Strapi
363
+ 4. Refresh browser (Cmd+Shift+R)
1135
364
 
1136
- # Check session is inactive
1137
- curl http://localhost:1337/api/magic-sessionmanager/sessions \
1138
- -H "Authorization: Bearer $JWT"
365
+ ### Sessions not being created
1139
366
 
1140
- # Should show:
1141
- # - isActive: false
1142
- # - logoutTime: (timestamp)
1143
- ```
367
+ **Fix:**
368
+ 1. Check Strapi logs for errors
369
+ 2. Make sure users are logging in (not already logged in)
370
+ 3. Check database is working
1144
371
 
1145
- ### 4. Test Force Logout
372
+ ### 401 or 403 errors
1146
373
 
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"
374
+ **Fix:**
375
+ - 401 = Not logged in (need to login as admin)
376
+ - 403 = Not allowed (check you're admin, not regular user)
1151
377
 
1152
- # Try to use API with old JWT
1153
- curl http://localhost:1337/api/users \
1154
- -H "Authorization: Bearer $JWT_A"
378
+ ### Database table "sessions" already exists
1155
379
 
1156
- # Response: 401 Unauthorized
1157
- # "All sessions have been terminated. Please login again."
1158
- ```
380
+ **Fix:**
381
+ - This plugin uses `magic_sessions` table (not `sessions`)
382
+ - If you see this error, another plugin is using that name
383
+ - Our plugin automatically uses the correct name
1159
384
 
1160
385
  ---
1161
386
 
1162
- ## 🐛 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
- ```
387
+ ## 💡 When To Use This Plugin
1175
388
 
1176
- 2. Verify middleware is mounted:
1177
- ```bash
1178
- # Look for: [magic-sessionmanager] Login/Logout interceptor middleware mounted
1179
- ```
389
+ **Perfect for:**
390
+ - Multi-tenant apps (see which tenant users are online)
391
+ - E-commerce (track customer sessions)
392
+ - Collaboration tools (show who's currently working)
393
+ - Security-critical apps (force-logout compromised accounts)
394
+ - Compliance requirements (session audit logs)
1180
395
 
1181
- 3. Check `plugin::magic-sessionmanager.session` collection exists:
1182
- - Go to Admin → Content Manager
1183
- - Look for "Session" collection
396
+ **Not needed if:**
397
+ - Single-user app
398
+ - No need to see who's logged in
399
+ - No security requirements
1184
400
 
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
401
+ ---
1194
402
 
1195
- **Solution:** This is by design. The middleware blocks requests from users with no active sessions.
403
+ ## 🔧 How To Test It
1196
404
 
1197
- ### Orphaned Sessions
405
+ ### Quick Manual Test
1198
406
 
1199
- **Problem:** Sessions remain `isActive = true` after JWT expires.
407
+ 1. **Login to your Strapi app** (frontend or admin)
408
+ 2. **Go to Admin → Sessions**
409
+ 3. **You should see your session!**
410
+ 4. **Click "Terminate" on your session**
411
+ 5. **Try to use the app → You're logged out!**
1200
412
 
1201
- **Cause:** JWT expiration > inactivity timeout
413
+ ### With Postman
1202
414
 
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
- }
415
+ **1. Login:**
416
+ ```
417
+ POST http://localhost:1337/api/auth/local
418
+ Body: { "identifier": "user@test.com", "password": "pass123" }
1213
419
  ```
1214
420
 
1215
- ### 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
- ```
421
+ **2. Check session created:**
422
+ ```
423
+ GET http://localhost:1337/magic-sessionmanager/sessions
424
+ ```
1226
425
 
1227
- 2. Wait longer than rate limit (default 30s)
426
+ **3. Logout:**
427
+ ```
428
+ POST http://localhost:1337/api/auth/logout
429
+ Authorization: Bearer YOUR_JWT_TOKEN
430
+ ```
1228
431
 
1229
- 3. Verify middleware mounted:
1230
- ```bash
1231
- # Look for: [magic-sessionmanager] ✅ LastSeen middleware mounted
1232
- ```
432
+ **Done!**
1233
433
 
1234
434
  ---
1235
435
 
1236
- ## 🛠️ Development
436
+ ## 📦 What Gets Installed
1237
437
 
1238
- ### Plugin Structure
438
+ When you install this plugin, you get:
1239
439
 
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
- ```
440
+ - ✅ Dashboard to see all sessions
441
+ - ✅ Session tracking (automatic)
442
+ - ✅ Force logout buttons
443
+ - Activity monitoring
444
+ - ✅ Encryption (secure)
445
+ - Multi-device support
1280
446
 
1281
- ### Build & Release
447
+ **Premium features require a license (free to generate):**
448
+ - 🔒 IP Geolocation
449
+ - 🔒 Threat detection
450
+ - 🔒 Auto-blocking
451
+ - 🔒 Email/webhook alerts
1282
452
 
1283
- ```bash
1284
- # Build
1285
- npm run build
453
+ ---
1286
454
 
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
- ```
455
+ ## 🙋 FAQ
1292
456
 
1293
- ---
457
+ **Q: Do I need to change my Strapi code?**
458
+ A: No! Just install and enable the plugin.
1294
459
 
1295
- ## 📦 NPM Release Process
460
+ **Q: Will this break my existing logins?**
461
+ A: No! It just tracks them, doesn't change them.
1296
462
 
1297
- Uses **semantic-release** for automated versioning.
463
+ **Q: Can users see each other's sessions?**
464
+ A: No! Only admins can see all sessions. Users only see their own.
1298
465
 
1299
- ### Commit Format
466
+ **Q: What if I uninstall the plugin?**
467
+ A: Sessions will stop being tracked. Everything else works normally.
1300
468
 
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
- ```
469
+ **Q: Does it slow down my app?**
470
+ A: No! It has smart rate-limiting to prevent database spam.
1306
471
 
1307
- GitHub Actions automatically publishes to NPM on push to `main`.
472
+ **Q: Can I customize the dashboard?**
473
+ A: Not yet, but it's planned for future versions!
1308
474
 
1309
475
  ---
1310
476
 
@@ -1312,16 +478,16 @@ GitHub Actions automatically publishes to NPM on push to `main`.
1312
478
 
1313
479
  - **NPM:** https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager
1314
480
  - **GitHub:** https://github.com/Schero94/Magic-Sessionmanager
1315
- - **Issues:** https://github.com/Schero94/Magic-Sessionmanager/issues
481
+ - **Report Bugs:** https://github.com/Schero94/Magic-Sessionmanager/issues
1316
482
 
1317
483
  ---
1318
484
 
1319
485
  ## 📄 License
1320
486
 
1321
- **MIT License** - Free for personal & commercial use
487
+ **MIT License** - Free to use!
1322
488
 
1323
- **Copyright (c) 2025 Schero D.**
489
+ **Copyright © 2025 Schero D.**
1324
490
 
1325
491
  ---
1326
492
 
1327
- **Built with ❤️ for Strapi v5**
493
+ **Made with ❤️ for Strapi v5**