> For the complete documentation index, see [llms.txt](https://docs.e6data.com/query-engine/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.e6data.com/query-engine/guides/security/access-tokens/token-security-best-practices.md).

# Token security best practices

How to store e6data tokens safely, scope them with least privilege, revoke them, manage them as an admin, and understand what the audit trail records.

This page is for admins and anyone who handles e6data credentials. It covers how to store tokens safely, scope them with least privilege, revoke them, manage them as an admin, and what the audit trail does and doesn't record.

Tokens are **bearer credentials**: anyone who holds the string can act as that identity until the token is revoked or expires. e6data uses a fixed-credential model - there is no automatic refresh and no short-lived rotation built in. That puts the responsibility on you to store tokens carefully, scope them tightly, set an expiry, and revoke fast when something leaks. The practices below exist to shrink the blast radius if a token is ever exposed.

## Authentication vs. authorization

A token only proves **identity**. What that identity is *allowed* to do is decided separately, by **role bindings**. This separation is the single most important security property to understand:

**A token is exactly as dangerous as the roles bound to its owner.** A leaked token bound only to a Viewer role can read; a leaked token bound to an Admin role can do real damage. To restrict what a token can do, change the role binding - not the token. This is why least privilege matters so much.

## Storing tokens safely

* **Never commit a token to source control.** Treat any token that lands in a repo, log, chat message, PR comment, or screenshot as compromised - revoke it.
* **Never hardcode tokens** in source or config files. Use environment variables or a secrets manager.
* **Personal access tokens** → store in a personal password manager (1Password, Bitwarden).
* **Service account API keys** → store in your platform's secrets store (GitHub Actions Secrets, AWS Secrets Manager, HashiCorp Vault, and so on).

## Least privilege

* **Assign the minimum role required.** A pipeline that only reads data should be bound to a **Viewer** role, not **Admin**. Token permissions come entirely from role bindings, so the role binding *is* the security boundary.
* **One key per application.** Never share a single token across multiple apps or teams - separate keys mean you can revoke one without breaking the others, and the audit trail stays meaningful.
* **Never use a PAT in CI/CD.** A PAT carries your personal roles and will outlive your access if you change teams or leave. Use a service account with its own scoped role binding.
* **One service account per system.** A dedicated account for CI, another for Airflow, another for monitoring - each with only the access it needs.

## Expiry and rotation

* **Set an expiry** on every token unless you have a deliberate rotation process. Expiry is enforced on every request; an expired token returns `401`.
* **Rotate proactively** - before expiry and immediately on suspected exposure - using create-before-delete to avoid downtime. See [Create, use, rotate, and revoke tokens](/query-engine/guides/security/access-tokens/create-use-rotate-revoke.md#rotating-a-token).
* **Review active tokens periodically** and revoke any that are no longer in use.

## Revocation and offboarding

Revocation takes effect immediately - a revoked token fails on its very next request.

* **Exposed token?** Revoke it at once (Console or API), then issue a replacement.
* **Service account deleted?** All of its API keys are invalidated immediately - there is no grace period. Stand up a replacement account and rotate the credentials in your applications *before* deleting the old one.
* **Team member leaving?** This is the one most people get wrong:

{% hint style="warning" %}
Removing a user's workspace access does **not** automatically revoke their personal access tokens. Their tokens still authenticate; they just return `403 Forbidden` because the role binding is gone. The tokens remain valid until they expire or are explicitly revoked. Always revoke a departing user's PATs explicitly, and rotate any service account keys they had access to.
{% endhint %}

## Admin controls

Workspace admins can manage tokens across all users - but note this is done through the API, not the Console. The **User settings → Access tokens** screen only shows your own tokens; there is no cross-user view in the UI.

Admin token operations are gated by role permissions:

| Operation                     | Method and path                             | Permission            |
| ----------------------------- | ------------------------------------------- | --------------------- |
| List a user's tokens          | `GET /api/v1/accesstokens/users/<email>`    | `accesstokens:read`   |
| Revoke all of a user's tokens | `DELETE /api/v1/accesstokens/users/<email>` | `accesstokens:revoke` |

Revoke every token for a departing team member:

```bash
curl -s -X DELETE \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  https://<workspace>.e6.run/api/v1/accesstokens/users/user@company.com
```

Service accounts are governed by their own permissions - `serviceaccounts:create`, `:read`, `:update` (covers adding and revoking keys), and `:delete`. Grant these only to admins who manage automation identities.

## Incident response - a leaked token

1. **Revoke** the exposed token immediately (Console, or `DELETE …/tokens/<uuid>`). For a whole user, revoke all their tokens via `DELETE …/users/<email>`.
2. **Rotate** anything that shared the same secret store or pipeline.
3. For suspected usage abuse, pull your gateway or access logs.
4. **Re-issue** replacements with an expiry and the minimum role binding.

## Security checklist

| Practice                                          | Why it matters                                             |
| ------------------------------------------------- | ---------------------------------------------------------- |
| Token in a secrets manager, never in code or logs | Bearer credential - exposure means takeover                |
| Minimum role binding (Viewer where possible)      | The role binding is the only thing limiting a leaked token |
| Service accounts (not PATs) for automation        | PATs die with the person; keys are independent             |
| One key per app, one account per system           | Revoke or rotate without collateral damage                 |
| Expiry set and proactive rotation                 | Caps the lifetime of any single secret                     |
| Explicit PAT revocation when offboarding          | Removing workspace access alone does **not** revoke tokens |
| Gateway logging if you need a usage trail         | Token usage isn't recorded; capture it at the gateway      |

## See also

* [Access tokens](/query-engine/guides/security/access-tokens.md) - the canonical token-types table.
* [Create, use, rotate, and revoke tokens](/query-engine/guides/security/access-tokens/create-use-rotate-revoke.md) - creating, using, and rotating tokens.
* [Roles and permissions](/query-engine/guides/security/identity-and-rbac/roles-and-permissions.md) - defining the role bindings that bound a token's access.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.e6data.com/query-engine/guides/security/access-tokens/token-security-best-practices.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
