mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
feat: enhance authentication and session management
- Added NODE_ENV variable for development in docker-compose.override.yml.example. - Changed default NODE_ENV to development in Dockerfile. - Implemented fetchWsToken function to retrieve short-lived WebSocket tokens for secure authentication in TerminalPanel. - Updated connect function to use wsToken for WebSocket connections when API key is not available. - Introduced verifySession function to validate session status after login and on app load, ensuring session integrity. - Modified RootLayoutContent to verify session cookie validity and redirect to login if the session is invalid or expired. These changes improve the security and reliability of the authentication process.
This commit is contained in:
@@ -40,7 +40,7 @@ import {
|
||||
} from '@/config/terminal-themes';
|
||||
import { toast } from 'sonner';
|
||||
import { getElectronAPI } from '@/lib/electron';
|
||||
import { getApiKey } from '@/lib/http-api-client';
|
||||
import { getApiKey, getSessionToken } from '@/lib/http-api-client';
|
||||
|
||||
// Font size constraints
|
||||
const MIN_FONT_SIZE = 8;
|
||||
@@ -486,6 +486,40 @@ export function TerminalPanel({
|
||||
const serverUrl = import.meta.env.VITE_SERVER_URL || 'http://localhost:3008';
|
||||
const wsUrl = serverUrl.replace(/^http/, 'ws');
|
||||
|
||||
// Fetch a short-lived WebSocket token for secure authentication
|
||||
const fetchWsToken = useCallback(async (): Promise<string | null> => {
|
||||
try {
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const sessionToken = getSessionToken();
|
||||
if (sessionToken) {
|
||||
headers['X-Session-Token'] = sessionToken;
|
||||
}
|
||||
|
||||
const response = await fetch(`${serverUrl}/api/auth/token`, {
|
||||
headers,
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.warn('[Terminal] Failed to fetch wsToken:', response.status);
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success && data.token) {
|
||||
return data.token;
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('[Terminal] Error fetching wsToken:', error);
|
||||
return null;
|
||||
}
|
||||
}, [serverUrl]);
|
||||
|
||||
// Draggable - only the drag handle triggers drag
|
||||
const {
|
||||
attributes: dragAttributes,
|
||||
@@ -940,7 +974,7 @@ export function TerminalPanel({
|
||||
const terminal = xtermRef.current;
|
||||
if (!terminal) return;
|
||||
|
||||
const connect = () => {
|
||||
const connect = async () => {
|
||||
// Build WebSocket URL with auth params
|
||||
let url = `${wsUrl}/api/terminal/ws?sessionId=${sessionId}`;
|
||||
|
||||
@@ -948,8 +982,14 @@ export function TerminalPanel({
|
||||
const apiKey = getApiKey();
|
||||
if (apiKey) {
|
||||
url += `&apiKey=${encodeURIComponent(apiKey)}`;
|
||||
} else {
|
||||
// In web mode, fetch a short-lived wsToken for secure authentication
|
||||
const wsToken = await fetchWsToken();
|
||||
if (wsToken) {
|
||||
url += `&wsToken=${encodeURIComponent(wsToken)}`;
|
||||
}
|
||||
// Cookies are also sent automatically with same-origin WebSocket
|
||||
}
|
||||
// In web mode, cookies are sent automatically with same-origin WebSocket
|
||||
|
||||
// Add terminal password token if required
|
||||
if (authToken) {
|
||||
@@ -1164,7 +1204,7 @@ export function TerminalPanel({
|
||||
wsRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [sessionId, authToken, wsUrl, isTerminalReady]);
|
||||
}, [sessionId, authToken, wsUrl, isTerminalReady, fetchWsToken]);
|
||||
|
||||
// Handle resize with debouncing
|
||||
const handleResize = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user