JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 63
  • Score
    100M100P100Q96066F
  • License SEE LICENSE IN LICENSE

Multi-factor authentication for Strapi v5 admin panel with license-gated Pro features.

Package Exports

  • strapi-plugin-shieldauth/package.json
  • strapi-plugin-shieldauth/strapi-admin
  • strapi-plugin-shieldauth/strapi-server

Readme

ShieldAuth — MFA for Strapi v5

Secure your Strapi v5 admin panel with modern multi-factor authentication.

ShieldAuth ships with TOTP and recovery codes today, with Email OTP, SMS, and WebAuthn on the roadmap. All paid factors are unlocked by your ShieldAuth license — the plugin validates your key against the ShieldAuth backend on startup and once per hour thereafter.


✅ Requirements

Strapi v5.x
Node.js ≥ 20 (the plugin uses native fetch and crypto.randomUUID)
Database Any Strapi-supported DB (Postgres, MySQL, SQLite). The plugin's instanceId is persisted to your DB — see Seats & instanceId.
ShieldAuth account A license key issued from your ShieldAuth dashboard
Outbound HTTPS Strapi must be able to reach the ShieldAuth backend (default https://api.shieldauth.example.com)

🚀 Install

npm install strapi-plugin-shieldauth

⚙️ 1. Register the plugin

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

export default ({ env }) => ({
  shieldauth: {
    enabled: true,
    config: {
      // Optional — you can also paste the key in the admin UI.
      licenseKey: env('SHIELDAUTH_LICENSE_KEY'),
      // Shown in TOTP authenticator apps (Google Authenticator, 1Password, etc.).
      appName: 'My Strapi App',
      issuer: 'My Company',
    },
  },
});

That's the entire plugin config. Everything else (license key, encryption key, backend URL) is read from environment variables — keep them out of source control.


🔐 2. Set environment variables

Add these to your .env:

# Your license key. Get it from your ShieldAuth dashboard.
# You can leave this blank and paste the key in the admin UI instead — both work.
SHIELDAUTH_LICENSE_KEY=

# Strongly recommended — encrypts TOTP secrets at rest (AES-256-GCM).
# Generate with:  openssl rand -hex 32
# ⚠️  Changing this value AFTER users enroll will invalidate every TOTP setup.
SHIELDAUTH_ENCRYPTION_KEY=

# Optional — override only for self-hosted ShieldAuth or staging.
# Defaults to the production ShieldAuth backend.
# In production this MUST be HTTPS — your license key is the auth credential.
# SHIELDAUTH_BACKEND_URL=https://api.shieldauth.example.com

What each variable does

Variable Required Source Notes
SHIELDAUTH_LICENSE_KEY ❌ optional ShieldAuth dashboard Either set it here (good for Docker/CI) or paste it in the admin UI (good for first-time setup). The admin-UI value always wins if both are set. Treat the key as a secret — it authenticates every API call.
SHIELDAUTH_ENCRYPTION_KEY ❌ optional You generate it If unset, falls back to Strapi's admin.auth.secret. Set a dedicated value so rotating Strapi's admin secret doesn't break your TOTP enrollments.
SHIELDAUTH_BACKEND_URL ❌ optional Override the default production URL. Leave unset unless you're on staging or running self-hosted ShieldAuth. Must be https:// in production — the license key is sent as a Bearer token.

▶️ 3. Start Strapi and verify

npm run develop

Watch the logs for one of:

[shieldauth] License valid — plan=<your-plan> source=remote        ← all good
[shieldauth] License INVALID — No license key configured. ...       ← paste key in admin UI
[shieldauth] License backend rejected our Authorization header (...)← see Troubleshooting

If you didn't set SHIELDAUTH_LICENSE_KEY, open http://localhost:1337/admin, go to Settings → ShieldAuth → License, and paste your key. Validation runs immediately and the status panel updates.


🔑 4. Enroll your first admin

Once the license shows valid:

  1. Open the admin panel and go to Settings → ShieldAuth → My MFA Devices.
  2. Click Enroll TOTP, scan the QR code with your authenticator app.
  3. Confirm with a 6-digit code from the app.
  4. Save your recovery codes — they're shown once and you'll need them if you lose your authenticator.
  5. Log out, log back in. You'll be prompted for a TOTP code after entering your password.

🪪 Seats & instanceId

Every plugin install generates a UUID (instanceId) on first startup and persists it to your Strapi DB. The ShieldAuth backend counts each unique instanceId against your seat allowance.

Important:

  • The same Strapi DB = the same instanceId = one seat. Restart, redeploy, scale horizontally — all fine, no seat consumed.
  • A fresh Strapi DB (new project, wiped DB, ephemeral container without persistence) generates a new instanceId and consumes a new seat. If you're stress-testing or rebuilding environments, you may hit instance-limit-exceeded.
  • To free a seat: clear the license key in the admin UI, or click Release this install. Both call the backend's deactivate endpoint.

🛠️ Troubleshooting

Symptom Likely cause Fix
Logs: code=missing-authorization No license key configured Paste your key in the admin UI or set SHIELDAUTH_LICENSE_KEY.
Logs: code=invalid-scheme or code=invalid-key-format License key is malformed (truncated copy/paste, extra whitespace) Re-copy from your dashboard, paste again.
Validation returns reason: "not-found" Key doesn't exist on the backend Check for typos. Make sure you copied the full key.
Validation returns reason: "revoked" Key was revoked by ShieldAuth admin Contact support.
Validation returns reason: "expired" License past its renewal date Renew on the ShieldAuth dashboard; refresh in admin UI.
Validation returns reason: "instance-limit-exceeded" More installs are claiming seats than your plan allows Deactivate an unused install (admin UI → Release this install) or upgrade your plan.
All TOTP logins suddenly fail with "invalid code" after a redeploy SHIELDAUTH_ENCRYPTION_KEY changed Restore the previous key value. If genuinely lost, every user must re-enroll TOTP.
Backend unreachable, logs reason: "offline-fallback" Network outage between your Strapi server and ShieldAuth Plugin uses the last cached license result for ~1 hour. Fix connectivity; the plugin retries with 1m → 5m → 15m backoff.

🔄 Rotating secrets

Secret How to rotate
SHIELDAUTH_LICENSE_KEY Update env var (or admin UI) → plugin re-validates immediately. Old key continues to work until you either deactivate the seat or the SaaS revokes it.
SHIELDAUTH_ENCRYPTION_KEY Don't, casually. Changing this invalidates all TOTP enrollments. If you must, plan a maintenance window: rotate, then ask all users to re-enroll.

🧹 Uninstalling cleanly

To uninstall in a way that frees the seat for reuse:

  1. In the admin UI: Settings → ShieldAuth → License → Clear license key. The plugin calls the deactivate endpoint and frees your seat before clearing the local key.
  2. Remove the plugin from config/plugins.ts.
  3. npm uninstall strapi-plugin-shieldauth.

If you skip step 1 — for example, you delete the project without clearing the key — the seat stays attached to that orphaned instanceId. Contact ShieldAuth support to release it.


✨ Features

  • Time-based One-Time Password (TOTP) — RFC 6238
  • Recovery codes (single-use, one-time-shown)
  • AES-256-GCM encryption of TOTP secrets at rest
  • Replay protection on TOTP verification
  • Rate limiting on authentication attempts
  • One-time login nonce (secure step-up flow)
  • Pluggable factor registry (Email OTP / SMS / WebAuthn coming)
  • License-driven feature gating

🔒 License & support

ShieldAuth is a commercial plugin.

  • A valid license key is required.
  • License validation runs on every Strapi startup and once per hour thereafter.
  • Unauthorized usage, redistribution, or modification is prohibited.

For licenses, billing, or support: 👉 aniket07013@gmail.com


📄 License

Proprietary — see the LICENSE file.