Users

Users are stored in the file config/server-users.jsonl file. The JSONL format means one json per line. When the server starts always checks if there are any users configured. If the user file is empty, the root user is created with a password the user must enter in the console where the server is starting. Example:

+--------------------------------------------------------------------+
|                WARNING: FIRST RUN CONFIGURATION                    |
+--------------------------------------------------------------------+
| This is the first time the server is running. Please type a        |
| password of your choice for the 'root' user or leave it blank      |
| to auto-generate it.                                               |
|                                                                    |
| To avoid this message set the environment variable or JVM          |
| setting `arcadedb.server.rootPassword` to the root password to use.|
+--------------------------------------------------------------------+

Root password [BLANK=auto generate it]: ***********
Please type the root password for confirmation (copy and paste will not work): ***********

Example of config/server-users.jsonl file:

{"name":"root","password":"PBKDF2WithHmacSHA256$65536$hcv0joKV/o/q+KOVmcwNUqhEq1w2/j8OVnEkkVjzkeg=$2q2u4rjUlJjgoKBX9sG0rV0bOh6aHo+RhHsOkXneGkM=","databases":{"*":["admin"]}}

In the users file the following information are stored per user:

  • Name, mandatory

  • Password. It is always saved hashed by using the algorithm PBKDF2 with a configurable salt (default = 32). The password is mandatory for all the users, but root. In the case root has no password, then ArcadeDB server asks to insert a password at startup (see above).

  • Databases, as the map database name and set of groups for that database. "*" is a special wildcard and means any. The configuration "databases":{"*":["admin"]} means use the "admin" group for any database.

admin-user

ArcadeDB allows each user to belong to zero or multiple groups. If no groups are defined, the default setting for the group * are used.

The following configuration defines "Jay" user to belong to "BlogWriters" in "Blog" database and "Editors" in the "Library" database:

{
  "databases": {
    "Blog": ["BlogWriters"],
    "Library": ["Editors"]
  }
}
jay-user

The declaration above implicitly assigns Jay to the default group for any other database configured. The default configuration for the default group is no access, where the user cannot read or write in the database.

Via Console

Alternatively, users can be created via the console, see Create User Console Command and Server Command.

Via Cypher

Users can also be managed using Cypher commands when running in server mode:

SHOW USERS
CREATE USER bob SET PASSWORD 'SecurePass123!'
ALTER USER bob SET PASSWORD 'NewPass456!'
DROP USER bob

See Cypher User Management for the full reference.

Password hash format

The recommended way to create or update a user’s password is through the HTTP API (POST /api/v1/server/users), the Console (CREATE USER), or Cypher (CREATE USER …​ SET PASSWORD …​). All three paths produce a correctly-formatted hash for you. Hand-editing config/server-users.jsonl is supported but error-prone; the rest of this section only matters if you are generating the hash yourself (for example from a provisioning script).

Each password is stored as a single string with four dollar-separated fields:

<algorithm>$<iterations>$<salt-base64>$<derived-key-base64>

Example:

PBKDF2WithHmacSHA256$65536$hcv0joKV/o/q+KOVmcwNUqhEq1w2/j8OVnEkkVjzkeg=$2q2u4rjUlJjgoKBX9sG0rV0bOh6aHo+RhHsOkXneGkM=

Field meaning:

Field Description

algorithm

Default PBKDF2WithHmacSHA256. Configured by arcadedb.server.securityAlgorithm.

iterations

Default 65536. Configured by arcadedb.server.saltIterations.

salt-base64

32 random bytes, Base64-encoded. See the note below for the subtle detail.

derived-key-base64

The 256-bit (32-byte) PBKDF2 output, Base64-encoded.

When verifying a password, the server feeds PBKDF2 the UTF-8 bytes of the Base64 salt string, not the raw 32 salt bytes. In other words, the text that appears between the second and third $ characters is taken verbatim and hashed with the user-supplied password. Any external tool that generates this hash must do the same, otherwise the stored hash will never match at login time and the user will be rejected with 403 User/Password not valid.

This is an implementation detail of the current storage format, preserved for compatibility with existing user files. It is not a security weakness, only a thing to be aware of when generating hashes outside the server.

The following Python snippet produces a hash that the server accepts:

import base64, hashlib, secrets

def hash_password(plaintext: str, iterations: int = 65536) -> str:
    raw = secrets.token_bytes(32)
    salt_b64 = base64.b64encode(raw).decode("ascii")
    derived = hashlib.pbkdf2_hmac(
        "sha256",
        plaintext.encode("utf-8"),
        salt_b64.encode("utf-8"),   # the Base64 string, NOT the raw bytes
        iterations,
        dklen=32,
    )
    derived_b64 = base64.b64encode(derived).decode("ascii")
    return f"PBKDF2WithHmacSHA256${iterations}${salt_b64}${derived_b64}"