Secrets Rotation

Document Engine offers the following options for authentication:

  • Dashboard password — Used to access the PSPDFKit Dashboard.

  • Secret keybase — Used for generating secret keys for the purposes of authentication.

  • Public key for authenticating JWT payloads — Used for client authentication.

Collectively, these options are referred to as secrets.

Secrets Management

You can configure secrets using environmental variables. However, this approach has the following disadvantages:

  • You can’t change secrets during runtime.

  • You can’t use more than one valid secret.

  • You need to restart Document Engine.

Document Engine provides an alternative mechanism for managing secrets: There’s always a “current” version of a secret that never expires and you can only change this current version using secret rotation. Next to the current version, you can have other secrets, but the non-current secrets need to have an expiration date.

By default, secrets are sourced from the following environmental variables:

  • JWT_PUBLIC_KEY

  • SECRET_KEY_BASE

  • DASHBOARD_PASSWORD

To change this behavior, set the REPLACE_SECRETS_FROM_ENV configuration option to false. In this case, current secrets are only sourced from environmental variables if the secrets aren’t yet set via the API. REPLACE_SECRETS_FROM_ENV must be set to false to enable secret rotation. Otherwise, secrets set via the API are replaced on every restart.

Secrets can be managed via the secrets API. The secret APIs expects the secret :type, which can be jwt, dashboard_password, or secret_key_base.

Adding a New Secret

To add a new secret, use the following request:

POST /api/secrets/:type
Content-Type: application/json
Authorization: Token token="<secret token>"

{
  "secret": "my new secret string",
  "expiresAt": "2023-01-01T12:00:00.000000Z"
}

The secret field is the new secret. expiresAt sets the expiration date for the secret. The date and time are in UTC in ISO 8601 format.

Listing Secrets

To list the IDs and expiry dates of existing secrets, use the following request:

GET /api/secrets/:type
Authorization: Token token="<secret token>"

An example response is the following:

[
  {
    "id": 1,
    "expiresAt": null
  },
  {
    "id": 2,
    "expiresAt": "2023-01-01T12:00:00.000000Z"
  },
  ...
]

Only non-expired secrets are returned. For the current secret, the expiresAt field is null.

Rotating Secrets

Current secrets don’t expire. To change current secrets, rotate them using the request below:

POST /api/secrets/:type/rotate
Content-Type: application/json
Authorization: Token token="<secret token>"

{
  "secret": "my new secret string"
}

Expiring Existing Secrets

To change the expiration date of secrets other than the current one, use the request below:

PATCH /api/secrets/:type/:id
Content-Type: application/json
Authorization: Token token="<secret token>"

{
  "expiresAt": "2023-01-01T12:00:00.000000Z"
}