Skip to main content

Service accounts and API tokens

Why you shouldn't use a personal account

Using a personal user account for CI/CD or automation creates several problems:

  • The token is tied to an employee — if they leave, all integrations break
  • Personal account permissions are often broader than what the script needs
  • Actions appear in the audit log under the person's name, not the pipeline's
  • Revoking access requires deleting or changing the personal account

A dedicated service account separates automation from human identities, follows least privilege, and makes the audit trail clear.


Step 1 — Create a service account role

Before creating the account, create a role that grants only what automation needs.

  1. Go to Settings → User management → Roles.
  2. Click Create role and name it (e.g. CI/CD service account or Rotation bot).
  3. Enable only the following permissions:
    • Use API (required for token generation)
    • No access to user management, system settings, LDAP, SSO, or vault type management
  4. Click Create.

Directory access (which vaults and folders the service account can read or write) is configured separately when the service account is created

One role per pipeline type

If you have multiple automation use cases (deploy bot, rotation script, audit exporter), create separate roles with different permission sets. This limits damage scope if a token is compromised.


Step 2 — Create the service account

  1. Go to Settings → User management → Users.
  2. Click Create user.
  3. Use a clearly identifiable login, e.g. svc-cicd-production or svc-rotation-bot.
  4. Assign the role created in Step 1 and groups, if necessary.
  5. Click Create.

If using LDAP, create a dedicated LDAP service account in your directory and map it to Passwork. Do not reuse an AD service account that has other system rights.


Step 3 — Grant vault access

The service account must be explicitly added to the vaults and folders it needs to access.

  1. Open the service account profile.
  2. Set the necessary access levels for the corresponding vaults listed on the Access rights tab.
Use caseMinimum access level
CI/CD pipeline (read secrets for deployment)Read only
Rotation script (update secret values)Read and edit
Audit / reporting scriptRead only
Migration / bulk importFull access on target vault

Use folder-level access if the service account only needs a subset of the vault.


Step 4 — Generate the token pair

  1. Open the service account profile
  2. Open the API tokens menu in the rightside panel and click Create API token.
  3. Copy both the accessToken and refreshToken immediately — they are shown only once.
Service account page
Store tokens securely

Never store tokens in source code, .env files committed to repositories, or CI/CD job logs. Use your CI/CD platform's encrypted secret storage (GitHub Secrets, GitLab CI/CD with masked variables, HashiCorp Vault, AWS Secrets Manager, etc.).


Token pair lifecycle

Passwork API uses two tokens with different lifetimes:

TokenTypical lifetimePurpose
accessTokenMinutes to hoursAdded to every API request as Authorization: Bearer
refreshTokenDays to weeksUsed to obtain a new token pair when access token expires

When accessToken expires, the API returns HTTP 401 with code accessTokenExpired. The integration then calls the refresh endpoint and updates both tokens.

The Python connector handles this automatically. For shell scripts using passwork-cli, the CLI also handles token refresh transparently when PASSWORK_REFRESH_TOKEN is provided.


Token rotation strategy

Regular rotation of the service account's token pair reduces the risk from token leakage.

Recommended token lifetimes by use case:

Use caseaccessToken lifetimerefreshToken lifetime
CI/CD job (ephemeral)15–60 minutes1 day
Always-on service (monitoring, rotation bot)1–4 hours30 days
Manual/scheduled script1 hour7 days

Rotating tokens via API:

Three endpoints are available (see API token rotation for full reference):

curl -s --request POST \
--url "https://passwork.example.com/api/v1/sessions/refresh" \
--header 'Content-Type: application/json' \
--header 'X-Response-Format: raw' \
--header "Authorization: Bearer $PASSWORK_TOKEN" \
--data "{\"refreshToken\": \"$PASSWORK_REFRESH_TOKEN\"}" | jq .

The token storage paradox

Passwork is the secret store — but you need a credential to access it. Where do you store the Passwork token?

Recommended approaches:

EnvironmentWhere to store Passwork tokens
CI/CD (GitHub Actions, GitLab)Platform's encrypted secret storage (masked variables)
Kubernetes workloadsKubernetes Secret, ideally populated by an external secret operator
Long-running servicesEnvironment variable injected at startup via a higher-trust secret store or config management
Developer workstations.env file not committed to VCS, or OS keychain

The key principle: Passwork tokens are bootstrap credentials. They live one level above the secrets they protect. They need strong protection — not as strong as a cloud provider root key, but stronger than an application database password.