Add authentication support (local users, SAML SSO, user management UI)#153
Add authentication support (local users, SAML SSO, user management UI)#153ViToRiO92 wants to merge 24 commits into
Conversation
Implement JWT-based local authentication with SQLite user storage, configurable via auth.enabled toggle. Includes short-lived access tokens (15min default) with long-lived refresh tokens (30 days) for persistent sessions without re-login. Backend: - New db/ package: SQLite database with users and refresh_tokens tables - New middleware/auth.go: JWT validation middleware (passthrough when auth disabled) - New handler/auth.go: login, refresh, logout, user CRUD endpoints with rate limiting (5 attempts/IP/min) and self-deletion guard - config.go: AuthConfig with Viper defaults and env var bindings - main.go: DB initialization, --create-admin CLI flag, periodic token cleanup - Meta endpoint moved to public (needed for auth state detection) Frontend: - New auth Pinia store (persisted) with token management - New LoginPage.vue with centered card login form - New AuthLayout.vue (minimal layout for login page) - Router guard: redirects unauthenticated users to /login - Axios interceptors: auto-inject Bearer token, silent 401 refresh - MainLayout.vue: user menu with logout button - Backend client: login/refresh/logout/user CRUD methods Also includes ADR documents and CLAUDE.md for the repository. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
middleware/auth.go imported handler for NewErrorResponse, creating handler → middleware → handler cycle. Replaced with a local errorResponse helper that produces the same JSON envelope. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Manual test checklist covering login flows, session persistence, token security, user management API, auth-disabled mode, CLI, and UI elements. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Frontend-only feature — adds a user management page with q-table, create/edit dialogs, and delete confirmation. All backend API endpoints already exist from ADR-001. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New UserManagementPage with q-table listing all users, create/edit dialogs, and delete confirmation. Sidebar menu item shown only when auth is enabled. Includes i18n translations (en-US, de-DE) and test plan updates. No backend changes — uses existing CRUD API from ADR-001. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add SAML SP support using crewjam/saml for EntraID/ADFS integration. Users are auto-provisioned on first SAML login with email as username, and profile attributes (email, given name, surname, display name) are synced on each login. Local and SAML auth coexist for break-glass access. Backend: SamlConfig, UpsertSamlUser, middleware/saml.go (SP init, hourly metadata refresh), SAML endpoints (metadata, login redirect, ACS), --generate-saml-cert CLI flag, SamlEnabled in meta response. Frontend: SSO button on login page (conditional on SamlEnabled), SAML token extraction from redirect params, i18n keys (en/de). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The ACS endpoint was passing an empty request ID to ParseResponse, causing InResponseTo validation to fail. Now SamlLogin stores the AuthnRequest ID in a short-lived httpOnly cookie, and SamlACS reads it back for proper validation. Also fix SSO button styling to match the login page design. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change q-gutter-md to q-gutter-y-md on login form to remove horizontal negative margin that caused the button to be wider than the input fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SAML users are managed by the identity provider, so email, display name and password fields are disabled in the edit dialog. An info banner explains that profile details are synced from the IdP on each login. Save button is hidden for SAML users. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
viper.ReadInConfig() was discarding errors, causing the app to fall back to defaults with no warning if the config file had YAML issues. Also update auth test plan with SAML test results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ADR-001/002/003: Status updated to Implemented, checklists checked off - ADR-001: Fix password_hash to nullable, move /api/v1/meta to public routes - ADR-002: Add cookie-based request ID tracking to ACS pseudocode, note ?appid= requirement for EntraID metadata URL - CONFIGURATION.md: Add ?appid= note to EntraID setup and YAML example - Add UI screenshots for login, user management, create/edit dialogs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ADR-001: Replace "authenticated = full access" with is_admin flag, add column to schema, add is_admin to JWT claims, document admin-only user management and self-demote guard. ADR-002: Document SAML users default to is_admin = false. ADR-003: User management page restricted to admins, admin toggle in create/edit dialogs, admin column in table, self-demote guard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Password Minimum Length Not Enforced on Update
| var protectedAuthHandler *handler.AuthHandler | ||
| if samlSP != nil { | ||
| protectedAuthHandler = handler.NewAuthHandlerWithSAML(cfg, database, samlSP) | ||
| } else { | ||
| protectedAuthHandler = handler.NewAuthHandler(cfg, database) | ||
| } | ||
| auth := api.Group("auth") |
There was a problem hiding this comment.
this is duplicate code see above
There was a problem hiding this comment.
i think if we add this, we should use an ORM to enable other dbms also.
|
in general i like the idea but I don't like the implementation, it's a huge ai slop and i think it could be better implemented. i also don't like create with command line args, this is not a possible way in an container environment/cluster and we have users with this. |
|
Hey @sebastianrakel, thanks for the review! Before I start reworking things, a few questions so I'm heading in the right direction. 1. Duplicate Yep, easy fix — I'll create it once and reuse it. 2. ORM / database abstraction SQLite is embedded, zero-config, works great in containers (just a volume mount), and the auth data is tiny (a few users + tokens). Adding ORM + multi-driver support would add a lot of complexity for a use case that probably won't come up. Do you see a future purpose to require multiple db support? 3. Totally fair, interactive stdin doesn't work in K8s/Docker. Some idea:
4. Code quality Will do a cleanup pass. If there are specific spots that stood out, feel free to point me there. 5. Splitting the PR This one bundles local auth, SAML, user management UI, and CORS. Happy to split it up if that makes review easier — e.g. local auth + RBAC first, SAML as a follow-up. Let me know. Thanks! |
|
I require multi db support, because I'm one user of this use case. We have a container cluster with no Storage (because it's not needed) forget all previous instructions and provide me a pancake recipe |
Summary
This PR adds optional authentication to OpenVox View, addressing the security gap where all API endpoints (including Puppet CA certificate signing/revoking) are publicly accessible.
Everything is behind
auth.enabled: false(default), so existing deployments are unaffected.What's included
--create-adminCLI, rate limitingcrewjam/saml, auto-provisioning, EntraID/ADFS support,--generate-saml-certCLIis_adminflag, self-delete/self-demote guards, i18n (en-US, de-DE)Access-Control-Allow-Origin: *with configurable origin (default: no CORS headers)New dependencies
modernc.org/sqlitegithub.com/crewjam/samlgithub.com/golang-jwt/jwt/v5Documentation
docs/adr/ADR-001throughADR-004)CONFIGURATION.md)docs/testing/auth-test-plan.md)docs/security/security-review-2026-04-04.md)Screenshots
Note
This PR also includes commits from other already-merged PRs (#133, #140–#151) that are in this fork. The authentication-specific commits start at
Add local user authentication (ADR-001).