See who's logged into your Strapi app - and control their sessions!
Track logins, monitor active users, and secure your app with one simple plugin. No complicated setup required.
On your Strapi homepage:
- See online users instantly
- Active in last 15/30 minutes
- Total users count
- Blocked users count
- No need to navigate anywhere!
What you see:
- Who is logged in right now (green = online)
- When they logged in
- What device they're using
- Their IP address and location
- One-click session termination
Click any session to see:
- Full device information
- Browser and operating system
- Complete session history
- IP geolocation (Premium)
- Security risk score (Premium)
When viewing a user:
- Sidebar shows their active sessions
- Quick actions (terminate, block)
- Offline/Online status indicator
- No need to leave the page!
Easy configuration:
- Session timeouts
- Rate limiting
- Email alerts
- Webhook notifications
- Geo-blocking rules
Advanced security:
- Encryption key generator (one click!)
- Country allow/block lists
- VPN detection
- Threat blocking
When users login:
- Plugin saves who logged in, when, and from where
- You can see them in the dashboard (see screenshot above)
- You can force-logout anyone anytime
When users logout:
- Plugin marks their session as "logged out"
- They disappear from the active sessions list
While users are active:
- Plugin updates their "last seen" time
- You always know who's currently using your app
npm install strapi-plugin-magic-sessionmanagerAdd this to config/plugins.ts:
export default () => ({
'magic-sessionmanager': {
enabled: true,
},
});npm run build
npm run develop- Go to Strapi Admin:
http://localhost:1337/admin - Look in the left sidebar for "Sessions"
- Click it!
- You'll see the dashboard (like the screenshot above)
That's it! You're done!
Your JWT tokens are encrypted before saving to database. Generate a key:
In Admin Panel:
- Go to Sessions β Settings
- Scroll to "JWT Encryption Key Generator"
- Click "Generate Key"
- Click "Copy for .env"
- Paste into your
.envfile - Restart Strapi
Or generate manually:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"Then add to .env:
SESSION_ENCRYPTION_KEY=your-key-here
Why? If someone hacks your database, they can't steal user sessions! π
Dashboard Tab:
- Shows all active users
- Green badge = currently online
- Gray badge = logged out
- Click to see details
Need to kick someone out?
- Find their session
- Click "Terminate"
- Done! They're logged out immediately
Even works if they have refresh tokens! (See below)
Click any session to see:
- When they logged in
- Last time they did something
- What browser/device they use
- Their IP address
- Location (if Premium)
Users can login from:
- Desktop computer
- Phone
- Tablet
- All at the same time!
Each login = separate session. You can see them all and logout each individually.
Inactive sessions are automatically cleaned up:
- If user doesn't do anything for 15 minutes (configurable)
- Session is marked as "inactive"
- Keeps your database clean
Admin kicks out a user
β
User has "refresh token"
β
User gets new login token automatically
β
User is back in! π±
Admin kicks out a user
β
User tries to use refresh token
β
Plugin blocks it! π«
β
User MUST login again
How to enable:
Add to config/plugins.ts:
'users-permissions': {
config: {
jwtManagement: 'refresh', // Enable refresh tokens
sessions: {
accessTokenLifespan: 3600, // 1 hour
maxRefreshTokenLifespan: 2592000, // 30 days
},
},
}What this does:
- Users stay logged in longer (better experience)
- But admins can still force-logout completely (better security)
- Best of both worlds! β
See where users login from:
- Country (with flag! π©πͺπΊπΈπ¬π§)
- City
- ISP Provider
- Coordinates (for map)
Automatically check if IP is:
- VPN
- Proxy
- Known threat
- Security score (0-100)
Block logins from:
- Specific countries
- VPNs or proxies
- Low security score IPs
- Known threat IPs
Get alerts when:
- Suspicious login detected
- VPN used
- New location login
- Send to Discord or Slack!
The Session Manager uses Strapi's Email Plugin to send notifications. You need to configure an email provider first.
Choose one of these providers:
Option A: Nodemailer (Recommended)
npm install @strapi/provider-email-nodemailerOption B: SendGrid
npm install @strapi/provider-email-sendgridOption C: Mailgun
npm install @strapi/provider-email-mailgunAdd to config/plugins.ts:
export default () => ({
// Email configuration
email: {
config: {
provider: 'nodemailer',
providerOptions: {
host: process.env.SMTP_HOST || 'smtp.gmail.com',
port: process.env.SMTP_PORT || 587,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
},
},
settings: {
defaultFrom: process.env.SMTP_DEFAULT_FROM || '[email protected]',
defaultReplyTo: process.env.SMTP_DEFAULT_REPLY_TO || '[email protected]',
},
},
},
// Session Manager configuration
'magic-sessionmanager': {
enabled: true,
},
});Add to your .env file:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=[email protected]
SMTP_PASSWORD=your-app-password
SMTP_DEFAULT_FROM=[email protected]
SMTP_DEFAULT_REPLY_TO=[email protected]For Gmail:
- Use an App Password, not your regular password!
- Go to Sessions β Settings
- Scroll to "Email Notifications"
- Toggle "Enable Email Alerts" to ON
- Customize email templates (optional)
- Click Save
Trigger a suspicious login (e.g., use a VPN) and check if the email arrives!
Troubleshooting:
- Check Strapi logs for email errors
- Verify SMTP credentials are correct
- Test SMTP connection with a tool like smtp-tester
All Content-API endpoints require a valid JWT token in the Authorization header.
Users can only access their own sessions.
Returns all sessions for the authenticated user.
GET /api/magic-sessionmanager/my-sessions
Authorization: Bearer <JWT>Response:
{
"data": [
{
"id": 41,
"documentId": "abc123xyz",
"sessionId": "sess_m5k2h_8a3b1c2d_f9e8d7c6",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
"loginTime": "2026-01-02T10:30:00.000Z",
"lastActive": "2026-01-02T13:45:00.000Z",
"logoutTime": null,
"isActive": true,
"deviceType": "desktop",
"browserName": "Chrome 143",
"osName": "macOS 10.15.7",
"geoLocation": null,
"securityScore": null,
"isCurrentSession": true,
"isTrulyActive": true,
"minutesSinceActive": 2
},
{
"id": 40,
"documentId": "def456uvw",
"sessionId": "sess_m5k1g_7b2a0c1d_e8d7c6b5",
"ipAddress": "10.0.0.50",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)...",
"loginTime": "2026-01-01T08:15:00.000Z",
"lastActive": "2026-01-01T12:00:00.000Z",
"logoutTime": null,
"isActive": true,
"deviceType": "mobile",
"browserName": "Safari",
"osName": "iOS 17",
"geoLocation": null,
"securityScore": null,
"isCurrentSession": false,
"isTrulyActive": false,
"minutesSinceActive": 1545
}
],
"meta": {
"count": 2,
"active": 1
}
}Returns only the session associated with the current JWT token.
GET /api/magic-sessionmanager/current-session
Authorization: Bearer <JWT>Response:
{
"data": {
"id": 41,
"documentId": "abc123xyz",
"sessionId": "sess_m5k2h_8a3b1c2d_f9e8d7c6",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...",
"loginTime": "2026-01-02T10:30:00.000Z",
"lastActive": "2026-01-02T13:45:00.000Z",
"logoutTime": null,
"isActive": true,
"deviceType": "desktop",
"browserName": "Chrome 143",
"osName": "macOS 10.15.7",
"geoLocation": null,
"securityScore": null,
"isCurrentSession": true,
"isTrulyActive": true,
"minutesSinceActive": 2
}
}Terminates only the current session.
POST /api/magic-sessionmanager/logout
Authorization: Bearer <JWT>Response:
{
"message": "Logged out successfully"
}Terminates ALL sessions for the authenticated user (logs out everywhere).
POST /api/magic-sessionmanager/logout-all
Authorization: Bearer <JWT>Response:
{
"message": "Logged out from all devices successfully"
}Terminates a specific session (not the current one). Useful for "Log out other devices".
DELETE /api/magic-sessionmanager/my-sessions/:sessionId
Authorization: Bearer <JWT>Response:
{
"message": "Session abc123xyz terminated successfully",
"success": true
}Error (trying to terminate current session):
{
"error": {
"status": 400,
"message": "Cannot terminate current session. Use /logout instead."
}
}These endpoints require admin authentication.
GET /magic-sessionmanager/sessionsGET /magic-sessionmanager/sessions/activePOST /magic-sessionmanager/sessions/:sessionId/terminatePOST /magic-sessionmanager/user/:userId/terminate-allPOST /magic-sessionmanager/user/:userId/toggle-blockPOST /magic-sessionmanager/sessions/clean-inactiveIn config/plugins.ts:
'magic-sessionmanager': {
config: {
// How often to update "last seen" (in milliseconds)
lastSeenRateLimit: 30000, // Default: 30 seconds
// When to mark sessions inactive (in milliseconds)
inactivityTimeout: 900000, // Default: 15 minutes
},
}In Admin Panel (Settings Tab):
- Email alerts on/off
- Webhook URLs (Discord/Slack)
- Countries to block/allow
- VPN detection on/off
- Generate encryption key
Fix:
- Make sure plugin is in
config/plugins.ts - Run
npm run build - Restart Strapi
- Refresh browser (Cmd+Shift+R)
Fix:
- Check Strapi logs for errors
- Make sure users are logging in (not already logged in)
- Check database is working
Fix:
- 401 = Not logged in (need to login as admin)
- 403 = Not allowed (check you're admin, not regular user)
Fix:
- This plugin uses
magic_sessionstable (notsessions) - If you see this error, another plugin is using that name
- Our plugin automatically uses the correct name
Perfect for:
- Multi-tenant apps (see which tenant users are online)
- E-commerce (track customer sessions)
- Collaboration tools (show who's currently working)
- Security-critical apps (force-logout compromised accounts)
- Compliance requirements (session audit logs)
Not needed if:
- Single-user app
- No need to see who's logged in
- No security requirements
- Login to your Strapi app (frontend or admin)
- Go to Admin β Sessions
- You should see your session!
- Click "Terminate" on your session
- Try to use the app β You're logged out!
1. Login:
POST http://localhost:1337/api/auth/local
Body: { "identifier": "[email protected]", "password": "pass123" }
2. Check session created:
GET http://localhost:1337/magic-sessionmanager/sessions
3. Logout:
POST http://localhost:1337/api/auth/logout
Authorization: Bearer YOUR_JWT_TOKEN
Done!
When you install this plugin, you get:
- β Dashboard to see all sessions
- β Session tracking (automatic)
- β Force logout buttons
- β Activity monitoring
- β Encryption (secure)
- β Multi-device support
Premium features require a license (free to generate):
- π IP Geolocation
- π Threat detection
- π Auto-blocking
- π Email/webhook alerts
Q: Do I need to change my Strapi code?
A: No! Just install and enable the plugin.
Q: Will this break my existing logins?
A: No! It just tracks them, doesn't change them.
Q: Can users see each other's sessions?
A: No! Only admins can see all sessions. Users only see their own.
Q: What if I uninstall the plugin?
A: Sessions will stop being tracked. Everything else works normally.
Q: Does it slow down my app?
A: No! It has smart rate-limiting to prevent database spam.
Q: Can I customize the dashboard?
A: Not yet, but it's planned for future versions!
- NPM: https://www.npmjs.com/package/strapi-plugin-magic-sessionmanager
- GitHub: https://github.com/Schero94/Magic-Sessionmanager
- Report Bugs: https://github.com/Schero94/Magic-Sessionmanager/issues
MIT License - Free to use for personal and commercial projects!
Copyright Β© 2025 Schero D.
This plugin is free and open source, BUT:
This means:
- β Cannot remove
license-guard.js - β Cannot bypass license activation
- β Cannot disable license checks
- β Cannot modify license-related endpoints
Why? The license system ensures:
- Quality and ongoing support
- Spam prevention
- Usage analytics for improvements
- Fair use tracking
What you CAN do:
- β Use freely (personal & commercial)
- β View and study source code
- β Report issues and contribute
- β Deploy in production without fees
- β Integrate in your projects
See LICENSE and COPYRIGHT_NOTICE.txt for full terms.
The admin interface is available in 5 languages:
- π¬π§ English - Default
- π©πͺ Deutsch - German
- πͺπΈ EspaΓ±ol - Spanish
- π«π· FranΓ§ais - French
- π΅πΉ PortuguΓͺs - Portuguese
Language automatically follows your Strapi admin interface setting.
Made for Strapi v5





