npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

strapi-security-suite

v0.3.1

Published

All-in-one authentication and session security plugin for Strapi v5

Downloads

310

Readme

🛡️ Strapi Security Suite

The admin security plugin that takes your sessions personally.

One plugin. Auto-logout. Single-session enforcement. Token revocation. Password policy. Built for Strapi v5. Fueled by in-memory Maps and zero tolerance for stale tokens.


🤔 What Is This?

Imagine a bouncer at a nightclub. But the nightclub is your Strapi admin panel, and the bouncer has a perfect memory, never sleeps, and will physically escort your idle admins out the door after 30 minutes of doing nothing.

That's this plugin.

  🔐 Admin logs in
   |
   |  👀 Every request tracked (timestamp saved in memory)
   |
   |  😴 Admin goes idle...
   |
   |  ⏰ 30 minutes pass...
   |
   🚪 BOOM. Logged out. Cookies cleared. Token dead.
         No arguments. No appeals. Just security.

✨ Features at a Glance

| Feature | What It Does | Vibe | | -------------------------- | ---------------------------------------------- | -------------------- | | ⏰ Auto-Logout | Kicks idle admins after configurable minutes | "Use it or lose it" | | 🚫 Single-Session Lock | One admin = one session. Period. | "No shadow clones" | | 💀 Token Revocation | Dead tokens stay dead. Instantly. | "Ghosts get ghosted" | | 🔑 Password Policy | Expiry + non-reusable passwords (configurable) | "Rotate or regret" | | ⚙️ Admin UI | Settings panel right inside Strapi | "Click, don't code" | | 🛡️ Input Validation | Server-side validation on every settings save | "Trust nobody" |


🚀 Quick Start

Step 1: Install it

yarn add strapi-security-suite

Step 2: Enable it

Add this to your config/plugins.js (or .ts):

module.exports = ({ env }) => ({
  'strapi-security-suite': {
    enabled: true,
  },
});

Step 3: Restart Strapi

yarn develop

Step 4: Find it

Go to SettingsGlobalSecurity Suite

That's it. You're done. Go get a coffee. ☕


🖼️ The Admin Panel

Once installed, you get a beautiful settings page with two panels:

┌───────────────────────────────────────────────────────┐
│            🛡️ Security & Session Settings              │
├───────────────────────────┬───────────────────────────┤
│                           │                           │
│  🕐 SESSION MANAGEMENT    │  🔑 PASSWORD MANAGEMENT    │
│                           │                           │
│  Auto Logout Time: [30]  │  Password Control: [ON]   │
│  (minutes)               │                           │
│                           │  Expiry Days: [30]        │
│  Multi-Session            │                           │
│  Control: [ON]            │  Non-Reusable: [ON]       │
│                           │                           │
├───────────────────────────┴───────────────────────────┤
│                               [ 💾 Save Settings ]    │
└───────────────────────────────────────────────────────┘

Everything is stored in the database. Change a value, hit save, it takes effect immediately. No restarts. No config files. No drama.


🧠 How It Actually Works

Here's the whole flow, explained like you're five (but a very smart five):

🔗 The Middleware Pipeline

When any request hits your Strapi server, it passes through 5 security checkpoints (middlewares), in this exact order:

  🌐 Incoming Request
       │
       ▼
  1. 🐣 seedUserInfos
  │    "Who are you? Let me check your JWT and load your profile"
  │
  ▼
  2. 🔍 interceptRenewToken
  │    "Trying to renew your token? Let me make sure you're still welcome"
  │
  ▼
  3. 👣 trackActivity
  │    "OK you're legit. I'm writing down the time. Don't be idle."
  │
  ▼
  4. ☠️ rejectRevokedTokens
  │    "Wait... is your session revoked? GET OUT. Cookies deleted. Token dead."
  │
  ▼
  5. 🚫 preventMultipleSessions  (on login only)
       "Already logged in somewhere else? 409 Conflict. One session only."

⏱️ The Auto-Logout Watcher

