User Authentication

Overview

Hydrolix authentication provides a centralized authentication system for your cluster. It works for all externally-available endpoints. It is enabled by default and covers:

  • Ingest API
  • Query API (including Clickhouse and HTTP)
  • Web UI
  • Miscellaneous services such as the transform validator, version, prometheus, and acme endpoints

Hydrolix ensures that one of these conditions is true for each request, or it denies access:

  • The request includes a valid 24-hour Bearer token
  • An auth_token cookie is sent in the request
  • The endpoint is the /login API method
  • In the case of the Web UI, the user is logged in

Users may be added, deleted, and managed using the Web UI or Config API.

📘

If you're upgrading from Hydrolix version 4.2 or earlier, set unified_auth: false in your hydrolixconfig.yaml file to re-enable the older, non-unified methods of authentication.

Using Authentication

Web UI

Visit your Hydrolix cluster's IP address via a web browser and you will be directed to the login page if you aren't already logged in.

API and Other Endpoints

Bearer Token

In this mechanism, the Bearer token is provided to the endpoint rather than a username and password. This token is valid for 24 hours, and can be thought of as a session token. This token authorizes access without the extra risk of sending rarely-changing usernames and passwords over the network for every request.

To retrieve the bearer token, use the login API endpoint. For example, using curl:

curl --request POST \
     --url https://hostname.company.net/config/v1/login \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
{
     "username": "[email protected]",
     "password": "secret"
}
'

The login API will return the following output:

{
  "uuid": "1111-2222-3333-4444-5555",
  "email": "[email protected]",
  "orgs": [
    {
      "uuid": "aaaa-bbbb-cccc-dddd",
      "name": "Hydrolix",
      "type": "singletenant"
    }
  ],
  "groups": [
    "org.asdf.Hydrolix.admin"
  ],
  "auth_token": {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXbzNLa21MbnhDNzVyaHVJQXR0RHhxak9LTlh4bURvWU5pTkVyeExueHhRIn0.eyJleHAiOjE2NjA0MDE4NjQsImlhdCI6MTY2MDMxNTQ2NCwianRpIjoiYmUzOTllMmItZjhkNC00MjY2LWI3OTYtZDdjN2NhZDhkNGU1IiwiaXNzIjoiaHR0cDovL2tleWNsb2FrOjgwODAvYXV0aC9yZWFsbXMvaHlkcm9saXgtdXNlcnMiLCJhdWQiOlsiY29uZmlnLWFwaSIsImFjY291bnQiXSwic3ViIjoiODM0NTc4M2YtYjE3Yi00ZTdhLTk3MDAtOTA5MzAxNmIyNWFmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29uZmlnLWFwaSIsInNlc3Npb25fc3RhdGUiOiJiZjY0ZTkwMy1iNmZjLTQ0NWEtYWU4Yi0wZDM1NzI1OGZkZGEiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMSJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oeWRyb2xpeC11c2VycyIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIGNvbmZpZy1hcGktc2VydmljZSBwcm9maWxlIiwic2lkIjoiYmY2NGU5MDMtYjZmYy00NDVhLWFlOGItMGQzNTcyNThmZGRhIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2VzQGh5ZHJvbGl4LmlvIiwiZW1haWwiOiJzZXJ2aWNlc0BoeWRyb2xpeC5pbyJ9.hR9Cv52CYVlG_FoSoGxvKjWXJXSWxxBMQJKP7EMbVxfpOZmQNmfaBPuBMO7NbGM12a7VPo8V_SQqxneJHPX4sxOiZ1DPePU1QPTrhh41-FkvyD6lQ9FEnAQGZFLFp0VKYiNbMIYnnM1dyfQAARwwcNq7wWQ_kZmzAz9QZMbdvtKzmGnlhsZkirBkz7aWQcnyuJQPcg6CZPa4p9nsP7qcLqMGY_b88v_VnBO13qM4u20NFvo2h8pef_tgtFupvZiUDMDjIFI_UTij6PLNJZFBYwmrxIMNrmJshtGIbMfRMFHKMVe6l7ruzwxCj-asdfasdfasdf",
    "expires_in": 86400,
    "token_type": "Bearer"
  }
}

👍

Pretty JSON

Note that the output from the above command can be made much more human-readable by piping it through a JSON utility such as jq.

Include the auth_token.access_token field value in your HTTP requests to authenticate with the token. Use a header named authorization with the value Bearer <TOKEN>. For example, to query the number of lines in your cluster's hydro.logs table:

