Authentication
AI Butler ships with four authentication building blocks that can be combined: password (bcrypt), TOTP, OIDC SSO, and FIDO2/WebAuthn (hardware security keys). All four are implemented in the codebase (see internal/auth/ and internal/webchat/auth/).
By default, auth is off — if you’re running on localhost for personal use, no auth is fine. The moment AI Butler is reachable from anywhere else (LAN, internet, Docker host), you want to turn it on.
RBAC Users
Section titled “RBAC Users”User management is split between RBAC (roles) and auth (passwords, TOTP, keys). The RBAC side lives in the CLI:
aibutler user create <username> <email> [role] # default role: useraibutler user listaibutler user assign <username> <role>Roles: admin, user, viewer, agent.
| Role | What they can do |
|---|---|
| admin | Full access — tools, channels, memory, config |
| user | Read + write + execute tools, read config |
| viewer | Read-only across tools, channels, memory |
| agent | Execute tools only, write channels only, read memory (for agent-to-agent peers) |
Example:
aibutler user create alice alice@example.com useraibutler user assign alice adminaibutler user listPassword Auth
Section titled “Password Auth”The webchat authenticator (internal/webchat/auth/auth.go) uses bcrypt for password hashing and supports optional TOTP layered on top. Password setup and reset flows live on the webchat login page — not the CLI — because that’s where most users will interact with them.
The first admin you create via aibutler user create is prompted to set a password on first webchat login.
TOTP (Time-Based One-Time Password)
Section titled “TOTP (Time-Based One-Time Password)”RFC 6238 compatible — works with Google Authenticator, Authy, 1Password, Bitwarden, Aegis. Codes rotate every 30 seconds.
TOTP is enrolled per-user via the webchat settings page. The secret is stored in the users database and verified on every login. When configured, TOTP is checked after the password — so a leaked password alone isn’t enough.
OIDC SSO
Section titled “OIDC SSO”AI Butler implements OIDC via internal/auth/oidc. Point it at your identity provider (Auth0, Okta, Google Workspace, Azure AD, Keycloak, Authentik, ZITADEL, Authelia) and map OIDC groups to AI Butler roles.
Client credentials live in the vault:
aibutler vault set oidc_client_id aibutleraibutler vault set oidc_client_secret YOUR_SECRETOIDC endpoint URLs and role mapping go in config.yaml. See Configuration Reference for the full field set.
FIDO2 / WebAuthn
Section titled “FIDO2 / WebAuthn”Hardware security keys (YubiKey, SoloKey, Nitrokey, Titan, Apple Touch ID, Windows Hello) — phishing-resistant, no password needed after initial enrollment. Implemented in internal/auth/webauthn.
Enrollment is per-user via the webchat settings page — click “Register Security Key” and tap your key. Login is then a single tap (no password).
WebAuthn credentials are bound to the rp_id — you cannot move them to a different domain. If you change domains, users must re-enroll.
Stacking Auth Methods
Section titled “Stacking Auth Methods”You can layer methods:
- Password + TOTP — classic 2FA. Something you know + something you have.
- WebAuthn only — passwordless hardware key login.
- OIDC — delegate everything to your identity provider.
Configure in config.yaml — see Configuration Reference.
Vault-Managed Credentials
Section titled “Vault-Managed Credentials”Anything secret lives in the vault, not in config files:
aibutler vault set <key> <value> # store a credentialaibutler vault get <key> # retrieve oneaibutler vault list # list keys (not values)aibutler vault delete <key> # removeThe aibutler auth command is a convenience alias for managing vault entries:
aibutler auth list # same as vault listaibutler auth status # vault health checkaibutler auth revoke <service> # delete a credentialTroubleshooting
Section titled “Troubleshooting”TOTP code rejected but you’re sure it’s right? Check server clock skew. TOTP requires the server and device to be within ~30 seconds of each other. Run timedatectl or chronyc tracking to verify NTP is working.
OIDC login returns “unknown issuer.” The issuer URL in your config must exactly match the iss claim in the ID token. Common mistakes: trailing slash, http vs https, /realms/<name> missing on Keycloak.
WebAuthn key not working after moving domains. WebAuthn credentials are bound to rp_id — re-enroll on the new host.