Authentication

Explanation of the authentication mechanisms for Ghostwriter's JSON Web Tokens

Introduction

Authentication is handled via JSON Web Tokens (JWT). There are two methods for retrieving a JWT:

  • Submit credentials as described below and receive a JWT that is capable of interacting with Ghostwriter as the authenticated user

  • Login via the web interface and generate a JWT with your preferred expiration date to use as an API token for automation

The JWT secret key is defined in the environment variables, GRAPHQL_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:

HEADER
{
  "alg": "HS256",
  "typ": "JWT"
}
PAYLOAD
{
  "username": "benny",
  "sub": "1",
  "sub_name": "benny",
  "sub_email": "[email protected]",
  "aud": "Ghostwriter",
  "iat": 1646088460,
  "exp": 1646117260,
}
SIGNATURE
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The tokens follow the JWT open standard (RFC7519).

User Tokens

User JWTs are generated with a Login action. The resulting JWT holds the same privileges as the authenticated user. The user JWTs are valid for 15 minutes.

mutation Login {
  login(password: "password", username: "username") {
    token
    expires
  }
}

The Login action is disabled for accounts with 2FA configured. An account with 2FA should use a generated API token (see below).

API Tokens

You can also generate tokens by visiting their profile page and scrolling down to the "API Tokens" section. In this section, you can create new tokens, see all existing tokens, and revoke tokens you no longer need.

A critical difference between API tokens and tokens generated by the Login action is they have user-defined expiration dates. They are intended to be used for long-running automation tasks.

Token Authentication

Requests authenticate with the Authorization header: Authorization: Bearer TOKEN

Hasura will connect to an authentication webhook before a request. The webhook takes several steps to thoroughly examine the JWT before allowing a request to proceed:

  1. Check the JWT is present

  2. Attempt to decode the JWT and verify the signature, audience, and expiration

  3. Verify the JWT contains the proper claims

  4. Finally, verify the user details are correct and that the account is still active

If the token passes the above checks and your user's role is authorized (see Authorization) to perform the query or mutation, you will receive a 200 OK response with your requested data.

If the token is not accepted, the authorization webhook will return a 401 Unauthorized response with an error like this:

{
  "errors": [
    {
      "extensions": {
        "path": "$",
        "code": "access-denied"
      },
      "message": "Authentication hook unauthorized this request"
    }
  ]
}

Any unauthorized request will be treated as having 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 user is the Login action.

Authentication & Authorization Flow

This is a MermaidJS diagram showing the general flow for authentication and authorization:

Last updated