Running in the background, checking every 5 seconds:

  🔄 Every 5 seconds:
     │
     │  🔍 Check each active session in memory
     │  🕐 Compare last activity timestamp vs. configured timeout
     │
     │  😴 Idle too long?
     │     │
     │     YES → Add email to revoked set
     │     │     → Delete session from activity map
     │     │     → Log it: "Auto-logged out admin X after Y seconds"
     │     │
     │     NO  → Carry on, you're fine 👍

🖥️ The Frontend Interceptor

On the admin panel side, window.fetch is patched to watch for a special header:

  🌐 Admin makes any API call
       │
       ▼
  👀 Check response headers for 'app.admin.tk'
       │
       YES → 🚨 FORCED LOGOUT 🚨
       │     window.stop()
       │     window.location.reload()
       │     (Session is over. Go home.)
       │
       NO  → ✅ Normal response. Continue working.

📂 Project Structure

strapi-security-suite/
📁 admin/src/                    ← Admin panel (React)
│   📄 index.js                    Plugin entry + fetch interceptor
│   📄 constants.js                API paths, header names
│   📄 pluginId.js                 Plugin ID constant
│   📁 components/
│   │   📄 Initializer.jsx         Plugin lifecycle init
│   📁 pages/
│   │   📄 App.jsx                 Router
│   │   📄 HomePage.jsx            Settings UI (the pretty one)
│   📁 translations/
│       📄 en.json                 i18n strings
│
📁 server/src/                   ← Server-side (Node.js)
│   📄 index.js                    Plugin entry point
│   📄 register.js                 Middleware registration phase
│   📄 bootstrap.js                Permissions + settings seeding
│   📄 destroy.js                  Cleanup on shutdown
│   📄 constants.js                ⭐ ALL magic values live here
│   │
│   📁 controllers/
│   │   📄 adminSecurityController.js   GET/POST settings (with validation!)
│   │
│   📁 services/
│   │   📄 autoLogoutChecker.js    Background watcher (setInterval)
│   │
│   📁 middlewares/
│   │   📄 seedUserInfos.js        Hydrate session from JWT
│   │   📄 interceptRenewToken.js  Block renewal for dead sessions
│   │   📄 trackActivity.js        Record last activity timestamp
│   │   📄 rejectRevokedTokens.js  Nuke revoked sessions
│   │   📄 preventMultipleSessions.js  One-session-per-admin gate
│   │
│   📁 policies/
│   │   📄 has-admin-permission.js  Route-level permission check
│   │
│   📁 globals/                  ← In-memory state (the "brain")
│   │   📄 sessionActivityMap.js   Map<"id:email", timestamp>
│   │   📄 revokedTokenSet.js      Set<email> of revoked sessions
│   │   📄 loginLocks.js           Set<email> login race-condition guard
│   │
│   📁 utils/
│   │   📄 errors.js               PluginError, ValidationError, AuthorizationError
│   │   📄 force-expire-admin.js   Issue a 1-second JWT to kill client token
│   │
│   📁 content-types/
│   │   📁 security-settings/
│   │       📄 schema.json          DB schema (singleType)
│   │
│   📁 routes/
│   │   📄 index.js                Admin-typed routes with policies
│   │
│   📁 types/
│       📄 typedefs.js             JSDoc type definitions
│
📄 eslint.config.mjs               ESLint v9 flat config
📄 .prettierrc                     Prettier config
📄 package.json                    Scripts, deps, lint-staged
📁 .husky/
    📄 pre-commit                  Runs lint-staged before every commit

🔧 Configuration Schema

All settings live in a single-type content-type in the database:

{
  "autoLogoutTime": 30,
  "multipleSessionsControl": true,
  "passwordExpiryDays": 30,
  "nonReusablePassword": true,
  "enablePasswordManagement": true
}

| Field | Type | Default | What It Does | | -------------------------- | --------- | ------- | ---------------------------------------- | | autoLogoutTime | integer | 30 | Minutes of inactivity before auto-logout | | multipleSessionsControl | boolean | true | Block concurrent sessions for same admin | | passwordExpiryDays | integer | 30 | Days before password must be changed | | nonReusablePassword | boolean | true | Prevent reuse of previous passwords | | enablePasswordManagement | boolean | true | Master switch for password features |


