Documentation Index
Fetch the complete documentation index at: https://specterops-2-feature-scoped-api-tokens.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Introduction
User login is handled with JSON Web Tokens (JWT). User-managed API tokens and service tokens are opaque database-backed credentials:-
Submit credentials to the
loginaction and receive a short-lived JWT that can interact with Ghostwriter as the authenticated user -
Create an API token from your profile and receive an opaque
gwat_token for user-bound automation -
Create a service token from your profile and receive an opaque
gwst_token for scoped non-human automation
DJANGO_JWT_SECRET_KEY. If you plug a Ghostwriter JWT into a
debugger like the one at https://jwt.io/, you will see something similar to the following:
User Tokens
User JWTs are generated with thelogin action. The resulting JWT holds the same privileges as the authenticated user.
User JWTs are valid for 15 minutes and include a tracked session identifier so administrators can revoke active sessions.
The collaborative editor uses JWTs with the
ghostwriter-collab+jwt type. Hasura accepts these tokens only as the
restricted collab role for the editor’s required read-only GraphQL queries. General GraphQL Actions reject them except
for the collaborative editor permission-check endpoint. Collab JWTs include scope claims for the editor model, object,
report, and finding. The webhook exposes these claims as Hasura session variables so the collab role can read only the
evidence rows needed by that editor page. Missing numeric IDs are represented as -1. Collab JWTs are not tracked in
UserSession; that table is only for JWTs returned by the login action.The
Login action is disabled for accounts with MFA configured. An account with MFA should use a generated API token (see below).API Tokens
You can also generate API tokens by visiting your profile page and using the API Tokens card. In this section, you can create new tokens, see all existing tokens, hide expired tokens, and revoke tokens you no longer need. API tokens are opaque tokens with agwat_ prefix. They are not JWTs and do not contain a readable payload. Ghostwriter
stores a hash of the token secret and validates the database record on each request so tokens can be revoked immediately.
API tokens have user-defined expiration dates. They are intended for automation tasks that should inherit the current
permissions of the user who created the token.
Service Tokens
Service tokens are created from the Service Tokens card on the user profile page. Service tokens are scoped credentials for non-human service principals. They do not inherit the permissions of the user who created them. Use service tokens when automation should have a fixed, limited permission set, such as:- Read/write access to one operation log and its entries
- Read-only access to project data
service role. Hasura exposes queries, mutations, and Actions at the role level, so a
service token might see GraphQL fields that are intended for another service-token preset. Token-specific permissions are
still enforced by Hasura row filters and Django Action authorization. For example, an operation-log read/write token can
see project-read Actions in the schema, but those Actions return an authorization error unless that specific token has the
required project-read grant.
These tokens are not JWTs. They are opaque tokens with a gwst_ prefix for easy identification. Opaque tokens do not include
a payload that describes a user or permission set. Rather, they are backed by a database entry that controls their permission
set.
User Profile and Tokens
Token Authentication
Requests authenticate with theAuthorization header: Authorization: Bearer TOKEN
Hasura connects to an authentication webhook before a request. The webhook accepts three credential families:
- login JWTs returned by the
loginaction - opaque user API tokens with the
gwat_prefix - opaque service tokens with the
gwst_prefix
- Check the JWT is present
- Attempt to decode the JWT and verify the signature, audience, and expiration
- Verify the JWT type and required claims
- Verify the tracked session exists, has not expired, has not been revoked, and belongs to the JWT subject
- Finally, verify the user details are correct and that the account is still active
200 OK response with your requested data.
For collaborative editor JWTs, the webhook verifies the JWT signature, audience, expiration, ghostwriter-collab+jwt
type, and active user. It then returns the restricted collab role with the token’s collab-scope session variables.
The collaborative editor permission-check endpoint also requires the requested model and object ID to match the token’s
collab scope.
For API tokens, the webhook validates the opaque token prefix and secret, checks the API token database record, and then
authenticates the request as the token’s user.
For service tokens, the webhook validates the opaque token, verifies the service principal is active, and returns
service-scoped session variables to Hasura. Service tokens do not become users and do not receive the permissions of
the user who created them. The shared service role controls which schema fields are visible, while each token’s
ServiceTokenPermission rows control which protected rows and Django-backed Actions the token can use.
If a request does not include an Authorization header, the webhook returns the public role with the username
anonymous. This is not a real user or role and is only used to manage access to resources designed to be accessed
without authentication. The only action available for this anonymous role is the Login action.
If a request includes an invalid, expired, revoked, or otherwise unacceptable token, the authorization webhook will return
a 401 Unauthorized response with an error like this: