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 |
🚀 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) 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=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. |
▶️ 3. Start Strapi and verify
npm run developWatch 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 TroubleshootingIf 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:
- Open the admin panel and go to Settings → ShieldAuth → My MFA Devices.
- Click Enroll TOTP, scan the QR code with your authenticator app.
- Confirm with a 6-digit code from the app.
- Save your recovery codes — they're shown once and you'll need them if you lose your authenticator.
- 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
instanceIdand consumes a new seat. If you're stress-testing or rebuilding environments, you may hitinstance-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:
- 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.
- Remove the plugin from
config/plugins.ts. 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.