Skip to content

Secure rotation & revocation of Strapi API and admin tokens

Learn how to configure, automate, and audit token rotation and revocation in Strapi 5, keep keys visible for operations, satisfy GDPR requirements, and stay protected against token leakage.

By the Revisionary team · · 4 min read

MacBook Pro
Photo by AltumCode on Unsplash

Developers can achieve secure, automated rotation and revocation of Strapi 5 API and admin tokens by configuring encryption, using the built‑in regeneration endpoint, storing secrets in a vault, and relying on audit logs for visibility and compliance. The process keeps token lifetimes short, ensures old tokens are invalidated instantly, and provides a tamper‑evident trail that satisfies GDPR audit needs.

Why token rotation matters

  • Limited exposure – Short‑lived tokens reduce the window an attacker can use a stolen key.
  • Compliance – GDPR requires the ability to demonstrate when personal data was accessed and by whom; audit logs of token events provide that evidence.
  • Operational hygiene – Automated rotation removes the need for manual key changes, lowering human error.
a bunch of blue wires connected to each other
Photo by Scott Rodgerson on Unsplash

1. Configure persistent token visibility

Strapi only shows a token once after creation unless an encryption key is defined. To keep tokens readable by your CI/CD or secret‑management tool, set admin.secrets.encryptionKey in /config/admin.js.

js
// /config/admin.js
module.exports = ({ env }) => ({
  admin: {
    // A 32‑byte base64 string – keep it safe in a vault
    secrets: {
      encryptionKey: env('STRAPI_ENCRYPTION_KEY'),
    },
    // Optional: customise the salt used for all tokens
    apiToken: {
      salt: env('API_TOKEN_SALT'),
    },
  },
});

Store STRAPI_ENCRYPTION_KEY and API_TOKEN_SALT in a secret manager (e.g., HashiCorp Vault, AWS Secrets Manager) and reference them via environment variables.

2. Choose appropriate token lifetimes

Strapi 5 lets you set token expiration to 7 days, 30 days, 90 days, or Unlimited. For production services, a 30‑day lifespan balances security and operational load.

bash
# Example: create a 30‑day API token via the REST API
curl -X POST https://cms.example.com/admin/api-tokens \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"frontend‑service","expiresIn":"30d"}'

The response contains the plaintext token only once; after that it is stored encrypted using the key above.

3. Automate rotation with the regeneration endpoint

Strapi added a programmatic endpoint to rotate a token without deleting and recreating it:

code
POST /admin/api-tokens/:id/regenerate

The endpoint returns a fresh access key while automatically revoking the previous one.

js
// rotation‑script.js – run from CI every 30 days
const fetch = require('node-fetch');
require('dotenv').config();

const ADMIN_TOKEN = process.env.STRAPI_ADMIN_TOKEN; // stored in vault
const TOKEN_ID = process.env.TARGET_API_TOKEN_ID; // ID of the token to rotate

async function rotate() {
  const res = await fetch(
    `https://cms.example.com/admin/api-tokens/${TOKEN_ID}/regenerate`,
    {
      method: 'POST',
      headers: { Authorization: `Bearer ${ADMIN_TOKEN}` },
    }
  );
  if (!res.ok) throw new Error('Rotation failed');
  const { accessKey } = await res.json();
  console.log('New token:', accessKey);
  // Store the new key back to the secret manager
  // e.g., AWS Secrets Manager put‑secret-value …
}

rotate().catch(console.error);

Add the script to a scheduled job (GitHub Actions, GitLab CI, Jenkins) and update the dependent services to read the refreshed secret from the vault.

4. Immediate revocation when a compromise is suspected

If a token is suspected to be leaked, revoke it instantly via the admin UI or the API:

bash
curl -X DELETE https://cms.example.com/admin/api-tokens/<id> \
  -H "Authorization: Bearer <admin-token>"

Because the same apiToken.salt is shared across API and admin tokens, changing the salt invalidates all existing tokens. This is a powerful emergency measure.

js
// emergency‑salt‑rotation.js
require('dotenv').config();
const fetch = require('node-fetch');

const ADMIN_TOKEN = process.env.STRAPI_ADMIN_TOKEN;
const NEW_SALT = require('crypto').randomBytes(32).toString('base64');

async function rotateSalt() {
  const res = await fetch('https://cms.example.com/admin/settings', {
    method: 'PUT',
    headers: {
      Authorization: `Bearer ${ADMIN_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ apiToken: { salt: NEW_SALT } }),
  });
  if (!res.ok) throw new Error('Salt rotation failed');
  console.log('All tokens invalidated');
}

rotateSalt().catch(console.error);

After running, generate fresh tokens for the services that still need access.

5. Enable and tune audit logging

Audit logs capture create, update, delete, and regenerate events for tokens, without storing the actual secret values. They also record the requestor’s IP address and, where permitted, request payloads – data required for GDPR‑compatible records.

5.1 Turn on audit logs (Enterprise only)

Add the following to /config/admin.js:

js
module.exports = ({ env }) => ({
  admin: {
    auditLogs: {
      enabled: true,
      retentionDays: env.int('AUDIT_LOG_RETENTION_DAYS', 180), // keep for 6 months
      exportMaxRows: env.int('AUDIT_LOG_EXPORT_MAX', 2000000),
    },
  },
});

The default retention is 90 days; extending it helps meet GDPR’s “record‑keeping” expectations.

5.2 Exporting logs for compliance reviews

bash
curl -X GET https://cms.example.com/admin/audit-logs/export \
  -H "Authorization: Bearer <admin-token>" \
  -o audit-logs.csv

The CSV can be stored in an immutable bucket (e.g., AWS S3 with Object Lock) to provide a tamper‑evident audit trail.

6. GDPR‑focused considerations

RequirementHow Strapi helps
Data minimisationTokens are never stored in plaintext after creation; only the encrypted version lives in the database.
Right to accessExported audit logs give data subjects visibility into when their personal data was accessed via a token.
Right to erasureDeleting a token (or rotating the salt) instantly removes its ability to authenticate, satisfying a “forget‑me” request.
Record‑keepingConfigurable audit‑log retention up to 180 days (or longer) aligns with typical GDPR retention policies.

7. Best‑practice checklist

  • Set admin.secrets.encryptionKey in /config/admin.js and store the key in a vault.
  • Define a unique apiToken.salt; rotate it only in emergencies.
  • Choose a token TTL of 30 days (or less) for all production services.
  • Automate rotation with the POST /admin/api-tokens/:id/regenerate endpoint.
  • Store fresh tokens back into the secret manager, never in code or repo.
  • Enable audit logs and configure retention to meet regulatory windows.
  • Export logs regularly and archive them in an immutable store.
  • Document revocation procedures (UI delete, salt rotation) in your incident‑response playbook.
  • Review permissions – ensure only privileged roles can create or regenerate tokens (see /docs/reference/configuration).
  • Test rotation in a staging environment before rolling out to production.

8. Integrating with Revisionary (optional)

If your project already uses the Revisionary plugin, you can link token‑related events to content‑change audits. The audit log already records token actions; Revisionary’s audit entries can be correlated by user ID to provide a full picture of who changed content and which token they used. This synergy improves traceability for both content and security teams.

A combination lock rests on a computer keyboard
Photo by Sasun Bughdaryan on Unsplash

9. Sample end‑to‑end workflow

  1. CI pipeline pulls STRAPI_ENCRYPTION_KEY, API_TOKEN_SALT, and STRAPI_ADMIN_TOKEN from the vault.
  2. Nightly job runs rotation‑script.js for each service token.
  3. Script writes the new token back to the vault and updates the service’s environment.
  4. Audit log automatically records the regeneration event (timestamp, IP, user ID).
  5. Monthly compliance run exports audit logs, validates that no token exceeds the TTL, and archives the CSV.

Following this workflow keeps your Strapi installation compliant, reduces the attack surface, and provides the visibility required by GDPR and internal security policies.


For further reading on Strapi’s security features, see the official docs and blog posts linked below.

TagsStrapiAPI securitytoken rotationaudit logsGDPR

Sources

  1. API Tokens – Strapi Documentation
  2. Admin Tokens – Strapi Documentation
  3. How to store API keys securely – Strapi Blog
  4. Audit Logs – Strapi Documentation
  5. Programmatic token regeneration PR
  6. Strapi security plugins overview

The Revisionary team

Developers who build Revisionary, a version history plugin for Strapi 5. We write about Strapi, web development, AI and application security.

This article was written with the help of AI.

All articles