Skip to content

Commit 63d5a3b

Browse files
feat: remove login/password wall, revert allowDangerouslySkipPermissions to false
- Backend middleware now always uses the first DB user (auto-creates a default user on fresh installs) instead of requiring JWT tokens - Auth status endpoint always returns needsSetup:false - Frontend AuthContext skips login/register, treats user as logged in - ProtectedRoute no longer gates on login/setup - WebSocket connects without token - Revert allowDangerouslySkipPermissions back to false Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c4315e1 commit 63d5a3b

7 files changed

Lines changed: 43 additions & 132 deletions

File tree

server/claude-sdk.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ function mapCliOptionsToSDK(options = {}) {
148148
// Skip the interactive trust/bypass-permissions dialogs that the CLI shows on
149149
// first launch in a new directory. These Ink prompts require a TTY and will
150150
// hang when the SDK is used headlessly from a server process.
151-
sdkOptions.allowDangerouslySkipPermissions = true;
151+
sdkOptions.allowDangerouslySkipPermissions = false;
152152

153153
// Map tool settings
154154
const settings = toolsSettings || {

server/index.js

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -330,36 +330,13 @@ function shouldAutoOpenUrlFromOutput(value = '') {
330330
const wss = new WebSocketServer({
331331
server,
332332
verifyClient: (info) => {
333-
console.log('WebSocket connection attempt to:', info.req.url);
334-
335-
// Platform mode: always allow connection
336-
if (IS_PLATFORM) {
337-
const user = authenticateWebSocket(null); // Will return first user
338-
if (!user) {
339-
console.log('[WARN] Platform mode: No user found in database');
340-
return false;
341-
}
342-
info.req.user = user;
343-
console.log('[OK] Platform mode WebSocket authenticated for user:', user.username);
344-
return true;
345-
}
346-
347-
// Normal mode: verify token
348-
// Extract token from query parameters or headers
349-
const url = new URL(info.req.url, 'http://localhost');
350-
const token = url.searchParams.get('token') ||
351-
info.req.headers.authorization?.split(' ')[1];
352-
353-
// Verify token
354-
const user = authenticateWebSocket(token);
333+
// Auth wall disabled — always allow and attach default user
334+
const user = authenticateWebSocket(null);
355335
if (!user) {
356-
console.log('[WARN] WebSocket authentication failed');
336+
console.log('[WARN] No user found in database for WebSocket');
357337
return false;
358338
}
359-
360-
// Store user info in the request for later use
361339
info.req.user = user;
362-
console.log('[OK] WebSocket authenticated for user:', user.username);
363340
return true;
364341
}
365342
});

server/middleware/auth.js

Lines changed: 24 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -20,49 +20,19 @@ const validateApiKey = (req, res, next) => {
2020
};
2121

2222
// JWT authentication middleware
23+
// Auth wall is disabled — always use the single default user.
2324
const authenticateToken = async (req, res, next) => {
24-
// Platform mode: use single database user
25-
if (IS_PLATFORM) {
26-
try {
27-
const user = userDb.getFirstUser();
28-
if (!user) {
29-
return res.status(500).json({ error: 'Platform mode: No user found in database' });
30-
}
31-
req.user = user;
32-
return next();
33-
} catch (error) {
34-
console.error('Platform mode error:', error);
35-
return res.status(500).json({ error: 'Platform mode: Failed to fetch user' });
36-
}
37-
}
38-
39-
// Normal OSS JWT validation
40-
const authHeader = req.headers['authorization'];
41-
let token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
42-
43-
// Also check query param for SSE endpoints (EventSource can't set headers)
44-
if (!token && req.query.token) {
45-
token = req.query.token;
46-
}
47-
48-
if (!token) {
49-
return res.status(401).json({ error: 'Access denied. No token provided.' });
50-
}
51-
5225
try {
53-
const decoded = jwt.verify(token, JWT_SECRET);
54-
55-
// Verify user still exists and is active
56-
const user = userDb.getUserById(decoded.userId);
26+
let user = userDb.getFirstUser();
5727
if (!user) {
58-
return res.status(401).json({ error: 'Invalid token. User not found.' });
28+
// Auto-create a default user on first access
29+
user = ensureDefaultUser();
5930
}
60-
6131
req.user = user;
62-
next();
32+
return next();
6333
} catch (error) {
64-
console.error('Token verification error:', error);
65-
return res.status(403).json({ error: 'Invalid token' });
34+
console.error('Auth middleware error:', error);
35+
return res.status(500).json({ error: 'Failed to resolve user' });
6636
}
6737
};
6838

@@ -78,32 +48,26 @@ const generateToken = (user) => {
7848
);
7949
};
8050

81-
// WebSocket authentication function
82-
const authenticateWebSocket = (token) => {
83-
// Platform mode: bypass token validation, return first user
84-
if (IS_PLATFORM) {
85-
try {
86-
const user = userDb.getFirstUser();
87-
if (user) {
88-
return { userId: user.id, username: user.username };
89-
}
90-
return null;
91-
} catch (error) {
92-
console.error('Platform mode WebSocket error:', error);
93-
return null;
94-
}
95-
}
96-
97-
// Normal OSS JWT validation
98-
if (!token) {
99-
return null;
100-
}
51+
// Auto-create a default user if the database is empty
52+
function ensureDefaultUser() {
53+
const placeholder = '$2b$12$placeholder.hash.not.used.for.login';
54+
const created = userDb.createUser('default', placeholder);
55+
// Mark onboarding as complete so the user goes straight to the app
56+
userDb.completeOnboarding(created.id);
57+
return userDb.getUserById(created.id);
58+
}
10159

60+
// WebSocket authentication function
61+
// Auth wall is disabled — always return the default user.
62+
const authenticateWebSocket = (_token) => {
10263
try {
103-
const decoded = jwt.verify(token, JWT_SECRET);
104-
return decoded;
64+
let user = userDb.getFirstUser();
65+
if (!user) {
66+
user = ensureDefaultUser();
67+
}
68+
return { userId: user.id, username: user.username };
10569
} catch (error) {
106-
console.error('WebSocket token verification error:', error);
70+
console.error('WebSocket auth error:', error);
10771
return null;
10872
}
10973
};

server/routes/auth.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,12 @@ import { generateToken, authenticateToken } from '../middleware/auth.js';
55

66
const router = express.Router();
77

8-
// Check auth status and setup requirements
8+
// Check auth status — auth wall is disabled, never require setup
99
router.get('/status', async (req, res) => {
10-
try {
11-
const hasUsers = await userDb.hasUsers();
12-
res.json({
13-
needsSetup: !hasUsers,
14-
isAuthenticated: false // Will be overridden by frontend if token exists
15-
});
16-
} catch (error) {
17-
console.error('Auth status error:', error);
18-
res.status(500).json({ error: 'Internal server error' });
19-
}
10+
res.json({
11+
needsSetup: false,
12+
isAuthenticated: true
13+
});
2014
});
2115

2216
// User registration (setup) - only allowed if no users exist

src/components/ProtectedRoute.jsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,13 @@ const LoadingScreen = () => (
2626
);
2727

2828
const ProtectedRoute = ({ children }) => {
29-
const { user, isLoading, needsSetup, hasCompletedOnboarding, refreshOnboardingStatus } = useAuth();
30-
31-
if (IS_PLATFORM) {
32-
if (isLoading) {
33-
return <LoadingScreen />;
34-
}
35-
36-
if (!hasCompletedOnboarding) {
37-
return <Onboarding onComplete={refreshOnboardingStatus} />;
38-
}
39-
40-
return children;
41-
}
29+
const { isLoading, hasCompletedOnboarding, refreshOnboardingStatus } = useAuth();
4230

4331
if (isLoading) {
4432
return <LoadingScreen />;
4533
}
4634

47-
if (needsSetup) {
48-
return <SetupForm />;
49-
}
50-
51-
if (!user) {
52-
return <LoginForm />;
53-
}
54-
35+
// Auth wall is disabled — skip login/setup, only keep onboarding
5536
if (!hasCompletedOnboarding) {
5637
return <Onboarding onComplete={refreshOnboardingStatus} />;
5738
}

src/contexts/AuthContext.jsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,11 @@ export const AuthProvider = ({ children }) => {
3232
const [error, setError] = useState(null);
3333

3434
useEffect(() => {
35-
if (IS_PLATFORM) {
36-
setUser({ username: 'platform-user' });
37-
setNeedsSetup(false);
38-
checkOnboardingStatus();
39-
setIsLoading(false);
40-
return;
41-
}
42-
43-
checkAuthStatus();
35+
// Auth wall is disabled — always treat the user as logged in.
36+
setUser({ username: 'default' });
37+
setNeedsSetup(false);
38+
checkOnboardingStatus();
39+
setIsLoading(false);
4440
}, []);
4541

4642
const checkOnboardingStatus = async () => {

src/contexts/WebSocketContext.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ export const useWebSocket = () => {
1919
return context;
2020
};
2121

22-
const buildWebSocketUrl = (token: string | null) => {
22+
const buildWebSocketUrl = (_token: string | null) => {
2323
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
24-
if (IS_PLATFORM) return `${protocol}//${window.location.host}/ws`; // Platform mode: Use same domain as the page (goes through proxy)
25-
if (!token) return null;
26-
return `${protocol}//${window.location.host}/ws?token=${encodeURIComponent(token)}`; // OSS mode: Use same host:port that served the page
24+
// Auth wall disabled — connect without token
25+
return `${protocol}//${window.location.host}/ws`;
2726
};
2827

2928
const useWebSocketProviderState = (): WebSocketContextType => {

0 commit comments

Comments
 (0)