🧪 API Endpoints

All routes are admin-typed (Strapi handles auth automatically):

| Method | Path | Auth | Permission | Description | | ------ | --------------------------------------- | -------- | ---------------- | --------------- | | GET | /strapi-security-suite/health | 🔓 None | — | Health check | | GET | /strapi-security-suite/admin/settings | 🔒 Admin | view-configs | Read settings | | POST | /strapi-security-suite/admin/settings | 🔒 Admin | manage-configs | Update settings |

🔐 Permissions

The plugin registers three permission actions:

| Permission | What It Allows | | ---------------------------------------------- | ------------------------ | | plugin::strapi-security-suite.access | Access the settings page | | plugin::strapi-security-suite.view-configs | Read security settings | | plugin::strapi-security-suite.manage-configs | Modify security settings |


✅ Engineering Standards Compliance

This plugin follows the STANDARDS.md operating protocol:

| Standard | Status | Details | | ----------------------------- | ------ | --------------------------------------------------------------------- | | 💬 ES6+ JavaScript | ✅ | Arrow functions, destructuring, template literals, native ESM | | 📄 Full JSDoc | ✅ | Every export documented with @param, @returns, @module | | 🔢 No Magic Values | ✅ | All values in constants.js (status codes, cookies, headers, timing) | | 🚨 Custom Error Hierarchy | ✅ | PluginErrorValidationError, AuthorizationError | | 🛡️ Input Validation | ✅ | saveSettings validates keys, types, and shape | | 🔍 ESLint | ✅ | v9 flat config with jsdoc plugin + Prettier compat | | 🎨 Prettier | ✅ | Single quotes, 100 print width, trailing commas | | 🪝 Husky + lint-staged | ✅ | Pre-commit: ESLint fix + Prettier on staged files | | 🏗️ Architecture | ✅ | Routes → Controllers → Services → Data (proper layering) | | 🔐 Security-First | ✅ | Auth/AuthZ separated, input validated, no secrets in logs |


🛠️ Development

# Install dependencies
yarn install

# Build the plugin
yarn build

# Watch mode (auto-rebuild on changes)
yarn watch

# Lint everything
yarn lint

# Lint + auto-fix
yarn lint:fix

# Check formatting
yarn format:check

# Auto-format everything
yarn format

# Verify plugin exports
yarn verify

🔮 Roadmap

| Feature | Status | | ----------------------------- | ----------------- | | ⏰ Auto-Logout | ✅ Shipped | | 🚫 Single-Session Enforcement | ✅ Shipped | | 💀 Token Revocation Pipeline | ✅ Shipped | | ⚙️ Admin Settings UI | ✅ Shipped | | 🔑 Password Expiry | 🚧 In Development | | 🔄 Non-Reusable Passwords | 🚧 In Development | | 📝 Admin Activity Logs | 🔜 Planned | | 📊 Security Dashboard | 🔜 Planned | | 👊 Brute Force Detection | 🔜 Planned | | 👁️ Real-time Session Viewer | 🔜 Planned |


🗣️ Real Talk

"We installed this and now our interns can't share logins anymore." — A CTO, probably

"Our admin panel feels like it judges us now. I love it." — That one developer who actually cares

"I left my desk for coffee and came back logged out. Respect." — Someone who now understands security


👥 Author

LPIX-11 — Orange / Sonatel


⚖️ License

MIT — Do whatever you want. Just don't blame us if you turn off all the features and get breached. That's on you.


💡 Philosophy

Security should be:

  • Fast — In-memory. No database lookups on every request.
  • Unforgiving — Idle? Gone. Revoked? Dead. Duplicated? Blocked.
  • Elegant — Clean constants, typed errors, layered architecture.
  • Mildly judgmental — This plugin will side-eye your stale sessions.

"The meta-principle: make the right thing the default thing. Discipline compounds. Shortcuts compound too, just in the wrong direction."