diff --git a/.env.example b/.env.example
index 7cab2722..e6f09c92 100755
--- a/.env.example
+++ b/.env.example
@@ -9,4 +9,13 @@
#API server
PORT=3001
#Frontend port
-VITE_PORT=5173
\ No newline at end of file
+VITE_PORT=5173
+
+# =============================================================================
+# AUTHENTICATION CONFIGURATION
+# =============================================================================
+
+# Disable authentication entirely (default: false)
+# When set to true, all features become accessible without login
+# WARNING: Only use in secure, private environments
+AUTH_DISABLED=false
\ No newline at end of file
diff --git a/server/index.js b/server/index.js
index ca451337..97dcc2d5 100755
--- a/server/index.js
+++ b/server/index.js
@@ -44,7 +44,7 @@ import authRoutes from './routes/auth.js';
import mcpRoutes from './routes/mcp.js';
import cursorRoutes from './routes/cursor.js';
import { initializeDatabase } from './database/db.js';
-import { validateApiKey, authenticateToken, authenticateWebSocket } from './middleware/auth.js';
+import { validateApiKey, authenticateToken, authenticateWebSocket, isAuthDisabled } from './middleware/auth.js';
// File system watcher for projects folder
let projectsWatcher = null;
@@ -143,6 +143,17 @@ const wss = new WebSocketServer({
verifyClient: (info) => {
console.log('WebSocket connection attempt to:', info.req.url);
+ // Skip authentication if AUTH_DISABLED is true
+ if (isAuthDisabled()) {
+ // Store mock user info for compatibility
+ info.req.user = {
+ userId: 1,
+ username: 'admin'
+ };
+ console.log('✅ WebSocket authentication bypassed (AUTH_DISABLED=true)');
+ return true;
+ }
+
// Extract token from query parameters or headers
const url = new URL(info.req.url, 'http://localhost');
const token = url.searchParams.get('token') ||
diff --git a/server/middleware/auth.js b/server/middleware/auth.js
index 433c3293..001a4611 100644
--- a/server/middleware/auth.js
+++ b/server/middleware/auth.js
@@ -4,6 +4,11 @@ import { userDb } from '../database/db.js';
// Get JWT secret from environment or use default (for development)
const JWT_SECRET = process.env.JWT_SECRET || 'claude-ui-dev-secret-change-in-production';
+// Check if authentication is disabled
+const isAuthDisabled = () => {
+ return process.env.AUTH_DISABLED === 'true';
+};
+
// Optional API key middleware
const validateApiKey = (req, res, next) => {
// Skip API key validation if not configured
@@ -20,6 +25,16 @@ const validateApiKey = (req, res, next) => {
// JWT authentication middleware
const authenticateToken = async (req, res, next) => {
+ // Skip authentication if AUTH_DISABLED is true
+ if (isAuthDisabled()) {
+ // Create a mock user object for compatibility
+ req.user = {
+ id: 1,
+ username: 'admin'
+ };
+ return next();
+ }
+
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
@@ -58,6 +73,15 @@ const generateToken = (user) => {
// WebSocket authentication function
const authenticateWebSocket = (token) => {
+ // Skip authentication if AUTH_DISABLED is true
+ if (isAuthDisabled()) {
+ // Return a mock user object for compatibility
+ return {
+ userId: 1,
+ username: 'admin'
+ };
+ }
+
if (!token) {
return null;
}
@@ -76,5 +100,6 @@ export {
authenticateToken,
generateToken,
authenticateWebSocket,
+ isAuthDisabled,
JWT_SECRET
};
\ No newline at end of file
diff --git a/server/routes/auth.js b/server/routes/auth.js
index 82a7c0d8..9edf6c06 100644
--- a/server/routes/auth.js
+++ b/server/routes/auth.js
@@ -1,17 +1,28 @@
import express from 'express';
import bcrypt from 'bcrypt';
import { userDb, db } from '../database/db.js';
-import { generateToken, authenticateToken } from '../middleware/auth.js';
+import { generateToken, authenticateToken, isAuthDisabled } from '../middleware/auth.js';
const router = express.Router();
// Check auth status and setup requirements
router.get('/status', async (req, res) => {
try {
+ // If authentication is disabled, return authenticated status
+ if (isAuthDisabled()) {
+ res.json({
+ needsSetup: false,
+ isAuthenticated: true,
+ authDisabled: true
+ });
+ return;
+ }
+
const hasUsers = await userDb.hasUsers();
res.json({
needsSetup: !hasUsers,
- isAuthenticated: false // Will be overridden by frontend if token exists
+ isAuthenticated: false, // Will be overridden by frontend if token exists
+ authDisabled: false
});
} catch (error) {
console.error('Auth status error:', error);
@@ -120,8 +131,21 @@ router.post('/login', async (req, res) => {
// Get current user (protected route)
router.get('/user', authenticateToken, (req, res) => {
+ // If authentication is disabled, return mock user
+ if (isAuthDisabled()) {
+ res.json({
+ user: {
+ id: 1,
+ username: 'admin'
+ },
+ authDisabled: true
+ });
+ return;
+ }
+
res.json({
- user: req.user
+ user: req.user,
+ authDisabled: false
});
});
diff --git a/src/components/ProtectedRoute.jsx b/src/components/ProtectedRoute.jsx
index 88b404bb..c1e9d56c 100644
--- a/src/components/ProtectedRoute.jsx
+++ b/src/components/ProtectedRoute.jsx
@@ -24,12 +24,17 @@ const LoadingScreen = () => (
);
const ProtectedRoute = ({ children }) => {
- const { user, isLoading, needsSetup } = useAuth();
+ const { user, isLoading, needsSetup, authDisabled } = useAuth();
if (isLoading) {
return ;
}
+ // If authentication is disabled, allow access immediately
+ if (authDisabled) {
+ return children;
+ }
+
if (needsSetup) {
return ;
}
diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx
index 77acb6c6..98df7b40 100644
--- a/src/contexts/AuthContext.jsx
+++ b/src/contexts/AuthContext.jsx
@@ -9,6 +9,7 @@ const AuthContext = createContext({
logout: () => {},
isLoading: true,
needsSetup: false,
+ authDisabled: false,
error: null
});
@@ -25,6 +26,7 @@ export const AuthProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('auth-token'));
const [isLoading, setIsLoading] = useState(true);
const [needsSetup, setNeedsSetup] = useState(false);
+ const [authDisabled, setAuthDisabled] = useState(false);
const [error, setError] = useState(null);
// Check authentication status on mount
@@ -41,6 +43,17 @@ export const AuthProvider = ({ children }) => {
const statusResponse = await api.auth.status();
const statusData = await statusResponse.json();
+ // Handle authentication disabled mode
+ if (statusData.authDisabled) {
+ setAuthDisabled(true);
+ setUser({ id: 1, username: 'admin' });
+ setNeedsSetup(false);
+ // Create a dummy token for frontend compatibility
+ setToken('auth-disabled-token');
+ setIsLoading(false);
+ return;
+ }
+
if (statusData.needsSetup) {
setNeedsSetup(true);
setIsLoading(false);
@@ -147,6 +160,7 @@ export const AuthProvider = ({ children }) => {
logout,
isLoading,
needsSetup,
+ authDisabled,
error
};
diff --git a/src/utils/api.js b/src/utils/api.js
index 22978512..9f1ebf7c 100644
--- a/src/utils/api.js
+++ b/src/utils/api.js
@@ -1,6 +1,6 @@
// Utility function for authenticated API calls
export const authenticatedFetch = (url, options = {}) => {
- const token = localStorage.getItem('auth-token');
+ const token = localStorage.getItem('auth-token') || 'auth-disabled-token';
const defaultHeaders = {
'Content-Type': 'application/json',
diff --git a/src/utils/websocket.js b/src/utils/websocket.js
index f03fd002..9efc3fa7 100755
--- a/src/utils/websocket.js
+++ b/src/utils/websocket.js
@@ -21,13 +21,31 @@ export function useWebSocket() {
const connect = async () => {
try {
+ // Check if authentication is disabled by checking auth status
+ let authDisabled = false;
+ let token = localStorage.getItem('auth-token');
+
+ try {
+ const statusResponse = await fetch('/api/auth/status');
+ if (statusResponse.ok) {
+ const statusData = await statusResponse.json();
+ authDisabled = statusData.authDisabled;
+ }
+ } catch (error) {
+ console.warn('Could not check auth status:', error);
+ }
+
// Get authentication token
- const token = localStorage.getItem('auth-token');
- if (!token) {
+ if (!authDisabled && !token) {
console.warn('No authentication token found for WebSocket connection');
return;
}
+ // Use dummy token if authentication is disabled
+ if (authDisabled && !token) {
+ token = 'auth-disabled-token';
+ }
+
// Fetch server configuration to get the correct WebSocket URL
let wsBaseUrl;
try {