Skip to content

Users API

Users are the accounts of the web interface and of the built-in authorization of HTTP MPEG-TS and HLS outputs. One users table serves both: the type of a user decides whether it may call the API (see Roles), the streaming fields decide whether it may play channels. Every command on this page is served on the command entry point POST {control_path}control/ only, except reset-password, which has its own path.

A user is stored under its login in the users object of the configuration:

{
"enable": true,
"type": 1,
"cipher": "3fed7a346e430ea4c2aa10250928f4de",
"created": 1758240000,
"token": "secret",
"ip": "192.168.1.10",
"expire": 0,
"conlimit": 0,
"packages": ["Sport"]
}

Web interface and API fields:

  • enable - boolean. For the web interface and the API only an explicit false denies the login; an absent value allows it. For streaming an absent value denies (see below).
  • type - number. 1 - control: every API method. 2 - observer: the read-only subset. 3 - streaming user: the credentials are rejected by the API with 403. A numeric string ("1") is accepted. A value above 3 is rejected with the Authentication failed log line; any other value (absent, non-numeric) is rejected silently.
  • cipher - string, the password hash: hex(md5(md5(md5(login + password)))), the inner digests chained as raw 16-byte binaries. Written by set-user and reset-password from the plain password; never accepted from a request and never returned by get-user.
  • created - number, Unix time when the user was created by set-user.
  • firstrun - true on the admin user that Astra creates at the first start when the configuration has no users (login admin, password admin, type 1).

Streaming fields, read by the users stage of the HTTP authorization chain; every other field of the record is stored and returned unchanged but not used:

  • token - string. The client is identified by the token query parameter of the play request: http://server:8000/play/a001/index.m3u8?token=secret.
  • ip - string, one IPv4 or IPv6 address. A request without a token parameter is identified by its source address instead. An unparsable value is skipped with an error in the log; the user keeps token access.
  • expire - number, Unix time after which playback is denied. 0 or absent - never expires.
  • conlimit - number, the maximum number of simultaneous streaming sessions of the user. When a new session exceeds it the oldest session of the user is closed. 0 or absent - unlimited.
  • packages - list of category names the user is restricted to; an empty or absent list allows every channel (see Categories API).
  • interface.arrange - the category the web interface of this user arranges by (see Categories API).

For streaming, enable must be true: a user without an enable value is denied playback, while the same user may still log in to the web interface.

Request: POST /control/. Control only.

{
"cmd": "get-user",
"id": "login"
}
  • id - string, required. The login.

Response:

{
"get-user": "ok",
"user": {
"enable": true,
"type": 1,
"created": 1758240000
}
}
  • user - the stored record without cipher.

An unknown login is answered 200 as well:

{
"get-user": "er",
"error": "user not found"
}

Request: POST /control/. Control only.

{
"cmd": "set-user",
"id": "login",
"user": {
"enable": true,
"type": 1,
"password": "secret"
}
}
  • id - string, required. The login; creates the user when it does not exist.
  • user - object, required. The new record, see User configuration. The stored record is replaced by this object: a field that is not sent is dropped. Only cipher is carried over from the stored record, and only when no password is sent.

A request without user or without id is not answered: the handler fails and the Astra process aborts. Always send both.

  • user.password - string, optional. The plain password; it is hashed into cipher and never stored. A new user without password has no cipher and cannot log in until one is set.
  • user.type - number or numeric string, optional. Converted to a number; a non-numeric string is dropped.

No field of user is validated beyond that.

Response:

{ "set-user": "ok" }

Side effects:

  • created is set to the current Unix time when the login did not exist before.
  • When password is sent, every session of the login is revoked: web login sessions, unredeemed WebSocket tokens and running streaming sessions.
  • The authorization chain is rebuilt with the new users table.
  • {"scope": "set-user", "id": "login", "user": {...}} is pushed over the WebSocket with the record as stored, cipher included (see Events).
  • The configuration is saved.

