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
PBKDF2with 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.
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"]
}
}
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 |
|---|---|
|
Default |
|
Default |
|
32 random bytes, Base64-encoded. See the note below for the subtle detail. |
|
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 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}"