curl --request POST \
  --url https://hostname.company.net/query/ \
  --header 'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXbzNLa21MbnhDNzVyaHVJQXR0RHhxak9LTlh4bURvWU5pTkVyeExueHhRIn0.eyJleHAiOjE2NjA0MDE4NjQsImlhdCI6MTY2MDMxNTQ2NCwianRpIjoiYmUzOTllMmItZjhkNC00MjY2LWI3OTYtZDdjN2NhZDhkNGU1IiwiaXNzIjoiaHR0cDovL2tleWNsb2FrOjgwODAvYXV0aC9yZWFsbXMvaHlkcm9saXgtdXNlcnMiLCJhdWQiOlsiY29uZmlnLWFwaSIsImFjY291bnQiXSwic3ViIjoiODM0NTc4M2YtYjE3Yi00ZTdhLTk3MDAtOTA5MzAxNmIyNWFmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29uZmlnLWFwaSIsInNlc3Npb25fc3RhdGUiOiJiZjY0ZTkwMy1iNmZjLTQ0NWEtYWU4Yi0wZDM1NzI1OGZkZGEiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMSJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1oeWRyb2xpeC11c2VycyIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIGNvbmZpZy1hcGktc2VydmljZSBwcm9maWxlIiwic2lkIjoiYmY2NGU5MDMtYjZmYy00NDVhLWFlOGItMGQzNTcyNThmZGRhIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2VzQGh5ZHJvbGl4LmlvIiwiZW1haWwiOiJzZXJ2aWNlc0BoeWRyb2xpeC5pbyJ9.hR9Cv52CYVlG_FoSoGxvKjWXJXSWxxBMQJKP7EMbVxfpOZmQNmfaBPuBMO7NbGM12a7VPo8V_SQqxneJHPX4sxOiZ1DPePU1QPTrhh41-FkvyD6lQ9FEnAQGZFLFp0VKYiNbMIYnnM1dyfQAARwwcNq7wWQ_kZmzAz9QZMbdvtKzmGnlhsZkirBkz7aWQcnyuJQPcg6CZPa4p9nsP7qcLqMGY_b88v_VnBO13qM4u20NFvo2h8pef_tgtFupvZiUDMDjIFI_UTij6PLNJZFBYwmrxIMNrmJshtGIbMfRMFHKMVe6l7ruzwxCj-asdfasdfasdf' \
  --data 'SELECT count() FROM hydro.logs'

If the token is invalid, the API will respond with a message like this:

{
    "error": "std::exception. Code: 1001, type: h::db::AclError, e.what() = <AclError invalid user token provided (Hydrolix v3.48.5 - Turbine aceb91e6)>, Stack trace (when copying this message, always include the lines below):\n\n (version 22.12.1.1)",
    "query": "select count() from hydro.logs"
}

🚧

Token Prefix

Don't forget the prefix Bearer.

HTTP Cookie

As of Hydrolix v4.12, an HTTP cookie may be used for authentication. This is normally used for web UI applications, but can be used by any client that supports cookies. Enable cookie authentication by including a cookie=true query string parameter to the request.

📘

Only for Config API

Currently, the Query API doesn't support cookies. This feature is coming soon, though!

Cookies are created with the following parameters:

Parameter NameValueDescription
HttpOnly(present)Cookie cannot be accessed through client-side JavaScript
Max-Age86400Seconds until the cookie expires (24 hours)
Path/Any path is accepted
Secure(present)Only HTTPS requests can contain cookies
SameSiteStrictHTTP client only sends cookie for requests from the same domain

The /v1/loginexample below uses cURL to store the authentication cookie received while logging in:

curl -v -X POST -H "Content-Type: application/json" \
  --cookie-jar my_cookies \
  https://$HDX_HOSTNAME/config/v1/login/\?cookie=true \
  -d "{
    \"username\":\"$HDX_USER\",
    \"password\":\"$HDX_PASSWORD\"
  }" | jq

The resulting my_cookies file will have a cookie named access_token in it.

Include this cookie in your HTTP requests to authenticate with the cookie. For example, in cURL, to query the dictionary layouts using the my_cookies file from above:

curl \               
  --url "https://$HDX_HOSTNAME/config/v1/dictionary_layouts?cookie=true" \
  --cookie my_cookies

Reporting

Full Authentication Audit Logging is available.

You can see reports of usage, including valid and invalid requests per token, in your Hydrolix cluster's Prometheus reporting.