Authentication
OryxOS ships with an opt-in HTTP Basic Auth for the management console (/admin/**). It is disabled by default — the core phase assumes a trusted internal network. When enabled, access to the admin console requires an account; the REST API (/api/v1/**) is not affected.
Basic Auth is suited to internal networks fronted by HTTPS. For internet-facing deployments, terminate TLS at a reverse proxy and restrict network exposure; this minimal auth is a first line, not a perimeter.
How it works
- Scope: only
/admin/**is protected. Machine-to-machine auth for/api/v1/**is handled by the separate REST API Key switch — the two toggles are independent. - Accounts: stored in the
web_usersSQLite table. Passwords are BCrypt-hashed (with a{bcrypt}prefix via Spring'sDelegatingPasswordEncoder) — never stored in plaintext, never written to config, logs, or git history. - Realtime: account changes take effect immediately. Each request re-reads the database — no in-process cache, no server restart needed for a new account to work.
- Startup guard: if you enable auth but no enabled account exists, startup is blocked with a clear error pointing at
oryxos user add.
Configuration
Auth is controlled under oryxos.web.auth in application.yml (the in-jar defaults, overridable via config/application.yml):
oryxos:
web:
auth:
enabled: false # default off — trusted internal network
realm: "OryxOS" # Basic Auth realm string in the WWW-Authenticate header| Property | Default | Description |
|---|---|---|
oryxos.web.auth.enabled | false | Master switch. false = no auth (current behavior). true = /admin/** requires Basic Auth. |
oryxos.web.auth.realm | OryxOS | Realm value sent back in the WWW-Authenticate: Basic realm="..." challenge. |
There is no exclude-paths setting — the filter is scoped to /admin/** only, so /api/v1/** (and /api/v1/health) is naturally exempt.
Quick start
Enable auth in
config/application.yml:yamloryxos: web: auth: enabled: trueCreate the first admin account (startup is blocked until at least one enabled account exists):
bashoryxos user add admin # Password (>= 8 chars): ******** # Confirm: ******** # Created user 'admin'Start the server:
bashoryxos serveOpen the console at
http://localhost:8080/admin/— the browser prompts for credentials. Enter the account you just created.
Verifying it works
# No credentials → 401 + WWW-Authenticate challenge
curl -i http://localhost:8080/admin/
# Correct credentials → 200
curl -u admin:<password> http://localhost:8080/admin/
# REST API stays open (not protected by Basic Auth)
curl http://localhost:8080/api/v1/healthAccount management
See the oryxos user CLI reference for add, list, passwd, disable, and delete.
listnever prints passwords or hashes.disablekeeps the row but blocks login (returns 401).deleteremoves it permanently.- Passwords must be ≥ 8 characters; usernames must be ≤ 64 characters with no whitespace.
REST API Key authentication
Machine-to-machine auth for /api/v1/** (018-rest-api-key), toggled independently from console auth above:
oryxos:
web:
apikey:
enabled: true # default false — current behavior unchanged- Before enabling, create a key with
oryxos apikey add <name>— theoryx_...plaintext is shown exactly once; only its SHA-256 hash is stored. - Callers pick either header:
Authorization: Bearer <key>orX-API-Key: <key>— both are equivalent. - Exemptions:
/api/v1/health(probes),/api/v1/auth/*(console login subtree), and OPTIONS preflight;/admin/**is entirely unaffected. - Console interop: requests carrying a valid console session pass as authenticated — with both switches on, admin data pages keep working. Enabling only apikey logs a startup warning (the browser has neither session nor key).
- Lifecycle:
oryxos apikey listfor inventory (no plaintext);oryxos apikey revoke <name>takes effect on the next request and leaves other keys untouched. Keys never expire automatically; a lost key can only be revoked and reissued.
# No key → 401 (uniform response, no failure-reason leak)
curl -i http://localhost:8080/api/v1/profiles
# With key → 200
curl -H "Authorization: Bearer oryx_..." http://localhost:8080/api/v1/profiles
# Probes stay open
curl http://localhost:8080/api/v1/healthDesign notes
- No Spring Security full stack: only
spring-security-crypto(the password-hashing jar) is used — no filter chain, no autoconfig, no RBAC. TheBasicAuthFilteris a plainOncePerRequestFilterregistered via aFilterRegistrationBeanscoped to/admin/**. - What this is not: this is not SSO, RBAC, multi-tenancy, or session-based login with logout. Those are extension-phase capabilities. Password hashing with a delegating encoder leaves an upgrade path to Argon2 without migration.
- HTTP Basic has no logout — clearing credentials is browser-controlled. For richer session semantics, a future feature can add a login page backed by the same
web_userstable.