Example:

Terminal window
curl -X POST --user login -d @- http://server:8000/control/ <<END
{
"cmd": "set-user",
"id": "new-admin",
"user": {
"enable": true,
"type": 1,
"password": "secret"
}
}
END

Request: POST /control/. Control only.

{
"cmd": "set-user",
"id": "login",
"user": {
"remove": true
}
}
  • id - string, required. The login. Removing an unknown login is answered ok as well.

Response:

{ "set-user": "ok" }

Side effects: every session of the login is revoked (web login sessions, WebSocket tokens, streaming sessions), the authorization chain is rebuilt, {"scope": "set-user", "id": "login", "user": {"remove": true}} is pushed over the WebSocket, the configuration is saved.

Request: POST /control/. Observer only: this is the set-user variant served to a user of type 2; it lets the observer change its own record and nothing else.

{
"cmd": "set-user",
"id": "observer",
"user": {
"enable": true,
"password": "new-secret"
}
}
  • id - string, required. Must be the authenticated login.
  • user - object, required. Replaces the stored record the same way as for control: send the complete record, a field that is not sent is dropped. type is always stored as 2, also when the request sends another value; cipher is carried over when no password is sent. A request without user is not answered: the handler fails and the Astra process aborts.
  • user.password - string, optional. The new password.

Response:

{ "set-user": "ok" }

Error replies, sent as an HTML error page:

  • 403 - id is not the authenticated login, or user.remove is set.
  • 404 - the authenticated login is no longer in the users table.

Side effects are the same as for control: a password change revokes every session of the login, including the one this request was authenticated with; the authorization chain is rebuilt, the set-user event is pushed, the configuration is saved.

Request: POST /control/. Control only.

{
"cmd": "toggle-user",
"id": "login"
}
  • id - string, required. The login.

Flips enable: true becomes false, false or absent becomes true.

Response:

{ "toggle-user": "ok" }

An unknown login is answered 200:

{
"toggle-user": "er",
"error": "user not found"
}

Side effects: when the user is now disabled, every session of the login is revoked (web login sessions, WebSocket tokens, streaming sessions). The authorization chain is rebuilt, {"scope": "set-user", "id": "login", "user": {...}} is pushed with the flipped record, the configuration is saved.

Example:

Terminal window
curl \
-X POST \
--user login \
-d '{"cmd":"toggle-user", "id":"login"}' \
http://server:8000/control/

Request: POST /control/reset-password/. No role: the request is not authenticated - an Authorization header is ignored; instead it is accepted only from the local machine: the peer address of the connection must be exactly 127.0.0.1. The path is always at the root of the control server, also when control_path is set, and the trailing slash is part of it: /control/reset-password without the slash is handled as a control API request and answered 403 without credentials. No Content-Type header is required.

{
"login": "admin",
"password": "new-secret"
}
  • login - string, required. The login; the user may be disabled or of any type.
  • password - string, required. The new plain password.

Response:

{ "reset-password": "ok" }

Error replies, sent as an HTML error page:

  • 403 - the peer address is not 127.0.0.1 (this includes the IPv6 loopback ::1).
  • 405 - the method is not POST, the body is empty, the body is not JSON, or login or password is missing.
  • 404 - unknown login.

Side effects: cipher is replaced, every session of the login is revoked (web login sessions, WebSocket tokens, streaming sessions), the API users registry is updated, the configuration is saved, and reset password for <login> is written to the log as a warning. No WebSocket event is pushed.

The astra reset-password command line tool calls this method: it asks for the control port, the login and the new password on the console and posts them to http://127.0.0.1:<port>/control/reset-password/. Astra must be running. The tool prints Request complete on 200, Request failed, code <status> on any other status, and Request failed: <error> when no connection could be made.

Terminal window
astra reset-password
Port: 8000
Login: admin
Password: new-secret
Request complete