strapi-plugin-magic-sessionmanager 3.3.0 → 3.3.2
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 +104 -4
- package/dist/server/index.js +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +1 -1
- package/server/src/bootstrap.js +2 -2
package/README.md
CHANGED
|
@@ -360,7 +360,7 @@ Access Token expires after 30 min
|
|
|
360
360
|
User still has Refresh Token
|
|
361
361
|
↓
|
|
362
362
|
User requests new Access Token:
|
|
363
|
-
POST /api/auth/refresh
|
|
363
|
+
POST /api/auth/refresh
|
|
364
364
|
↓
|
|
365
365
|
Strapi issues new JWT
|
|
366
366
|
↓
|
|
@@ -369,7 +369,7 @@ User continues without re-login
|
|
|
369
369
|
|
|
370
370
|
**The Solution (v3.2+):**
|
|
371
371
|
- **Stored:** YES - Refresh tokens are encrypted and stored with sessions ✅
|
|
372
|
-
- **Tracked:** YES - Middleware intercepts `/api/auth/refresh
|
|
372
|
+
- **Tracked:** YES - Middleware intercepts `/api/auth/refresh` requests ✅
|
|
373
373
|
- **Validated:** YES - Checks if session is still active before issuing new tokens ✅
|
|
374
374
|
|
|
375
375
|
**How It Works:**
|
|
@@ -384,7 +384,7 @@ Admin terminates session
|
|
|
384
384
|
Session: isActive = false ❌
|
|
385
385
|
↓
|
|
386
386
|
User tries to refresh token:
|
|
387
|
-
POST /api/auth/refresh
|
|
387
|
+
POST /api/auth/refresh
|
|
388
388
|
{ refreshToken: "..." }
|
|
389
389
|
↓
|
|
390
390
|
[Refresh Token Middleware]
|
|
@@ -452,7 +452,7 @@ REFRESH_TOKEN="abc123..."
|
|
|
452
452
|
# Go to Admin → Sessions → Find session → Terminate
|
|
453
453
|
|
|
454
454
|
# 3. Try to refresh token
|
|
455
|
-
curl -X POST http://localhost:1337/api/auth/refresh
|
|
455
|
+
curl -X POST http://localhost:1337/api/auth/refresh \
|
|
456
456
|
-H "Content-Type: application/json" \
|
|
457
457
|
-d "{\"refreshToken\":\"$REFRESH_TOKEN\"}"
|
|
458
458
|
|
|
@@ -462,6 +462,106 @@ curl -X POST http://localhost:1337/api/auth/refresh-token \
|
|
|
462
462
|
|
|
463
463
|
**This completely solves the refresh token security gap!** 🔒
|
|
464
464
|
|
|
465
|
+
### Without Refresh Tokens (Default Behavior)
|
|
466
|
+
|
|
467
|
+
If you **don't enable** refresh tokens (`jwtManagement: 'refresh'`):
|
|
468
|
+
|
|
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
|
|
499
|
+
|
|
500
|
+
**Trade-offs:**
|
|
501
|
+
|
|
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 |
|
|
508
|
+
|
|
509
|
+
**Recommendation:**
|
|
510
|
+
|
|
511
|
+
**Enable refresh tokens** for better UX + use this plugin to secure them! 🔒
|
|
512
|
+
|
|
513
|
+
**Testing in Postman:**
|
|
514
|
+
|
|
515
|
+
```
|
|
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."
|
|
533
|
+
```
|
|
534
|
+
|
|
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
|
|
548
|
+
|
|
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
|
+
```
|
|
555
|
+
|
|
556
|
+
**Troubleshooting Tests:**
|
|
557
|
+
|
|
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
|
|
564
|
+
|
|
465
565
|
### Multi-Login Behavior
|
|
466
566
|
|
|
467
567
|
**Strapi Default:** Allows multiple simultaneous logins
|
package/dist/server/index.js
CHANGED
|
@@ -399,7 +399,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
|
|
|
399
399
|
});
|
|
400
400
|
strapi2.log.info("[magic-sessionmanager] ✅ Login/Logout interceptor middleware mounted");
|
|
401
401
|
strapi2.server.use(async (ctx, next) => {
|
|
402
|
-
const isRefreshToken = ctx.path === "/api/auth/refresh
|
|
402
|
+
const isRefreshToken = ctx.path === "/api/auth/refresh" && ctx.method === "POST";
|
|
403
403
|
if (isRefreshToken) {
|
|
404
404
|
try {
|
|
405
405
|
const refreshToken = ctx.request.body?.refreshToken;
|
package/dist/server/index.mjs
CHANGED
|
@@ -395,7 +395,7 @@ var bootstrap$1 = async ({ strapi: strapi2 }) => {
|
|
|
395
395
|
});
|
|
396
396
|
strapi2.log.info("[magic-sessionmanager] ✅ Login/Logout interceptor middleware mounted");
|
|
397
397
|
strapi2.server.use(async (ctx, next) => {
|
|
398
|
-
const isRefreshToken = ctx.path === "/api/auth/refresh
|
|
398
|
+
const isRefreshToken = ctx.path === "/api/auth/refresh" && ctx.method === "POST";
|
|
399
399
|
if (isRefreshToken) {
|
|
400
400
|
try {
|
|
401
401
|
const refreshToken = ctx.request.body?.refreshToken;
|
package/package.json
CHANGED
package/server/src/bootstrap.js
CHANGED
|
@@ -296,8 +296,8 @@ module.exports = async ({ strapi }) => {
|
|
|
296
296
|
|
|
297
297
|
// Middleware to block refresh token requests for terminated sessions
|
|
298
298
|
strapi.server.use(async (ctx, next) => {
|
|
299
|
-
// Check if this is a refresh token request
|
|
300
|
-
const isRefreshToken = ctx.path === '/api/auth/refresh
|
|
299
|
+
// Check if this is a refresh token request (Strapi v5: /api/auth/refresh)
|
|
300
|
+
const isRefreshToken = ctx.path === '/api/auth/refresh' && ctx.method === 'POST';
|
|
301
301
|
|
|
302
302
|
if (isRefreshToken) {
|
|
303
303
|
try {
|