feat: Implement bearer token validation in auth middleware (#186)

This commit is contained in:
samanhappy
2025-06-19 12:11:35 +08:00
committed by GitHub
parent 1e308ec4c5
commit d119be0f82
15 changed files with 248 additions and 56 deletions

View File

@@ -0,0 +1,102 @@
import { getApiUrl, getBasePath } from '../utils/runtime';
export interface SystemConfig {
routing?: {
enableGlobalRoute?: boolean;
enableGroupNameRoute?: boolean;
enableBearerAuth?: boolean;
bearerAuthKey?: string;
skipAuth?: boolean;
};
install?: {
pythonIndexUrl?: string;
npmRegistry?: string;
};
smartRouting?: {
enabled?: boolean;
dbUrl?: string;
openaiApiBaseUrl?: string;
openaiApiKey?: string;
openaiApiEmbeddingModel?: string;
};
}
export interface PublicConfigResponse {
success: boolean;
data?: {
skipAuth?: boolean;
};
message?: string;
}
export interface SystemConfigResponse {
success: boolean;
data?: {
systemConfig?: SystemConfig;
};
message?: string;
}
/**
* Get public configuration (skipAuth setting) without authentication
*/
export const getPublicConfig = async (): Promise<{ skipAuth: boolean }> => {
try {
const basePath = getBasePath();
const response = await fetch(`${basePath}/public-config`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
const data: PublicConfigResponse = await response.json();
return { skipAuth: data.data?.skipAuth === true };
}
return { skipAuth: false };
} catch (error) {
console.debug('Failed to get public config:', error);
return { skipAuth: false };
}
};
/**
* Get system configuration without authentication
* This function tries to get the system configuration first without auth,
* and if that fails (likely due to auth requirements), it returns null
*/
export const getSystemConfigPublic = async (): Promise<SystemConfig | null> => {
try {
const response = await fetch(getApiUrl('/settings'), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
const data: SystemConfigResponse = await response.json();
return data.data?.systemConfig || null;
}
return null;
} catch (error) {
console.debug('Failed to get system config without auth:', error);
return null;
}
};
/**
* Check if authentication should be skipped based on system configuration
*/
export const shouldSkipAuth = async (): Promise<boolean> => {
try {
const config = await getPublicConfig();
return config.skipAuth;
} catch (error) {
console.debug('Failed to check skipAuth setting:', error);
return false;
}
};

View File

@@ -15,13 +15,9 @@ export const fetchLogs = async (): Promise<LogEntry[]> => {
try {
// Get authentication token
const token = getToken();
if (!token) {
throw new Error('Authentication token not found. Please log in.');
}
const response = await fetch(getApiUrl('/logs'), {
headers: {
'x-auth-token': token,
'x-auth-token': token || '',
},
});
@@ -43,14 +39,10 @@ export const clearLogs = async (): Promise<void> => {
try {
// Get authentication token
const token = getToken();
if (!token) {
throw new Error('Authentication token not found. Please log in.');
}
const response = await fetch(getApiUrl('/logs'), {
method: 'DELETE',
headers: {
'x-auth-token': token,
'x-auth-token': token || '',
},
});
@@ -84,12 +76,6 @@ export const useLogs = () => {
// Get the authentication token
const token = getToken();
if (!token) {
setError(new Error('Authentication token not found. Please log in.'));
setLoading(false);
return;
}
// Connect to SSE endpoint with auth token in URL
eventSource = new EventSource(getApiUrl(`/logs/stream?token=${token}`));

View File

@@ -26,10 +26,6 @@ export const callTool = async (
): Promise<ToolCallResult> => {
try {
const token = getToken();
if (!token) {
throw new Error('Authentication token not found. Please log in.');
}
// Construct the URL with optional server parameter
const url = server ? `/tools/call/${server}` : '/tools/call';
@@ -37,7 +33,7 @@ export const callTool = async (
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-token': token,
'x-auth-token': token || '', // Include token for authentication
Authorization: `Bearer ${token}`, // Add bearer auth for MCP routing
},
body: JSON.stringify({
@@ -81,15 +77,11 @@ export const toggleTool = async (
): Promise<{ success: boolean; error?: string }> => {
try {
const token = getToken();
if (!token) {
throw new Error('Authentication token not found. Please log in.');
}
const response = await fetch(getApiUrl(`/servers/${serverName}/tools/${toolName}/toggle`), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-token': token,
'x-auth-token': token || '',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ enabled }),
@@ -123,18 +115,14 @@ export const updateToolDescription = async (
): Promise<{ success: boolean; error?: string }> => {
try {
const token = getToken();
if (!token) {
throw new Error('Authentication token not found. Please log in.');
}
const response = await fetch(
getApiUrl(`/servers/${serverName}/tools/${toolName}/description`),
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'x-auth-token': token,
Authorization: `Bearer ${token}`,
'x-auth-token': token || '',
Authorization: `Bearer ${token || ''}`,
},
body: JSON.stringify({ description }),
},