← Back to Articles
Tutorial2026-10-18 • 5 min read

Securing Strapi REST Endpoints: API Tokens in v4 & v5

Written by Siji AI (MooLux Tech Team)

# Securing Public and Private REST Endpoints with API Tokens in Strapi v4 and v5

Headless CMS architectures demand strict boundary controls between public content delivery and private management workflows. In Strapi v4 and v5, API Tokens serve as the primary authentication mechanism for REST endpoints. This guide covers architectural best practices, terminal automation, performance tuning, and Linux deployment hardening.

Why API Token Security Matters in Headless Architectures

Unlike traditional monolithic CMS platforms, Strapi exposes a JSON-based REST API by design. Every data mutation, media upload, or role-specific query travels over standard HTTP(S). Without tokenization:

  • Unrestricted read access exposes internal content models and relationships
  • Privilege escalation occurs when users bypass admin UI restrictions
  • Audit trails break, making compliance (GDPR, SOC2) nearly impossible

API Tokens in Strapi solve this by acting as scoped JWT-like credentials tied to specific Roles, Permissions, and Expiration policies. Strapi v5 further tightens this with granular plugin-level scoping and improved session handling.

Understanding Strapi’s Permission Model (v4 vs v5)

Both versions rely on a Role → Permission → API Token chain:

| Feature | Strapi v4 | Strapi v5 | |---------|-----------|-----------| | Token Generation | Admin UI / REST /api/api-tokens | Enhanced REST /api/v1/api-tokens | | Expiration Enforcement | Optional (requires cron/plugin) | Native TTL enforcement with middleware | | Scope Granularity | Global CRUD on content-type | Plugin, route, and field-level scoping | | Audit Logging | Basic token creation logs | Immutable audit trail with IP tracking |

Architectural Tip: Never bind tokens to the super-admin role. Use custom roles like content-reader, media-manager, or api-integrator to enforce least-privilege access.

Generating and Managing API Tokens via Terminal

Automate token creation for CI/CD pipelines and infrastructure-as-code deployments. Use Strapi’s internal API or environment-driven provisioning:

bashMooLux Terminal
# Create a token via curl (requires admin session cookie or admin API key)
curl -X POST http://localhost:1337/api/api-tokens \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production-frontend-reader",
    "description": "Read-only access for Next.js/SvelteKit apps",
    "type": "full-access", 
    "permission": { "roleType": "public" }
  }'

In Strapi v5, use the improved token creation payload with explicit expiration and custom fields:

bashMooLux Terminal
curl -X POST http://localhost:1337/api/v1/api-tokens \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ci-cd-uploader",
    "type": "custom",
    "expiresAt": "2025-12-31T23:59:59Z",
    "permissions": ["plugin::upload.assets.read"]
  }'

Best Practice: Store tokens in systemd-environment or vault rather than .env files. Rotate quarterly using Strapi’s tokens.regenerate endpoint.

Securing Public vs. Private Endpoints: Practical Implementation

Public Endpoints (Read-Only) Public tokens should only expose content-types like `articles`, `homepage`, or `navigation`. Configure Strapi’s **Role Permissions** to allow `find` and `findOne` only.

javascriptMooLux Terminal
// config/middleware.js (Strapi v4/v5 hybrid pattern)
module.exports = {
  settings: {
    cors: { enabled: true, origin: "https://yourdomain.com" },
    responseTime: { enabled: true },
    security: { enabled: true, disablePoweredBy: true }
  }
};

Frontend consumption with fetch:

javascriptMooLux Terminal
const PUBLIC_TOKEN = process.env.STRAPI_PUBLIC_TOKEN;

const fetchData = async () => {
  const res = await fetch("https://api.yourdomain.com/api/articles?populate=*", {
    headers: { "Authorization": `Bearer ${PUBLIC_TOKEN}` }
  });
  return res.json();
};

Private Endpoints (Write/Mutation) Private tokens handle media uploads, draft publishing, or webhook triggers. Bind these to elevated roles with explicit `create`, `update`, and `delete` permissions.

Rate Limiting at the Proxy Layer:

nginxMooLux Terminal
# /etc/nginx/sites-enabled/strapi-proxy.conf
limit_req_zone $binary_remote_addr zone=api_tier:10m rate=30r/s;

server {
    listen 443 ssl;
    server_name api.yourdomain.com;

    location /api/ {
        limit_req zone=api_tier burst=10 nodelay;
        proxy_pass http://127.0.0.1:1337;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Optimizing Token Performance & Linux Deployment Tips

  1. Connection Pooling: Strapi relies on PostgreSQL/MySQL. Use pgbouncer or proxySQL to reduce TCP handshake latency for high-frequency token validation.
  2. Token Caching: Enable Redis-based session/token cache via @strapi/provider-auth-local or custom middleware to skip repeated DB role lookups.
  3. Systemd Optimization: Run Strapi with Restart=always, ExecReload=/bin/kill -HUP $MAINPID, and WatchdogSec=30 for crash resilience.
  4. File Descriptor Limits: Headless APIs open many concurrent socket connections. Increase /etc/security/limits.conf:
bashMooLux Terminal
* soft nofile 65535
   * hard nofile 65535

5. Audit Rotation: Use logrotate for Strapi’s logs/ directory to prevent disk saturation on long-running Linux instances.

Best Practices for Production Hardening

  • Enforce HTTPS everywhere with Let’s Encrypt or internal PKI; tokens transmitted over HTTP are trivially intercepted.
  • Bind tokens to IP allowlists where possible using Strapi v5’s enhanced plugin architecture or nginx $allow directives.
  • Monitor token entropy: Reject tokens with predictable prefixes or weak generation patterns. Strapi’s native generator uses crypto.randomBytes(24).
  • Implement graceful token revocation: Delete or expire tokens via the REST API instead of hard-restarting the Strapi process.
  • Version your API paths: Use /api/v1/ prefixes to decouple token validation middleware from future schema migrations.

Conclusion

Securing REST endpoints in Strapi v4 and v5 isn’t just about adding an Authorization header. It’s a systemic architecture decision that touches role design, proxy configuration, Linux resource limits, and deployment automation. By leveraging scoped API tokens, enforcing least-privilege permissions, and hardening your Linux stack, you build a headless CMS that scales securely across production workloads.

Next Steps: Audit your current role-permission matrix, migrate legacy tokens to v5’s expiration-aware format, and integrate token rotation into your CI/CD pipeline. Security is iterative—start small, measure latency impact, and iterate.