Auth & RBAC
Three credential types reach the API — JWT bearer tokens, API keys, and short-lived WebSocket tickets. Three built-in roles — admin, operator, and viewer — cover most deployments, and custom roles with arbitrary subsets of the 37 granular permissions are supported. Local accounts use bcrypt; OAuth / OIDC providers federate the rest.
Local users
Local users live in SQLite with bcrypt-hashed passwords. Create them via the UI (Users → Add user) or the API:
curl -X POST https://aifw.local/api/v1/auth/users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "alice",
"password": "correct horse battery staple",
"email": "alice@example.com",
"role": "operator"
}'
Login returns a JWT plus a refresh token:
curl -X POST https://aifw.local/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "..."}'
TOTP 2FA
Each user can enrol a TOTP authenticator (Google Authenticator, Authy, 1Password, Bitwarden, …).
POST /api/v1/auth/totp/setup— returns the otpauth URI and QR-code data.- User scans, enters the 6-digit code into
POST /api/v1/auth/totp/verify. - Recovery codes are issued in the same response — store them somewhere offline.
When 2FA is enabled, login becomes a two-step flow:
# 1) Username + password — returns a TOTP challenge token
curl -X POST https://aifw.local/api/v1/auth/login \
-d '{"username": "alice", "password": "..."}'
# 2) Submit the 6-digit code to complete login
curl -X POST https://aifw.local/api/v1/auth/totp/login \
-d '{"challenge": "<token>", "code": "123456"}'
Disable from POST /api/v1/auth/totp/disable (requires a fresh password challenge).
OAuth / SSO
Three provider types are built in:
| Provider | provider_type |
Notes |
|---|---|---|
google |
Pre-configured auth + token URLs | |
| GitHub | github |
Pre-configured auth + token URLs |
| Generic OIDC | oidc |
Supply your own auth / token / userinfo URLs (Okta, Auth0, Keycloak, Azure AD, …) |
Add a provider:
curl -X POST https://aifw.local/api/v1/auth/oauth/providers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Google Workspace",
"provider_type": "google",
"client_id": "...apps.googleusercontent.com",
"client_secret": "...",
"scopes": "openid email profile",
"enabled": true
}'
Redirect URI to register with the provider:
https://aifw.local/api/v1/auth/oauth/{provider}/callback
Login flow uses /api/v1/auth/oauth/{provider}/authorize → provider consent → callback → AiFw mints a JWT for the matched (or auto-provisioned) local user.
API keys
API keys carry an explicit permission set independent of any user role. Use them for scripts, CI, monitoring, and integrations.
curl -X POST https://aifw.local/api/v1/auth/api-keys \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "metrics scraper",
"permissions": ["dashboard:view", "connections:view"],
"expires_at": "2027-01-01T00:00:00Z"
}'
Authenticate by sending the key as a bearer-style header:
Authorization: ApiKey <key>
Rotate by creating a new key and revoking the old one. Keys are listed by name + creation date; the secret is shown exactly once on creation.
WebSocket auth
Browsers can’t set custom headers on WebSocket or EventSource connections, so AiFw issues short-lived single-use tickets bound to the authenticated user:
# Issue a ticket — requires a normal Bearer JWT
curl -X POST https://aifw.local/api/v1/auth/ws-ticket \
-H "Authorization: Bearer $TOKEN"
# => { "ticket": "<opaque hex>" }
// Open the socket within 30 seconds
const ws = new WebSocket(`wss://aifw.local/ws?ticket=${ticket}`);
Tickets are 256 bits of entropy, single-use, and expire in 30 seconds. They live only in process memory — on restart everything reconnects anyway. See aifw-api/src/auth/ws_ticket.rs.
RBAC
Built-in roles
- admin — every permission. Full read + write + system control.
- operator — everything except
users:write,settings:write,updates:install,system:reboot, andha:manage. Day-to-day rule / NAT / VPN editing without account or platform-level changes. - viewer — read-only. All
*:readand*:viewpermissions exceptusers:read,settings:read, andbackup:read(those leak too much).
Custom roles are arbitrary subsets of the permission set below. Create with POST /api/v1/auth/roles.
Permission catalogue (37 permissions)
The canonical list lives in aifw-common/src/permission.rs. Permissions are stored as a 64-bit bitmask in the JWT claims for cheap server-side checks.
Dashboard & observability
| Permission | Description |
|---|---|
dashboard:view |
View the main dashboard widgets and overview |
connections:view |
View the live connection / state table |
logs:view |
View pf logs, audit logs, and system logs |
Filtering & NAT
| Permission | Description |
|---|---|
rules:read |
List firewall rules |
rules:write |
Create, update, delete, reorder firewall rules |
nat:read |
List NAT rules (port-forward, redirect, outbound) |
nat:write |
Manage NAT rules |
aliases:read |
List aliases |
aliases:write |
Manage aliases (address / network / port bags) |
VPN, Geo-IP, IDS
| Permission | Description |
|---|---|
vpn:read |
List WireGuard tunnels, peers, IPsec SAs |
vpn:write |
Manage VPN configuration |
geoip:read |
List geo-IP rules and country bans |
geoip:write |
Manage geo-IP rules; refresh GeoLite2 data |
ids:read |
View IDS / IPS alerts, rules, suppressions |
ids:write |
Change IDS mode, manage rulesets and suppressions |
Network services
| Permission | Description |
|---|---|
dns:read |
View DNS resolver / forwarder configuration |
dns:write |
Manage DNS forwarders, blocklists, overrides |
dhcp:read |
View DHCP leases and scopes |
dhcp:write |
Manage DHCP scopes, static reservations, options |
interfaces:read |
View interface configuration and status |
interfaces:write |
Configure interfaces, IP addressing, VLANs |
Multi-WAN & reverse proxy
| Permission | Description |
|---|---|
multiwan:read |
View multi-WAN instances, gateways, groups, policies |
multiwan:write |
Manage multi-WAN policy, SLA, leak detection |
proxy:read |
View reverse proxy routers, services, middlewares |
proxy:write |
Manage reverse proxy + ACME / TLS configuration |
Identity & settings
| Permission | Description |
|---|---|
users:read |
List users, roles, and audit log |
users:write |
Create / update / delete users, roles, API keys |
settings:read |
Read system settings (TLS, time, OAuth, …) |
settings:write |
Modify system settings, OAuth providers, AI config |
Plugins
| Permission | Description |
|---|---|
plugins:read |
List installed plugins and their status |
plugins:write |
Install, enable, disable, remove plugins |
Updates, backup, system
| Permission | Description |
|---|---|
updates:read |
Check for and view available system updates |
updates:install |
Apply system updates / firmware |
backup:read |
Read configuration history and backups |
backup:write |
Create, restore, import / export configuration |
system:reboot |
Reboot or shutdown the appliance |
ha:manage |
Manage high-availability cluster (demote, snapshot, failover) |
API endpoints
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/auth/login |
Username + password login |
POST |
/api/v1/auth/totp/login |
Submit TOTP code after /login |
POST |
/api/v1/auth/refresh |
Exchange a refresh token for a new JWT |
POST |
/api/v1/auth/logout |
Revoke the current session |
POST |
/api/v1/auth/register |
Self-service registration (if enabled) |
GET |
/api/v1/auth/me |
Current user identity, role, perms |
POST |
/api/v1/auth/totp/setup |
Begin TOTP enrolment |
POST |
/api/v1/auth/totp/verify |
Verify and activate TOTP |
POST |
/api/v1/auth/totp/disable |
Disable TOTP |
POST |
/api/v1/auth/ws-ticket |
Mint a 30-second WebSocket ticket |
GET / POST |
/api/v1/auth/users |
List / create users |
GET / PUT / DELETE |
/api/v1/auth/users/{id} |
Manage one user |
GET |
/api/v1/auth/audit |
User audit log |
GET / POST |
/api/v1/auth/roles |
List / create custom roles |
PUT / DELETE |
/api/v1/auth/roles/{id} |
Update or remove a role |
GET |
/api/v1/auth/permissions |
Enumerate every permission |
POST |
/api/v1/auth/api-keys |
Create an API key |
GET / PUT |
/api/v1/auth/settings |
Auth settings (lockout, refresh TTL, …) |
GET / POST |
/api/v1/auth/oauth/providers |
List / create OAuth providers |
PUT / DELETE |
/api/v1/auth/oauth/providers/{id} |
Manage one provider |
GET |
/api/v1/auth/oauth/{provider}/authorize |
Begin OAuth login |
GET |
/api/v1/auth/oauth/{provider}/callback |
OAuth provider callback |