fix: prevent admin escalation when AUTH_ENABLED=false

When auth was disabled, users could log out, reach the login page,
and authenticate with the default admin/admin credentials to gain
full admin privileges — defeating the purpose of AUTH_ENABLED=false.

Defense-in-depth fix across five layers:
- Skip ensureDefaultAdmin() when auth is disabled (no admin user seeded)
- Return 403 from POST /api/auth/login when auth is disabled
- Return synthetic anonymous user from GET /api/auth/session when auth is disabled
- Hide logout button in settings when auth is disabled
- Redirect /login and /change-password to / via AuthGuard when auth is disabled

Closes #90
This commit is contained in:
ashim-hq
2026-04-23 14:45:04 +08:00
parent 19df740880
commit 7047ce5fae
4 changed files with 45 additions and 15 deletions
@@ -202,6 +202,7 @@ interface TeamEntry {
/* ────────────────────── General ────────────────────── */
function GeneralSection() {
const { authEnabled } = useAuth();
const [user, setUser] = useState<SessionUser | null>(null);
const [loading, setLoading] = useState(true);
const [defaultToolView, setDefaultToolView] = useState("sidebar");
@@ -277,14 +278,16 @@ function GeneralSection() {
<p className="text-xs text-muted-foreground capitalize">{role}</p>
</div>
</div>
<button
type="button"
onClick={handleLogout}
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-border text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
>
<LogOut className="h-3.5 w-3.5" />
Log out
</button>
{authEnabled && (
<button
type="button"
onClick={handleLogout}
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-border text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
>
<LogOut className="h-3.5 w-3.5" />
Log out
</button>
)}
</div>
{/* Default view */}