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.
User configuration
Section titled “User configuration”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 explicitfalsedenies 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 with403. A numeric string ("1") is accepted. A value above3is rejected with theAuthentication failedlog 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 byset-userandreset-passwordfrom the plainpassword; never accepted from a request and never returned byget-user.created- number, Unix time when the user was created byset-user.firstrun-trueon theadminuser that Astra creates at the first start when the configuration has no users (loginadmin, passwordadmin, type1).
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 thetokenquery parameter of the play request:http://server:8000/play/a001/index.m3u8?token=secret.ip- string, one IPv4 or IPv6 address. A request without atokenparameter 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.0or 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.0or 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.
Get user
Section titled “Get user”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 withoutcipher.
An unknown login is answered 200 as well:
{ "get-user": "er", "error": "user not found"}Create or update user
Section titled “Create or update user”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. Onlycipheris carried over from the stored record, and only when nopasswordis 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 intocipherand never stored. A new user withoutpasswordhas nocipherand 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:
createdis set to the current Unix time when the login did not exist before.- When
passwordis 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,cipherincluded (see Events).- The configuration is saved.
Example:
curl -X POST --user login -d @- http://server:8000/control/ <<END{ "cmd": "set-user", "id": "new-admin", "user": { "enable": true, "type": 1, "password": "secret" }}ENDRemove user
Section titled “Remove user”Request: POST /control/. Control only.
{ "cmd": "set-user", "id": "login", "user": { "remove": true }}id- string, required. The login. Removing an unknown login is answeredokas 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.
Change own password
Section titled “Change own password”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.typeis always stored as2, also when the request sends another value;cipheris carried over when nopasswordis sent. A request withoutuseris 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-idis not the authenticated login, oruser.removeis 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.
Toggle user
Section titled “Toggle user”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:
curl \ -X POST \ --user login \ -d '{"cmd":"toggle-user", "id":"login"}' \ http://server:8000/control/Reset password
Section titled “Reset password”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 not127.0.0.1(this includes the IPv6 loopback::1).405- the method is notPOST, the body is empty, the body is not JSON, orloginorpasswordis 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.
astra reset-password Port: 8000 Login: adminPassword: new-secretRequest complete