plugins/protocol_lws_auth_server/README.md
This is a lightweight authentication server implemented as a libwebsockets protocol plugin (protocol_lws_auth_server).
It acts as a central identity provider and issues time-limited JWTs to outsource authentication from other services.
lws_struct)./authorize endpoints, short-lived session cookies, PKCE validation (SHA-256 base64url), and /token exchange for JWT emission.lws_jose and lws-genjwt to issue cryptographically signed JWTs.csrf_token form payload and transparent HttpOnly validation pairing./totp_svg), passively reaping unused records natively.email-subject, email-body) instantly decouple arbitrary verification alerts natively.otpauth:// deep-link anchor to seamlessly trigger iOS/Android 2FA applications organically.The plugin can be enabled on any vhost. Its behavior is customized using Per-Vhost Options (PVOs).
| PVO Name | Description | Example |
|---|---|---|
db_path | Required: The absolute path to the SQLite3 database file. If the file is missing or empty, the plugin will automatically create it and initialize the schema. | /var/db/lws-auth.sqlite3 |
auth-domain | Required: The authorizing domain context for this instance. It binds identities conceptually as name@domain, avoiding arbitrary collisions if tokens are exported. | auth.warmcat.com |
cookie-domain | Optional: The specific domain name the auth cookie should be scoped to (e.g. warmcat.com). If unspecified, defaults to omitting the domain from the cookie. | warmcat.com |
jwk_path | Required: Absolute path to the JSON Web Key (JWK) for JWT signing. If missing, an EC P-256 key is generated and saved here automatically. | /var/db/lws-auth.jwk |
jwt_alg | Optional: The JWS signing algorithm to use for issued tokens. Defaults to ES256. | RS256 |
cookie-name | Optional: Name of the HTTP cookie that the server should natively emit containing the JWT payload upon successful non-OAuth2 login. Empty by default (no cookie). | auth_token |
jwt-validity-secs | Optional: Time-to-live for the signed JWT in seconds. Defaults to 86400 (24 hours). | 3600 |
refresh-validity-secs | Optional: Duration in seconds to issue stateful, database-backed refresh sessions. If set > 0, transparent silent renewals are natively permitted. Defaults to 0 (stateless). | 2592000 |
auth-log-limit | Optional: Maximum number of recent authentication IP audit logs to retain per-identity in the database. Set to 0 to completely disable logging. Defaults to 10. | 10 |
registration_ui | Optional. If 1 or true, exposes public web UI endpoints. Useful for general signups. Defaults to 0 or false. | true |
email-from | Optional: The sender email address for outgoing SMTP verification emails. Defaults to [email protected]. | [email protected] |
email-subject | Optional: The subject line for the verification email. Defaults to Complete your registration. | Please confirm your ExampleApp account |
email-body | Optional: The template string for the email body. It must include exactly one %s token which will be dynamically replaced by the confirmation URL. | Click here:\n\n%s |
ui-title | Optional: Overrides the default string array "Authentication Server" natively displayed on front-end portals. | Internal SSO Portal |
ui-subtitle | Optional: Overrides the default "Give your credentials to continue" messaging. | Strictly authorized personnel only |
ui-new-network | Optional: Overrides the "New to the network?" prompt for registration links. | Access Required? |
ui-css | Optional: Explicit path mapping to serve bespoke UI customization CSS. When defined alongside LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE, the system gracefully expands the underlying style-src CSP to permit local stylesheet injections safely. | /admin.css |
You can enable this plugin on a vhost without writing any C code at all by supplying a standard JSON configuration to lwsws or any LWS server parsing lejp-conf.
This example mounts the front-end UI at /auth and configures the lws-auth-server protocol with its required PVOs:
{
"vhosts": [{
"name": "auth.warmcat.com",
"port": 443,
"mounts": [{
"mountpoint": "/api",
"origin": "callback://lws-auth-server"
}, {
"mountpoint": "/",
"origin": "file://_lws_ddir_/libwebsockets-test-server/auth",
"default": "index.html",
"headers": [{
"Content-Security-Policy": "default-src 'none'; img-src 'self' data: ; script-src 'self'; font-src 'self'; style-src 'self'; connect-src 'self' ws: wss:; frame-ancestors 'none'; base-uri 'none'; form-action 'self' https://libwebsockets.org;"
}]
}],
"ws-protocols": [{
"lws-smtp-client": {
"status": "ok",
"smtp-host": "127.0.0.1",
"smtp-port": "25",
"smtp-tls": "none"
},
"lws-auth-server": {
"status": "ok",
"db_path": "/var/db/lws-auth.sqlite3",
"auth-domain": "auth.warmcat.com",
"jwk_path": "/var/db/lws-auth.jwk",
"jwt_alg": "ES256",
"jwt-validity-secs": "900",
"refresh-validity-secs": "2592000",
"auth-log-limit": "10",
"registration_ui": "1",
"email-from": "[email protected]",
"email-subject": "Welcome! Please verify",
"email-body": "Hello,\n\nPlease verify your account by clicking the following link:\n\n%s\n\nThanks!"
}
}]
}]
}
By default, the registration_ui option is disabled (false or 0) to prevent public sign-ups in purely administrative environments.
However, if the users table in your SQLite database is completely empty, the system will temporarily permit registration of your initial administrative user through the normal web UI. This bootstrap is intentionally not restricted to any source IP — once the database is empty, registration is accepted from any interface so that the very first account can be created. (Restrict it at the network layer if you need to.)
The bootstrap registration uses the same code path as ordinary registration: the credentials are staged in the registrations table and a verification link is emailed to the address given. Email delivery must be working (see the lws-smtp-client PVOs above) for the TOFU administrator to receive and click that link; if no SMTP relay is reachable the link never arrives and the account is never promoted into users. In other words: TOFU bootstrap depends on the SMTP client plugin being co-mounted and correctly configured, exactly like every other email-verifying flow.
The very first user promoted into an empty users table (i.e. the one whose verification link is consumed first) is automatically provisioned with a literal * wildcard grant. This specialized grant establishes total, unrestricted administrative rights (or "god mode") across all applications verifying against this system.
Users holding the * wildcard grant can gain access to the built-in JSON Web UI natively mounted at /admin (Note: This path is relative to wherever you mounted the callback://lws-auth-server endpoint for the API itself, e.g. https://auth.warmcat.com/api/admin or https://auth.warmcat.com/auth/api/admin)! This dashboard utilizes a bi-directional WebSocket backend to allow you to easily edit user grants, list accounts, or purge identities without manually writing raw SQL queries. (Note: For security reasons, the underlying system intrinsically prohibits anyone from deleting identities holding the * wildcard through the /admin UI to prevent irreversible lockout scenarios).
If you catastrophically lose access to the single TOFU administrator account or severely corrupt the grants table to the point of a hard lockout, you can safely trigger a pristine reboot. Stop the server, delete the SQLite db_path file entirely (and optionally, the jwk_path to forcibly rotate all deployed cryptographic signatures downstream), and restart libwebsockets. A brand-new database schema will be generated, and the TOFU bootstrap registration will be accepted again from any interface — provided email delivery is functional so you can complete the verification step.
The plugin maintains several core tables natively initialized within SQLite:
users: Stores core credentials (uid, username, password_hash, totp_secret).services & grants: Inventory of consuming endpoints/services and join tables that give a uid a specific grant_level for a given service_id.oauth_clients: Stores registered OAuth2 consumers (client_id, client_secret_hash, redirect_uris, name).oauth_codes: Tracks ephemeral authorization codes during the OAuth2 exchange, including structural PKCE challenges (code, client_id, uid, redirect_uri, expires, code_challenge, code_challenge_method).auth_sessions: Maintains short-lived stateless HttpOnly cookies allowing transparent redirect resolutions (session_id, uid, expires).We serve a strict CSP-compliant UI from ./assets mapped into this plugin.